Webpack生成企业站静态页面 - ajax请求

news2024/12/24 8:31:55

         一些项目因需求不同,如需SEO或小项目,使用angular、react或vue就大材小用了。可以通过webpack、gulp这些构建工具,也能快速完成html页面开发,并且也能使用less/sass/styus等样式预编译功能,以及将js、html分模块、分组件进行开发。

        webpack生成企业站静态页面已经讲了三篇,本该结篇,但这几天又想到以前项目上使用过MVP模式开发,一部分通过后台渲染,一部分前端渲染;这样能减轻后端压力,也能提升开发速度,让前端在写静态页面时候就能完成页面数据渲染工作。有需求就有革新的动力,所以这篇将对之前功能再度升级改造。

        当然,这种方法把数据获取到客户端通过art-template模板引擎对数据进行渲染,实现是没问题;但是完全前端进行渲染,这样对SEO优化不太友好,若是不考虑此问题不大;若将head标签和导航等公共部分在服务端渲染,其他内容通过ajax请求在客户端渲染,也能满足SEO优化需求和减轻后端压力。

        另外art-template存在在webpack编译环境 和 浏览器的生产环境,两个环境语法标签会存在冲突,在webpack构建生成静态页面时候语法标签就会被解析掉,所以要重点注意一点,虽然这是可以通过art-templte配置来解决。

1.项目环境搭建 地址:Webpack生成企业站静态页面 - 项目搭建-CSDN博客

2. 组件化 地址:Webpack生成企业站静态页面 - 组件化-CSDN博客

3. 增加数据处理能力 地址:Webpack生成企业站静态页面 - 增强数据处理能力-CSDN博客

        该篇是和前三篇连贯讲解的,所以从后面开始看的,可能地方不太清楚或运行后报错等,出现这些问题可以翻看下前几篇,这里就不再从零开始讲解项目如何搭建和完善的了。

一、配置修改

        首先修改一下webpack.config.js,对外增加暴露art-template插件,在客户端浏览器中运行时,也能使用art-template。

1.1 暴露art-template

        这里大家注意的时,添加的是template-web.js,直接用require引用art-template会报错。

        入口entry位置添加artTemplate,生成artTemplate.js到dist/js目录中。如下图:

        在module的rules中,之前对外暴露jquery位置后面,再增加一个暴露art-template的loader。如下图:

        webapck.config.js代码如下:

const { resolve } = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const artTemplate = require('art-template');
const { entrys, staticHtmls, watchHtmls } = require('./static.config');
const htmlData = require('./html.data.json');

// 指定art-template模板路径
artTemplate.defaults.root = resolve(__dirname, './src');
// 指定模板名称
artTemplate.defaults.extname = '.html';

