• Vue基础(复习)


    序:

    ​ 声明式渲染(最基础用法)–>组件系统(更丰富的用法)–>客户端路由(单页面应用,局部更新,历史回退功能)–>集中式管理状态(功能比较大,用了大量业务数据,为了方便管理vuex)–>项目构建(前后端分离,前端 独立开发,测试,部署,上线)

    mvc和mvvm

    1. mvc(后端思想)

    img

    2. mvvm(前端思想)

    ①、界面(View):HTML + CSS,且HTML还是增强版;

    ②、数据模型(Model):保存页面所需要的变量和函数 的对象;

    ③、视图模型(ViewModel):自动保持页面与内存数据同步的特殊对象。

    Vue的绑定原理(访问器属性 + 虚拟DOM树):

    一切Vue的开始都是从new Vue(),首先创建Vue类型的对象,将模型对象的内容包裹进Vue类型的对象中托管。

    a. 将原data隐姓埋名。并为data中每个变量自动请保镖(定义访问器属性getset);

    b. 打散引入的methods,让methods中的所有方法,都直接隶属于new Vue();

    c. 结果methods中的方法和为data中变量请的保镖就平级了,所以对象中平级的方法,想使用平级的访问器属性,就必须加this

    虚拟dom树:

    **虚拟dom树:**Vue扫描HTML页面获取仅保存可能发生变化的元素,得到简版的dom树;

    **何时创建:**new Vue()创建完对象后,自动扫描el: "#app"所指向的页面区域,在扫描过程中仅找出可能发生变化的元素,保存在一个新创建的虚拟dom树集合中;

    优点:

    a. 内容少:仅包含可能发生变化的元素,其余元素都不包含;

    b. 遍历快: 可快速找到受影响的元素;

    c. 渲染效率高: 只更新受影响的元素;

    d.已经封装了DOM增删改查操作,避免了打量重复的编码。

    修改变量后,Vue变化过程:

    修改变量其实是修改变量的访问器属性;

    修改访问器属性就会触发set()

    触发set(),就会自动执行set中的通知函数

    通知发给虚拟DOM树,告知那个变量的值发生了变化

    虚拟DOM树遍历自己内部的元素,只找到受本次变化影响的元素

    虚拟DOM树用已经封装好的DOM操作,只能更新页面中受影响的元素

    img

    简单指令

    1.v-cloak

    {{ msg }}
    • 1

    解决插值表达式的闪烁问题(页面刷新加载时出现的{{}})

    **注:**配合样式[v-cloak]display: none

    • 不解析标签
    • 只替换占位符,不覆盖原本内容

    2. v-text

    • 1
    • 默认没有闪烁问题
    • 覆盖元素中的内容
    • 不解析标签

    3.v-html

    • 1
    • 覆盖元素中内容
    • 会解析标签

    4.v-bind:(简写为‘:’)

    • 1

    绑定属性,数据单向绑定
    不加v-bind时,则认为’mytitle’为字符串,加上后则为变量或者合法js表达式

    三种绑定方法:

    1. 对象型 ‘{red:isred}’
    2. 三元型 ‘isred?“red”:“blue”’
    3. 数组型 '[{red:“isred”},{blue:“isblue”}]

    5.v-on:(简写‘@’)

    绑定事件

    点击:v-on:click = ‘方法名’ -------@click
    悬浮:v-on:mouseover = ‘方法名’ -------@mouseover
    离开:v-on:mouseout = ‘方法名’ -------@mouseout
    移动端 touchstart、touchend、touchmove…

    6.事件修饰符

    写在绑定事件名后:如 @click.stop

    • .stop:阻止冒泡
    • .prevent:阻止默认行为,提交事件不再重载页面
    • .capture:改为事件捕获
    • .self:事件在该元素本身触发时 触发回调
    • .once:只触发一次

    7.数据双向绑定指令 v-model

    
    
    • 1

    **注:**仅适用于表单元素

    8.v-for循环遍历

    • 1
    • key的值只能为 srting 或者 number类型
    • 使用绑定属性的形式指定key的值

    9.v-if、v-show

    • 1
    • 2
    • v-if 删除或创建元素
    • 有较高切换性能消耗,若元素需频繁切换,不适用v-if
    • v-show 隐藏或显示元素,等同切换 display值 => ‘none’
    • 有较高初始渲染消耗,若元素并不需要显示,不适用v-show
    • v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好一

    附:为什么避免 v-if 和 v-for 在一起用

    当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,通过 v-if 移动到容器元素,不会 再重复遍历列表中的每个值。取而代之的是,我们只检查它一次,且不会在 v-if 为否的时候运 算 v-f

    过滤器

    用作常见的文本格式化,可使用在:mustache插值 和 v-bind表达式;
    {{ msg | 过滤器名称(传参)}} ===> 先通过过滤器对数据进行处理后,在返回给name显示;
    ‘|’ => 管道符;
    过滤器调用 采用就近原则,当全局过滤器与私有过滤器重名,则优先采用私有过滤器;

    1.全局过滤器

    所有的vm实例都共享
    定义:Vue.filter(‘过滤器名称’, function(msg,arg){ //数据处理 })
    定义位置:在vm实例外面定义
    参数:

    • msg:管道符前面的数据
    • arg:接收的参数

    2.私有过滤器(局部)

    定义位置:vm内部,filters: {},与methods同级
    定义:filters:{ 过滤器名称(管道符前数据,接受的参数) {}}
    《=========》
    (小知识):string.padStart(2, ‘0’) 用来给个位数补零

    自定义指令

    自定义指令名以 ‘v-’ 开头

    1.全局

    定义:Vue.directive(‘自定义指令吗’, {})
    参数1:指令名称 定义时,自定义指令名不加 ‘v-’ 前缀,调用时需加上
    参数2:对象,对象中有一些指令相关函数,在特定阶段执行相应操作
    例:焦点事件

    
    
    • 1
    Vue.directive('focus', {
    每个函数第一个参数为 el,表示被绑定指令的元素,此时可使用原生的方法
    	bind:function(el){ //指令绑定到元素上时执行,仅一次
    		el.focus() //元素还未插入到DOM 中,不生效
    		//多为与样式相关的操作
    	}
    	inserted:function(el){ //元素插入到 DOM 中的时候执行,仅一次
    		el.focus() //元素已经插入到DOM 中,生效
    		//多为与js相关的操作
    	}
    	updated:function(){ //VNode 更新时执行,可能触发多次
    
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    函数相关参数

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v1uT6JV9-1659282675374)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220523152632331.png)]

    2.私有

    定义位置:在vm实例内定义,与 methods 同级
    定义:directives: {'自定义指令名': {相关函数}}
    函数简写(全局/私有):

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8VNnPiQj-1659282675375)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220523152736818.png)]

    实例生命周期

    生命周期函数与 methods 同级

    **html:**
    

    {{ msg }}

    **js:** var vm = new Vue({ el: '#app', data: { msg: 'ok' }, methods: { show() { console.log('执行了show方法') } }, })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    ***创建期间的生命周期函数***
    beforCreate(){ //实例被完全创建之前执行
    	//在这个生命周期内,data 和 methods 中的数据未初始化
    	console.log(this.msg); //undefined
    	this.show()  //报错,this.show() is not a function
    }
    
    created() {
    	//在这个生命周期内,data 和 methods 中的数据初始化完成
    	//可调用 methods 中的方法和操作 data 中的数据
    	console.log(msg) //ok
    	this.show() //执行了show方法
    }
    
    beforeMount() { //模板在内存中编译完成,还未渲染到页面中
    	//在这个生命周期内,页面中的元素未被替换,还是原来写好的模板字符串
    	console.log(document.getElementById('p').innerHtml) //{{ msg }}
    }
    
    mounted() { 实例创建期间的最后一个生命周期函数
    	//将编译好的内存中的模板挂在到页面中
    	console.log(document.getElementById('p').innerHtml) //ok
    }
    
    ***组件运行阶段的生命周期函数***
    beforeUpdate() {  //界面还未被更新,但数据已被更新
    	//组件/数据被改变时触发
    	//例:当点击input按钮时:
    	console.log(document.getElementById('p').innerHtml) // ok ===>页面未更新
    	console.log(this.msg) // No ===>数据已经改变
    }
    updated(){ //页面与数据都已更新
    	//组件/数据被改变时触发
    	//例:当点击input按钮时:
    	console.log(document.getElementById('p').innerHtml) // No ===>页面已更新
    	console.log(this.msg) // No ===>数据已经改变
    }
    
    ***组件销毁阶段的生命周期函数***
    beforeDestroy() {
    	//还未执行销毁过程
    }
    destroyed() {
    	//组件被完全销毁,此时组件中所有的数据、方法、指令、过滤器等 都不可用
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    动画

    将需要动画的元素使用 标签包裹
    样式:
    v-enter, v-leave-to {} ——>进入和离开
    v-enter-active, v-leave-active {} ——>中间过程动画

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ZPkq5Xs-1659282675376)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220523152906898.png)]

    点击查看:vue动画详细介绍

    组件

    定义:拆分vue实例的代码量,不同组件划分不同功能模块,需要时调用

    1.全局创建

    //引用组件
    ****Vue.component('组件名称', { //创建的组件模板对象 })**** Vue.component('myCom1', { template: '#tmp1' }) 注: 1.若组件名称使用驼峰命名时,调用时用小写,并且单词之间‘-’连接,若未使用驼峰命名,则直接引用组件名; 2.常见的模板对象必须有一个根元素包裹
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.局部创建(私有)

    实例内部,与methods同级

    components: { //定义实例内部私有组件
    	组件名: {
    		template: ''
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.组件中 data、methods

    Vue.compontent('com1', {
    	template: '',
    	data: function() {
    		return {}
    		//组件中的 data 为一个函数,且必须 return 一个对象
    	},
    	methods: {}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4.组件切换

    
    
    • 1

    5.组件传值

    5.1.父传子

    var vm = new Vue({ el: '#app', data: { msg: '父组件数据' }, methods: { show() { console.log('调用了父组件方法') } }, //定义子组件: components: { com1: { template: '#son', props: ['parentmsg'], //将父组件传递的parentmsg属性在props数组中定义,然后才能使用,但是不做更改 methods: { parentfunc() { this.$emit(‘func’) } } } } }) 总结: (1)在父组件调用子组件的地方,绑定一个自定义属性,属性值为要传递的数据,在子组件定义的地方通过props数组接收 (2)若调用父组件的方法,在父组件调用子组件的地方,使用事件绑定方式,自定义事件名,在子组件的方法中,通过this.$emit('方法名')调用父组件方法
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    5.2.子传父

    在子组件调用的地方,添加自定义事件,这个事件由父组件执行,在子组件中,使用this.$emit('自定义事件名称','需要传递的参数')来讲数据传递给父组件

    获取DOM元素及组件

    使用ref

    来找我啊

    var com = { template: '#son', data() { return { msg: 'son msg' } }, methods: { show() { console.log('这里是子组件的方法') } } } var vm = new Vue({ el: '#app', data: {}, methods: { getElement() { console.log(this.$refs.content.innerText); //来找我啊 console.log(this.$refs.sonContent.msg); //son msg this.$refs.sonContent.show(); //这里是子组件的方法 } }, components: { com } })
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里,通过给元素添加 ref 属性,使用this.$refs.ref属性名.innerText去获取元素的内容,避免了DOM的操作,也可以给子组件添加 ref 属性,同样使用 this.$refs.ref属性名.变量名/方法名 去获取子组件中的变量或者方法。

    路由

    1、vue-router

    var routerObj = new VueRouter({ //创建路由实例
    	routes: [ //路由匹配规则
    		{
    			path: '/...', //路径
    			component: 组件模板对象, //组件模板对象,不能为组件引用名称
    		},
    		{path: '', component: },
    		...
    	]
    })
    
    var vm = new Vue({
    	el: '#app',
    	data: {},
    	methods: {},
    	router: routerObj, //将路由规则对象注册到vm实例上
    })
    
    在页面中使用``来显示组件内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、router-link

    (1)、默认渲染为一个 a 标签
    (2)、tag属性:将router-link转为指定的元素

    登录 //此时渲染为 span 标签
    注册 //此时为默认渲染 a 标签
    
    • 1
    • 2

    3、路由 redirect 重定向

    routes: [
    	{path: '/', redirect: '/login'} //如果为根路径,则重定向到登录页路径
    ]
    
    • 1
    • 2
    • 3

    注: 此处重定向不同于 node 中的重定向

    跳转按钮的样式修改

    • 在使用时,标签会有一个默认的类名:router-link-active,可以通过这个类名在修改被选中的标签的样式
    • 可以在router的构造函数中,通过linkActiveClass属性来修改默认的类名

    4、路由传参之 — query

    4.1、获取参数: this.$route.query
    4.2、传参:

    在跳转按钮处定义点击事件,在点击事件中:
    this.$router.push({
    	path: '跳转的路径',
    	query: {
    		//传递的参数
    		id: '01',
    		neme: '哈哈哈'
    	}
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    **注:**在标签中,添加点击事件时,需要写成 @click.native

    4.3.使用params时,在路由实例中的匹配规则内,需要加上 ‘name’ 属性,值为路径名称(不加‘/’)
    **注:**params必须使用name来引入

    4.4、路由嵌套 — children

    在某个路由跳转的组件中,内部需要使用路由时,在路由匹配规则中格式应为:

    登录
    routes: [
     {
     	path: '/account', 
     	component: account,
     	children: [
     		path: 'login', //此时路径不加'/'
     		component: login
     	]
     } //如果为根路径,则重定向到登录页路径
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5、路由命名视图

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IEiVCFHN-1659282675377)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220523154346943.png)]

    图中布局分为头部(header),左侧边栏(leftBox),内容(mainBox)三个组件组成

    路由匹配规则 routes: [ { path: '/', components: { 'default': header, 'left': leftBox, 'main': mainBox } }, ]
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    watch 监听

    1、监听文本框内容变化

    watch:{} :与 methods 同级,可以监视 data 中指定的数据的变化,然后触发 watch 中对应的 function 函数

    data:{ txtValue: '' }, watch: { txtValue: function(newVal,oldVal) { //当输入框中值改变时,触发该事件 //方法中可以包含newVal、oldVal两个参数,代表改变之前的值后改变之后的值 } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2、监听路由变化

    watch: {
    	'$route.path': function(newVal,oldVal) {
    		//当输入框中值改变时,触发该事件
    		//方法中可以包含newVal、oldVal两个参数,代表改变之前的值后改变之后的值
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3、computed 计算属性

    computed :{} :与 methods 同级,可以定义一些属性,为计算属性,其本质是一个方法,只不过在使用这些计算属性的时候,是将其名称直接当作属性来使用,并不会把计算属性当作方法去调用

    data: { firstName: '' }, computed: { lastName: function() { return this.firstName } } 【注】: 1、计算属性在调用的时候不加 () 调用,直接当作普通属性使用 2、计算属性的 function 内部所用到的任何 data 中的数据发生变化,就会重新计算该计算属性中的值 3、计算属性的求值结果会被缓存,方便下次直接使用,如果计算属性的方法中所依赖的任何数据都没有发生变化,则不会重新对计算属性求值
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    修饰符

    1.Lazy

    Lazy 修饰符的作用是,改变输入框的值时value不会改变,当光标离开输入框时,v-model绑定的值value才会改变。

    
    
    {{value}}
    data() { return { value: '222' } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbc8IEhs-1659282675378)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220706001452133.png)]

    2. Trim

    Trim 修饰符的作用类似于javaScript中的 Trim()方法,作用是把v-model 绑定的值的首尾空格给过滤掉。

    
    
    {{value}}
    data() { return { value: '123123' } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    失去光标前

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DcPCcsQj-1659282675379)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220706001718926.png)]

    失去光标后

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qcMnFUP7-1659282675380)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220706001700068.png)]

    3. Number

    Number 修饰符的作用是将数值转成数字,但是先输入字符串与先输入数字是两种情况。

    
    
    {{value}}
    data() { return { value: '123123' } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    先输入数字字符串时,只取前面数字部分

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y6YYrXDh-1659282675381)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220706001815094.png)]

    当开始输入非数字的字符串时,由于Vue无法将字符串转换为数值,所以属性值将实时更新成相同的字符串,即使后面输入数字,也将被视作字符串。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZuLhYdl0-1659282675381)(C:\Users\huawei\AppData\Roaming\Typora\typora-user-images\image-20220706001841004.png)]

    4. Stop

    Stop修饰符的作用是阻止冒泡

    methods: { clickEvent(num) { console.log(num) } } // 不加 stop 点击按钮输出 1 2 // 加了 stop 点击按钮输出 1
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    5. Capture

    事件默认是由里往外冒泡,capture 修饰符的作用是反过来,由外往内捕获

    methods: { clickEvent(num) { console.log(num) } } // 不加 capture 点击按钮输出 1 2 // 加了 capture 点击按钮输出 2 1
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    6. Self

    只要学过 python 的都有感觉,这个就是他自身,只有当点击他的时候才能显示,别想从冒泡获取。比如,如果在最外层加上 .self ,当点击button的时候,只有点击最外层才能被触发,如果不加上 .self 会被冒泡

    methods: { clickEvent(num) { console.log(num) } } // 不加 self 点击按钮输出 1 2 // 加了 self 点击按钮输出 1 点击div才会输出 2
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    7. Once

    这个更好理解,只能触发一次,你再点击对我没用了

    methods: { clickEvent(num) { console.log(num) } } // 不加 once 多次点击按钮输出 1 // 加了 once 多次点击按钮只会输出一次 1
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    8. Prevent

    作用是阻止默认事件,什么是默认事件呢?比如我写一个 a 标签,他默认是跳转的,如果加上 .prevent 就可以在跳转之间加上自己的事件,保证显示咱们自己的行为

    点我
    
    methods: {
            clickEvent(num) {
                console.log(num)
            }
        }
    
        // 不加 prevent 点击a标签 先跳转然后输出 1
        // 加了 prevent 点击a标签 不会跳转只会输出 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    9. Native

    在项目开发中如果你用到了自己自定义的组件,并且想给他绑定一个点击事件,这时候就是 .native 发挥作用的时候了,他可以将事件绑定到根组件上,这样 click 事件就会生效了

    // 执行不了
    
    
    // 可以执行
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    10. Left,Right,Middle

    这三个修饰符是鼠标的左中右键触发的事件

    
    
    methods: {
            clickEvent(num) {
                console.log(num)
            }
        }
    
        // 点击中键输出1
        // 点击左键输出2
        // 点击右键输出3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    11. Passive

    当我们在监听元素滚动事件的时候,会一直触发 onscroll 事件,在pc 端是没什么问题的,但是在移动端,会让我们的网页变卡,因此我们使用这个修饰符的时候,相当于给 onscroll 事件整了一个 .lazy 修饰符

    ...
    • 1

    12. Sync

    当父组件传值进子组件,子组件想要改变这个值时,可以这么做

    // 父组件里
    
    
    // 子组件里
    this.$emit('update:foo', newValue)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    .Sync 的作用就是可以简写

    // 父组件里
    
    
    // 子组件里
    this.$emit('update:foo', newValue)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    13. KeyCode

    当我们这么写事件的时候,无论按什么按键都会触发事件

    
    
    • 1

    那么想要限制某一个按钮才能触发事件要怎么办?这个时候 keyCode 就派上用场了

    
    
    • 1

    Vue 提供的 keyCode

    //普通键
    .enter 
    .tab
    .delete //(捕获“删除”和“退格”键)
    .space
    .esc
    .up
    .down
    .left
    .right
    //系统修饰键
    .ctrl
    .alt
    .meta
    .shift
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    eg:

    // 按 ctrl 才会触发
    
    
    // 也可以鼠标事件+按键
    
    
    // 可以多按键触发 例如 ctrl + 67
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Vue双向绑定的实现

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bmr1Zkj2-1659282675382)(C:\Users\huawei\Videos\GIF\1658933955026.gif)]

    vue2

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Documenttitle>
    head>
    <body>
      <div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
        <input type="text">
        <h1>h1>
        <button>点击button>
      div>
    body>
    <script>
      const input = document.getElementsByTagName('input')[0]
      const h1 = document.getElementsByTagName('h1')[0]
      const btn = document.getElementsByTagName('button')[0]
      let data = { text: '' }
    
      input.addEventListener('input', function(e) {
        data.text = e.target.value
      })
      btn.onclick = function() {
        data.text = '晚上好,小龙虾!'
      }
      Object.defineProperty(data, 'text', {
        get: function() {
          return data['text']
        },
        set: function(newValue) {
          h1.innerText = newValue
          input.value = newValue
        }
      })
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    vue3

    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Documenttitle>
    head>
    <body>
      <div id="app" style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
        <input type="text">
        <h1>h1>
        <button>点击button>
      div>
    body>
    <script>
      const h1 = document.getElementsByTagName('h1')[0]
      const btn = document.getElementsByTagName('button')[0]
      let data = { text: '' }
    
      function effect() {
        h1.innerText = data.text
      }
    
      const obj = new Proxy(data, {
        // target当前对象 key属性
        get(target, key) {
          return target[key]
        },
        // target当前对象 key属性 newValue它的值
        set(target, key, newValue) {
          target[key] = newValue
          effect()
          return true
        }
      })
      btn.onclick = function() {
        obj.text = '晚安!'
      }
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Documenttitle>
    head>
    <body>
      <div id="app" style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
        <input type="text">
        <h1>h1>
        <button>点击button>
      div>
    body>
    <script>
      const h1 = document.getElementsByTagName('h1')[0]
      const btn = document.getElementsByTagName('button')[0]
      let data = { text: '' }
    
      function effect() {
        h1.innerText = data.text
      }
    
      const obj = new Proxy(data, {
        // target当前对象 key属性
        get(target, key) {
          return target[key]
        },
        // target当前对象 key属性 newValue它的值
        set(target, key, newValue) {
          target[key] = newValue
          effect()
          return true
        }
      })
      btn.onclick = function() {
        obj.text = '晚安!'
      }
    script>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    参考

  • 相关阅读:
    什么是轮式里程计
    听GPT 讲Rust源代码--library/core/src(6)
    交叉编译qt到arm平台
    计算机毕业设计之java+springboot基于vue的就业信息管理系统-招聘信息管理系统
    如何实现MQTT协议数据传输?
    【C++】面向对象模型 ① ( 面向对象设计 | 面向对象底层实现机制 | 程序内存结构 )
    [CG从零开始] 4. pyopengl 绘制一个正方形
    Git学习笔记6
    《Unity Shader入门精要》笔记08
    Vue指令v-show和v-if的区别
  • 原文地址:https://blog.csdn.net/MoXinXueWEB/article/details/126092666