module.exports = {
    entry: {
        artTemplate: ['art-template/lib/template-web.js'],
        jquery: ['jquery'],
        ...entrys()
    },
    output: {
        filename: 'js/[name].bundle.js',      // 对入口名称进行命名,
        clean: true                           // 在生成文件之前清空 output 目录
    },
    module: {
        rules: [
            // MiniCssExtractPlugin.loader 提取CSS为独立文件
            // css-loader 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样。
            {
                test: /\.css$/i,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            // webpack 将 Less 编译为 CSS 的 loader。
            {
                test: /\.less$/i,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            },
            // 匹配图片资源,指定构建后存储位置和命名
            {
                test: /\.(png|jpg|jpeg|svg|gif)$/i,
                type: 'asset/resource',
                generator: {
                    filename: 'images/[name][ext]'
                }
            }, 
            // 匹配html页面,并提取内部资源文件
            {
                test: /\.html$/i,
                loader: "html-loader",
                exclude: /node_modules/,
                options: {
                    minimize: false,        // 不压缩html内容
                    preprocessor: (content, loaderContext) => {
                        // 正则达式
                        let regEx = /<datalist>\s*{\s*[\s\S]*?\s*}\s*<\/datalist>/gi,
                        // 区域html页面中json数据
                        htmlResult = content.match(regEx),
                        // 公共部分json数据
                        returnData = {...htmlData},
                        // 临时存储html中读取到的json数据
                        data = {};
                        // 判断htmlResult如果不为空,并且数组(match匹配到数据返回为数组格式)则转换字符串内容为json数据
                        if(null!=htmlResult&&Array.isArray(htmlResult)){
                            try {
                                // 去除datalist标签
                                htmlResult = htmlResult.map(item => {
                                    item = item.replace('<datalist>', '');
                                    item = item.replace('</datalist>', '');
                                    return JSON.parse(item);
                                });
                                // 合并数据
                                htmlResult.forEach(item => {
                                    Object.assign(data, item);
                                });
                                // 合并到htmlData数据集中
                                Object.assign(returnData, data);
                            } catch (error) {
                                console.error('html result:', error);
                            }
                            // 清除页面中数据
                            content = content.replace(regEx, '');
                        }
                        return artTemplate.compile(content)(returnData);
                    }
                }
            },
            // 将jquery暴露给全局对象(self、window 和 global)
            {
                test: require.resolve('jquery'),
                loader: "expose-loader",
                options: {
                    exposes: ["$", "jQuery"]
                }
            },
            // 对外暴露art-template
            {
                test: require.resolve('art-template/lib/template-web.js'),
                loader: "expose-loader",
                options: {
                    exposes: ["artTemplate"]
                }
            }
        ]
    },
    plugins: [
        ...staticHtmls(),
        // 提取css文件
        new MiniCssExtractPlugin({
            filename: 'css/[name]_bundle.css',      //输出文件
        }),
    ],
    resolve: {
        alias: {
            // 样式路径目录别名
            $css: resolve(__dirname, 'src/css')
        }
    },
    mode: 'production',
    devServer: {
        static: {
            // 指定服务运行目录
            directory: resolve(__dirname, 'dist')
        },
        watchFiles: [...watchHtmls()],
        compress: true,     //gzip压缩
        port: 3000,         //指定端口号
        open: true,         //服务启动后自动在浏览器打开
        hot: true           //开启热更
    }
}

1.2 html引入art-template

        要想在客户端浏览器中能调用art-template,还需要做最后一步,前篇中为了方便后期维护,将页面配置信息单独放在static.config.js文件中,需要在这把artTemplate放到chunks中,如下图:

        这样再执行webpack命令,artTemplate.bundle.js文件就成自动注入到所有html文件中。

        static.config.js文件代码如下:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 引用JS文件
const scripts = ["common", "index", "list", "article", "contact", "message"];
// 需要生成的静态页面
const htmls = [
    {name: "index.html", chunks: ['index']},
    {name: "list.html", chunks: ['list']},
    {name: "article.html", chunks: ['article']},
    {name: "contact.html", chunks: ['contact']},
    {name: "message.html", chunks: ['message']}
];
/**
 * 静态页面配置
 */
module.exports = {
    // 重组js入口文件
    entrys: () => {
        let params = {};
        scripts.forEach(name => {
            params[name] = resolve(__dirname, `./src/js/${name}.js`);
        })
        return params;
    },
    // 重组静态页面文件
    staticHtmls: () =>  htmls.map(item => {
        return new HtmlWebpackPlugin({
            inject: 'body',
            template: resolve(__dirname, `./src/${item.name}`),
            filename: item.name,
            chunks: ['jquery', 'artTemplate', 'common', ...item.chunks],
            minify: false
        });
    }),
    // 监听热更html页面
    watchHtmls: () =>  htmls.map(item => resolve(__dirname, `./src/${item.name}`))
}

二、创建mock数据

        第二步,使用mock来模拟后台接口,这里使用梦学谷的mock,地址:Easy Mock。这个平台使用太简单了,就不教大家怎么使用了。现在通过这个模拟我们需要的接口,如下图:

/inviteList 接口返回数据代码如下:

{
  "code": 200,
  "data": [{
      "title": "2015-03-17诚招",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    },
    {
      "title": "2014-03-12招聘",
      "datetime": "2014-03-12",
      "url": "javascript:;"
    },
    {
      "title": "2013-03-30诚招学生暑期工",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    }
  ],
  "message": "sccuess"
}

/bottomList 接口返回数据代码如下:

{
  "code": 200,
  "data": [{
      "title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    },
    {
      "title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    },
    {
      "title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    },
    {
      "title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮",
      "datetime": "2014-10-2",
      "url": "javascript:;"
    }
  ],
  "message": "success"
}

/firstList 接口返回数据代码如下:

{
  "code": 200,
  "data": [{
      "title": "望玉岛标题",
      "description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ",
      "thumb": "images/index_09.jpg",
      "url": "javascript:;"
    },
    {
      "title": "望玉岛标题",
      "description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ",
      "thumb": "images/index_10.jpg",
      "url": "javascript:;"
    },
    {
      "title": "望玉岛标题",
      "description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ",
      "thumb": "images/index_11.jpg",
      "url": "javascript:;"
    }
  ],
  "message": "success"
}

        由于这里是项目演示而模拟的数据,所以好个区域是使用同一份接口数据,就不一一造模拟数据了。

三、ajax封装

        这里主要是演示如果通过ajax请求获取数据,再将数据渲染到页面,所以就简单封装并模拟。如果有朋友希望使用axios或其他相关请求工具,可以自行研究。

        由于ajax请求所有页面都需要使用到,所以这里将封装内容放到之前创建的common.js文件中,代码如下:

import '$css/common.less';

(function(){
    // ajax请求地址
    const ajaxBaseUrl = "https://mock.mengxuegu.com/mock/${mock的Project ID}/webpack_ajax_pro";

    // 配置art-template语法模板
    artTemplate.defaults.rules[1].test = /{%([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*%}/;

    /**
     * ajax 请求
     * @param {*} url 
     * @param {*} params 
     * @param {*} type 
     */
    function ajaxRequest(url, params, type){
        return new Promise(function(resolve, reject){
            $.ajax({
                url: ajaxBaseUrl + url,
                type: type,
                data: params,
                success: function(res){
                    resolve(res);
                },
                error: function(e){
                    reject(e);
                }
            });
        });
    }

    /**
     * 封装Get请求
     * @param {*} id 
     * @param {*} url 
     * @param {*} params 
     */
    $.fn.requestGetRender = function(id, url, params){
        let that = this;
        ajaxRequest(url, params, 'get').then(function(res){
            let html = artTemplate(id, res);
            $(that).html(html);
        }).catch(function(msg){
            console.error(msg);
        });
    }

    /**
     * 封装POST请求
     * @param {*} id 
     * @param {*} url 
     * @param {*} params 
     */
    $.fn.requestPostRender = function(id, url, params){
        let that = this;
        ajaxRequest(url, params, 'post').then(function(res){
            let html = artTemplate(id, res);
            $(that).html(html);
        }).catch(function(msg){
            console.error(msg);
        });
    }
})();

        代码里需要注意的是art-template引擎的语法规则修改,因为<% %>和{{  }}在webpack中默认使用,如果客户端代码中不修改语法规则,webpack构建时含有<% 和 {{  的语法内容都会被匹配到和清空,这样到客户端时就获取不到任何模板内容了。

        客户端修改为开始标签为{% 和结束标签为%},代码如下:

// 配置art-template语法模板
artTemplate.defaults.rules[1].test = /{%([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*%}/;

        另外ajax这里就不细讲了,如不了解它的,可以去看下相关文档。

        art-template在expose-loader中对外暴露名称已修改为artTemplate,所以在成功获取到数据后,可以直接使用artTemplate来渲染数据。通过artTemplate渲染后得到新的html内容,直接通过jquery将其追加到DOM中。

        另外有些人可能不清楚$.fn是什么,不了解jquery朋友可以查看下相关手册,了解其用法和作用。

四、语法标签修改

        以上工作做完后,我们可以修改index.html中数据了。将之前不管使用{{set inviteList = ... }},还是<datalist>标签引用的JSON数据,把需要通过接口获取的数据可以全部删除掉。第二步将客户端浏览器要使用到的模板信息,独立出来在template中创建indexTpl.html,单独存放。如下图:

        indexTpl.html模板代码如下:

<script type="text/html" id="tpl_top">
{%each data as item%}
<dl class="b_list">
    <dt>
        <a href="#" target="_blank">
            <img src="{%item.thumb%}" alt="09" />
        </a>
    </dt>
    <dd>
        <h2><a href="{%item.url%}" target="_blank">{%item.title%}</a></h2>
        <span>
            {%item.description%}
            <a href="{%item.url%}" target="_blank">[详细情况]</a>
        </span>
    </dd>
</dl>
{%/each%}
</script>

<script type="text/html" id="tpl_bottom">
{%each data as item %}
<li>
    <span>{% item.datetime %}</span>
    <a href="{% item.url %}" target="_blank">{% item.title %}</a>
</li>
{%/each%}
</script>

        对页面代码分析可知,几个区域主要分为这两种模板数据结构,所以结构一样的可以共用一个模板。另外模板里的语法开始和结束标签也修改为common.js中修改的语法规则,如果未修改客户端浏览器运行时可能渲染为空。

        现在index.html文件中代码如下:

<!-- 修改当前页面对应标题 -->
{{$data.navIndexName = "首页"}}

{{extend './template/layout.html'}}

<datalist>
{
    "title": "首页"
}    
</datalist>

{{block 'content'}}
<!-- mainer_wrapper -->
<div id="mainer_wrapper">
	<!-- main -->
	<div class="main-container">
        <div class="clear"></div>

        <!-- 广告 START -->
        <div class="box_gg">
        	<a href="#" target="_blank">
                <img src="images/index_08.jpg" alt="banner" />
            </a>
        </div>
        <!-- 广告 END -->
        
        <!-- box_content 最新活动 START -->
    	<div class="box_content wd490 fl">
        	<div class="title"><a href="#" class="more">MORE &gt;&gt;</a>最新活动</div>
            <div class="content">
                <div id="newsBox"></div>
                <div class="clear"></div>
            </div>
        </div>
        <!-- /box_content 最新活动 END -->
        
        <!-- box_content 旅游项目 START -->
    	<div class="box_content wd490 fl mg_l15">
        	<div class="title"><a href="#" class="more">MORE &gt;&gt;</a>旅游项目</div>
            <div class="content">
				<div id="travelBox"></div>
                <div class="clear"></div>
            </div>
        </div>
        <!-- /box_content 旅游项目 END -->
        
        <!-- box_content 旅游咨询 START -->
    	<div class="box_content fl" style="width:360px;">
        	<div class="title"><a href="#" class="more">MORE &gt;&gt;</a>旅游咨询</div>
            <div class="content">
				<ul class="box_list" id="consultBox"></ul>
            </div>
        </div>
        <!-- /box_content 旅游咨询 END -->
        <!-- box_content 贵宾服务 START -->
    	<div class="box_content fl mg_l15" style="width:360px;">
        	<div class="title"><a href="#" class="more">MORE &gt;&gt;</a>贵宾服务</div>
            <div class="content">
				<ul class="box_list" id="serviceBox"></ul>
            </div>
        </div>
        <!-- /box_content 贵宾服务 END -->
        <!-- box_content 招聘信息 START -->
    	<div class="box_content fl mg_l15" style="width:240px;">
        	<div class="title"><a href="#" class="more">MORE &gt;&gt;</a>招聘信息</div>
            <div class="content">
				<ul class="box_list" id="invitBox"></ul>
            </div>
        </div>
        <!-- /box_content 招聘信息 END -->
        <div class="clear"></div>
    </div>
    <!-- /main -->
</div>
<!-- /mainer_wrapper -->

{{include './template/indexTpl.html'}}
{{/block}}

        这里将独立出去的art-template渲染需要的模板文件,再通过include引入进来。其他不需要的数据也清理干净,页面显示更为整洁了。

        此时执行npx webpack serve命令,发现页面数据为空,这是因为还未写调用接口数据的代码,如下图:

        html代码除了将多余json数据、模板代码作了处理,还需要添加相关ID,这在后面客户端渲染页面数据会有用的。如下图:

五、页面渲染

        由于是首页数据渲染,之前也创建了index.html的入口文件,所以调用接口的功能就写在index.js文件中,代码如下:

import '$css/index.less';

$(function(){
    // 最新活动
    $('#newsBox').requestGetRender('tpl_top', '/firstList', {});
    // 旅游项目
    $('#travelBox').requestGetRender('tpl_top', '/firstList', {});
    // 旅游咨询
    $('#consultBox').requestGetRender('tpl_bottom', '/bottomList', {});
    // 贵宾服务
    $('#serviceBox').requestGetRender('tpl_bottom', '/bottomList', {});
    // 招聘信息
    $('#invitBox').requestGetRender('tpl_bottom', '/inviteList', {});
});

        如果devServer打开了hot功能,在index.js中添加上面代码后,页面数据已显示出来了。如下图:

        这里写的比较简单,也是按个人思路整理的,希望对大家有帮助。不管用什么方法,只要能满足项目需求,达到预期效果,用什么方式实现并不重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1553490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WhatsApp防封指南:封号原因与解封方法

相信各位小伙伴已经发现&#xff0c;WhatsApp新一轮风控已经启动&#xff0c;不少小伙伴已经受到封号潮的冲击。无论是老号还是新号都难以幸免。为了防止WhatsApp客户数据和聊天信息的丢失&#xff0c;针对封号的防封攻略请收藏&#xff01; 一、WhatsApp被封的8个原因 1、被过…

单片机之串口通信

目录 串口介绍 通信的基本概念 并行通信和串行通信 同步通信和异步通信 串行异步通信方式 串行同步通信方式 通信协议 单片机常见通信接口 串行通信三种模式 串口参数 传输速度 ​串口的连接 电平标准 串行口的组成 串口数据缓冲寄存器 串行口控制寄存器 串口…

(免费分享)基于springboot,vue付费自习室系统带论文

在当今数字化时代&#xff0c;高效、便捷的管理系统成为了各行各业不可或缺的工具。特别是在教育服务领域&#xff0c;自习室作为学生和在职人员重要的学习场所&#xff0c;其预约和管理需求日益增长。为了满足这一市场需求&#xff0c;本文开发了这款基于微信小程序的付费自习…

springboot实战---5.最简单最高效的后台管理系统开发

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;SpringBoot &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&…

骗子查询系统源码

源码简介 小权云黑管理系统 V1.0 功能如下&#xff1a; 1.添加骗子&#xff0c;查询骗子 2.可添加团队后台方便审核用 3.在线反馈留言系统 4.前台提交骗子&#xff0c;后台需要审核才能过 5.后台使用光年UI界面 6.新增导航列表&#xff0c;可给网站添加导航友链 7.可添加云黑类…

stm32之GPIO寄存器

文章目录 1 背景2 GPIO寄存器的类型2.1 端口配置寄存器2.2 设置/清除寄存器和位清除寄存器 3 总结 1 背景 C51单片机在进行数据的输入输出时&#xff0c;是直接操作与外部引脚关联的内部寄存器&#xff0c;例如&#xff0c;当设置P2_1为0时&#xff0c;就是将外部引脚的P21引脚…

常用的8个应用和中间件的Docker运行示例

文章目录 1、Docker Web 管理工具 portainer2、在线代码编辑器 Code Server3、MySQL4、Redis5、Nginx6、PostgreSQL7、媒体管理工具 Dim8、Gitlab 1、Docker Web 管理工具 portainer Portainer 是一个轻量级的管理 UI &#xff0c;可让你轻松管理不同的 Docker 环境&#xff0…

map与set容器常见操作详解(含示例代码及注意事项)

&#x1f389;个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名乐于分享在学习道路上收获的大二在校生 &#x1f648;个人主页&#x1f389;&#xff1a;GOTXX &#x1f43c;个人WeChat&#xff1a;ILXOXVJE &#x1f43c;本文由GOTXX原创&#xff0c;首发CSDN&…

【案例·增】一条insert语句批量插入多条记录

问题描述&#xff1a; 往MySQL中的数据库表中批量插入多条记录&#xff0c;可以使用 SQL 中的 ((), ()…)来处理 案例&#xff1a; INSERT INTO items(name,city,price,number,picture) VALUES(耐克运动鞋,广州,500,1000,003.jpg),(耐克运动鞋2,广州2,500,1000,002.jpg);规则…

C语言--编译和链接

1.翻译环境 计算机能够执行二进制指令&#xff0c;我们的电脑不会直接执行C语言代码&#xff0c;编译器把代码转换成二进制的指令&#xff1b; 我们在VS上面写下printf("hello world");这行代码的时候&#xff0c;经过翻译环境&#xff0c;生成可执行的exe文件&…

2. Java基本语法

文章目录 2. Java基本语法2.1 关键字保留字2.1.1 关键字2.1.2 保留字2.1.3 标识符2.1.4 Java中的名称命名规范 2.2 变量2.2.1 分类2.2.2 整型变量2.2.3 浮点型2.2.4 字符型 char2.2.5 Unicode编码2.2.6 UTF-82.2.7 boolean类型 2.3 基本数据类型转换2.3.1 自动类型转换2.2.2 强…

【详细讲解PostCSS如何安装和使用】

&#x1f308;个人主页:程序员不想敲代码啊&#x1f308; &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家&#x1f3c6; &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d; 希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提…

macOS Ventura 13.6.6 (22G630) Boot ISO 原版可引导镜像下载

macOS Ventura 13.6.6 (22G630) Boot ISO 原版可引导镜像下载 3 月 26 日凌晨&#xff0c;macOS Sonoma 14.4.1 发布&#xff0c;同时带来了 macOS Ventru 13.6.6 安全更新。 macOS Ventura 13.6 及更新版本&#xff0c;如无特殊说明皆为安全更新&#xff0c;不再赘述。 本站…

MoneyPrinterTurbo搭建详细流程(Linux)及常见问题

先附上链接: MoneyPrinterTurbohttps://github.com/harry0703/MoneyPrinterTurboMoneyPrinterTurbo是一款合成视频的软件。 你只需要提供一个主题或者关键字,就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐,然后合成一个高清的短视频。 接下来讲解详细的搭…

vue3 渲染一个后端返回的图片字段渲染、table表格内放置图片

一、后端直接返回图片url 当图片字段接口直接返回的是图片url&#xff0c;可以直接放到img标签上 <img v-if"thumbLoader" class"r-image-loader-thumb" :src"resUrl" /> 二、当图片字段接口直接返回的是图片Id 那么就需要去拼一下图片…

SQL-CRUD-2数据库实验

目录 第一关任务描述 相关知识 插入完整内容的行 插入选定内容的行 编程要求 测试说明 第一关代码 第二关任务描述 相关知识 删除表中的指定行 删除表中的所有行 编程要求 测试说明 第二关代码 第三关任务描述 相关知识 更新表中的指定行 编程要求 测试说明…

鸿蒙:搜索框组件Search

搜索框组件&#xff0c;适用于浏览器的搜索内容输入框等应用场景。 说明 该组件从API Version 8开始支持 子组件 无 接口 Search(options?: { value?: string, placeholder?: string, icon?: string, controller?: SearchController }) 参数: 参数名 参数类型 必…

61、服务攻防——中间件安全CVE复现K8sDockerJettyWebsphere

文章目录 K8sDockerWebSphere K8s k8s&#xff1a;简单来说&#xff0c;跟docker一样&#xff0c;是个容器系统。 k8s对外攻击面总结 常见漏洞&#xff1a;未授权访问、提权漏洞 Docker docker逃逸&#xff1a;1、由内核漏洞引起&#xff1b;2、由Docker软件设计引起&#x…

【Git】git status中文文件名编码问题解决

git status中文文件名编码问题解决 一、问题二、解决方法 一、问题 在默认配置下&#xff0c;查看文件状态&#xff0c;中文文件名在工作区状态输出&#xff0c;中文名不能正确显示&#xff0c;而是显示为八进制的字符编码。 PS D:\VS代码\Widget> git status On branch m…

TOP100-回溯(二)

4.39. 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限制…