开始于2022年3月4日
没看的page:
038_收集表单数据=>047自定义指令
初识vue
- 想让Vue工作,必须创建vue实例,并至少传入一个配置属性
- 容器中的代码依然符合HTML规范,只不过混入了一些特殊的vue语法
- 容器中的代码被称为【Vue模板】
- 容器和实例一定是一一对应的
- 双花括号
{{xxx}}
(插值语法
)内xxx
是js表达式,且xxx
可以自动读取data中所有属性 - 真实开发中只有一个Vue实例,且会配合组件一起使用
模板语法
模板语法分为插值语法和指令语法
插值语法用来解析标签体中的内容
指令语法用于解析标签(包括:标签属性、标签体内容、绑定事件)
v-bind:href="xxx"
可以简写为:href="xxx"
xxx
同样为js表达式,且可以直接读取到data中的所有属性
数据绑定
单向数据绑定:v-bind
双向数据绑定:v-model
v-model
只能应用在表单类元素(输入类元素)上这类元素都有value值,因为v-model默认收集value值,所以
v-model:value
的简写形式是v-model
两种指令的简写:
el与data的两种写法
el
在new实例时就定义好
el
后续使用
v.$mount('#root')
再添加(更灵活)mount:挂载
data
对象式:写成对象
函数式:将data写成函数,且该函数需要返回对象
data函数应该写成普通函数,而非箭头函数
写法:
1
2
3
4
5
6
7
8
9
10
11
12const v=new Vue({
//el:'#root',
data(){
console.log('@@@',this)
return {
name:'jack'
}
}
//data:{
// name:'HUST'
//}
})
由Vue管理的函数,不能写成箭头函数。一旦写成箭头函数,this指针就不再是Vue实例了。
MVVM模型
M:Model模型,对应data中的数据
V:View视图,模板
VM:ViewModel,Vue实例对象
因此在文档中,经常用vm
(ViewModel的缩写)这个变量名来表示Vue实例。
data中的所有属性,最后都出现在了vm身上
vm身上所有属性,以及Vue原型上所有属性,在Vue模板中都可以直接使用
数据代理
Object.defineProperty方法
为对象添加属性,与后面的Vue.set()
区分
1 | let person={ |
通过这种方式添加的属性:不可枚举(即不能遍历),且无法修改值,且无法删除
除非修改上述属性
get()
函数
1 | let number=20 |
set()
函数
1 | let number=20 |
通过get()
来帮age从number处取值,通过set()
来将person.age
设置的值赋给number
即getter
将number绑定给age,setter
将age绑定给number
定义数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作
见下例:
1 | let obj={x:100} |
相当于给obj2
添加了名为extra
的属性,并将该属性绑定到obj.x
上
getter
会导致extra
的值从obj.x
处获取
setter
会导致修改extra
的值时会同时修改obj.x
的值
结果见下图:
Vue中的数据代理
见下面的代码:
1 | const vm=new Vue({ |
这里vm中即有name和address两个值,可以通过vm.name
和vm.address
直接访问,相当于getter
Vue实例中的data对象交给了vm,vm将data存在了自己的_data
中
如下图:
Vue中的数据代理图示:
总结:
Vue中数据代理:通过vm对象来代理data对象中属性的操作(读/写)
好处:更加方便操作data中的数据
基本原理:
通过
Object.defineProperty()
把data对象中的所有属性添加到vm上为每一个添加到vm上的属性,都制定一个getter/setter
在getter/setter内部去 读/写 data中对应的属性
事件处理
事件的基本处理
- 使用
v-on:xxx
或@xxx
都能绑定事件,其中xxx是事件名。在本节中使用v-on:click
点击事件举例,v-on:
指令可以简写成@
- 事件的==回调==需要配置在Vue实例的method对象中,最终会在vm上
- methods中配置的函数,不要用箭头函数,要用普通函数,否则this就不是vm了
- methods中配置的函数,都是被Vue管理的函数,this指向的是vm或组件实例对象
@click="demo"
和@click="demo($event)"
效果一致,但带个括号可以在括号里传参数
事件修饰符
写法:<a href="https:www.baidu.com" @click.prevent="showInfo">点我看蟹黄堡秘方</a>
Vue中的事件修饰符:
- prevent:阻止默认事件 (常用)
- stop:阻止事件冒泡 (常用)
- once:事件只触发一次 (常用)
- capture:使用事件的捕获模式
- self:只有event . target是当前操作的元素是才触发事件
- passive:事件的默认行为立即执行,无需等待事件回调执行完毕
修饰符是可以连着写的:@click.prevent.stop="showInfo"
键盘事件
keyup是按键弹起的时候触发,keydown是按键按下的时候触发
Tab特殊,要配合keydown使用
通过这种形式触发:
1 | <input type="text" placeholder="按下回车提示输入" @keyup.enter="showInfo"> |
按键修饰也是可以连着写的:@keyup.ctrl.y="showInfo"
计算属性
姓名案例:(3种写法)
插值语法
v-model:value
是双向数据绑定,简写为v-model
methods
数据(Model)驱动视图(View):数据变化的时候视图中也会随之变化,修改模板的时候都会引起容器的重新解析,会导致在容器中的函数调用重新执行(在插值语法中写方法)
1
2
3
4
5
6
7
8
9
10姓名:<span>{{fullname()}}</span>
//调用fullname这个methods需要带括号`()`
...
methods:{
fullname(){
console.log('@')
return this.surname+'-'+this.name;
//注意上面的this.name而非name
}
}计算属性
普通属性是data中的属性,类似键值对
计算属性写在
computed
里get()
的调用时机:1、初次读取fullname时;2、所依赖的数据发生变化时这正是类似的例子里计算属性相较于methods的优势:只会在必要时调用,会有缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const vm=new Vue({
el:'#root',
data:{
name:'三',
surname:'张'
},
computed:{
fullname:{
get(){
return this.surname+'-'+this.name
},
set(value){
const arr=value.split('-')
this.surname=arr[0]
this.name=arr[1]
}
}
}
计算属性:
定义:要用的属性不存在,要通过已有属性计算得来。
原理:底层借助了
objcet.defineproperty
方法提供的getter和setterget函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
优势:与methods实现相比, 内部有缓存机制(复用),效率更高,调试方便。
备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
简写:
当不需要修改计算属性的value时(即不需要setter时)可以将计算属性简写成方法的形式,这个函数就是原来的get()函数
监视属性
使用旧知识写天气案例:
小小的天气案例,用到了计算属性computed,用到了方法methods
可以把不用将点击事件click绑定至changeWeather方法,而是直接在click后面引号中写上简单的isHot=!isHot
使用监视属性写天气案例:
watch的简写与计算属性computed类似:
(在不使用watch中的immediate、deep属性时可以采用简写)
监视属性总结:
当被监视的属性变化时,回调函数自动调用,进行函数内的操作
回调函数是指
handler()
监视的属性(计算属性也可以监视)必须存在,才能进行监视
监视属性不存在时不会报错
监视的两种写法:
new Vue
时传入watch配置- 通过
vm.$watch
监视
深度监视
监视多级结构中某个属性的变化
对象中的key是个字符串,简写形式可以不带''
单引号,但像下面的例子中要监视numbers.a
时就得加单引号,不然会带.
1 | //监视多级结构中某个属性的变化 |
监视多级结构中所有属性的变化
整个对象在监视时相当于监视复杂结构的地址,尽管其内容发生改变,只要地址不变,监视就不会给出变动
如果开启deep属性:deep:true
,则可以做到监控一整个结构的所有属性
深度监视总结:
- Vue中的watch默认不监视对象内部值的改变(只监视一层)
- 配置
deep:true
可以检测对象内部值的改变(可以监视每一层)
另外:
- Vue自身可以检测对象内部值的改变,但其提供的watch默认不可以
- 使用watch时根据数据对象的具体结构,决定是否采用深度监视
回顾:Vue管理的函数
methods中的函数
计算属性中的get()、set(),以及计算属性简写时的函数(直接是属性名做函数)
监视属性中的handler(),以及监视属性简写时的函数(直接是属性名做函数)
上述姓名案例和天气案例通过计算属性和监视属性都可以实现
具体差别见代码
基础实现用计算属性较为简单,但一些复杂需求还是要使用监视属性,例如姓名案例中修改姓名后延迟1s后再使全名修改
计算属性中不能开启异步任务去维护数据,但监视属性watch可以
要注意的是:
Vue管理的函数都要使用普通函数
计时器要使用箭头函数,见下例:
computed和watch之间的区别:
- computed能完成的功能,watch都能完成
- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
==两个重要的小原则==:
- 被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
- 所有不被Vue管理的函数(定时器的回调函数、ajax的回调函数、Promise的回调函数等),最好写成箭头函数,这样this指向的才是vm 或 组件实例对象
- 上述俩原则目标统一:确保this指向的是vm 或 组件实例对象
绑定样式
:class
或:style
是v-bind:class
和v-bind:style
的简写
记得样式属性写在对象里时例如font-size
要写成fontSize
,且40px
两边要加引号,如下所示:
绑定class样式
字符串写法:适用于——样式名不确定,需要动态指定的情况
数组写法:适用于——要绑定的样式名称不确定,个数也不确定
将数组中的样式全都绑定,通过增删数组,来控制绑定哪些样式
对象写法:适用于——要绑定的样式名字和个数都确定,但要动态决定用不用
绑定style样式
也分为对象写法和数组写法
要分清楚哪里带引号,哪里不带引号
条件渲染
通过
v-show="a"
实现,a
是Vue管理的变量,可以动态修改,值为true
orfalse
通过
v-if="b"
实现,v-if
在将其隐藏的时候会彻底删除
所以隐藏/显示频率高的时候用v-show
,减少开销
同理还有v-else-if
、v-else
,与v-if
是一组判断
- 可以用
template
将在不影响结构的前提下将多个标签包裹,但只能配合v-if
- 使用
v-if
的时候元素可能获取不到(元素可能直接被删掉了),但v-show
一定能获取到元素
列表渲染
基本列表
利用v-for
一般用v-for
来遍历数组、对象,偶尔遍历字符串、次数
v-for
指令:
- 用于展示列表数据
- 语法:
v-for="(item,index) in xxx" :key="yyy"
每个元素key
唯一 - 可遍历:数组、对象、字符串、次数
key的原理
如果以Vue自动给出的index作为key会出问题,解释见下图:
==面试==:关于key的作用总结如下:
列表过滤
推荐用计算属性实现,但监视属性也能实现
一个使用name作为keyword进行关键词模糊筛选的例子
使用到了js中数组的filter
方法 【JavaScript Array filter() 方法】
内部返回值使用js中字符串的indexOf
方法 【JavaScript indexOf() 方法】,若indexOf()
返回-1,表示父串中无子串,否则返回子串在父串中的下标
监视实现:
(推荐)计算属性实现:
列表排序
计算属性的强大之处:计算filPersons
所用到的变量中有一个发生改变,都会引起filPersons
的重新计算
js中数组的sort
方法 【JavaScript Array sort() 方法】
Vue监测数据改变的原理
利用set()
方法,但set()
方法只能应用于对象,不能修改数组
因为Vue.set()
没有对数组进行监测,增加setter()
和getter()
数组名、对象 才是响应式的,其改变会触发视图更新
能修改数组并引发视图更新的方法:push()
、pop()
、shift()
、unshift()
、splice()
、sort()
、reverse()
注意,split()
方法不能修改数组,只能返回筛选后的结果
Vue对数组的监测实际上是通过包装数组身上上述常用能够修改数组的方法实现的,以便监测其变化,进而触发视图更新
总结:
038_收集表单数据=>047自定义指令
生命周期
引出生命周期
- 生命周期又名生命周期回调函数、声明周期函数、生命周期钩子
- 是什么:是Vue在关键时刻帮我们调用的一些特殊名称的函数
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
- 生命周期函数中的this指向的是vm或组件实例对象
生命周期流程
声明周期示意图:
挂载流程-更新流程-销毁流程
讲了8个-4对生命周期钩子
beforeCreate()
-created()
beforeMount()
-mounted()
beforeUpdate()
-updated()
beforeDestory()
-destoryed()
详见上面的生命周期流程示意图
比较重要的是mounted()
和beforeDestory()
在
mounted()
中做初始化的事情发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
在
beforeDestory()
中做收尾善后的事情清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
关于销毁Vue实例:
- 销毁后借助Vue开发者工具看不到任何信息
- 销毁后自定义时间会失效,但原生DOM事件依然有效
- 一般不会在
beforeDestory()
操作数据,因为数据即便被改变,也不会再触发更新流程了
小Tips:在生命周期函数
mounted()
中创建的定时器,想在methods
中将其关闭,创建时可以创建成this.timer=setInterval()
的 形式,这样创建在this中,就相当于创建在vm上,methods
中也能使用方法将其关闭
组件
非单文件组件:一个文件中包含有n个组件,写在.html文件里
单文件组件:一个文件中只包含有1个组件,写在.vue文件中,一个文件就是一个组件
Vue中使用组件的三大步骤:
定义组件(创建组件)
注册组件
使用组件(写组件标签)
如何定义一个组件:
使用
Vue.extend(options)
创建,其中optinos
和new Vue(options)
时传入的那个options
几乎一样,但区别如下:el
不要写:最终所有的组件都要经过一个vm的管理,由vm中的el
决定服务哪个容器data
必须写成函数:避免组件被复用时,数据存在引用关系
另外:使用
template
可以配置组件结构const school = Vue.extend(options)
可以简写为const school = opntions
如何注册组件:
- 局部注册:靠
new Vue
的时候传入components
选项 - 全局注册:靠
Vue.components('组件名',组件)
- 局部注册:靠
编写组件标签:
<school></school>
【关于VueComponent
】
school组件本质是一个名为
VueComponent
的构造函数,且不是程序员定义的,是Vue.extend
生成的我们只需要写
<school></school>
或<school/>
,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
每写一次标签就调用一次相应的构造函数
特别注意:每次调用
Vue.extend
,返回的都是一个全新的VueComponent
关于this指向:
组件配置中:
data函数、methods中的函数、watch中的函数、computed中的函数
它们的this均为【
VueComponent
实例对象】new Vue()
配置中:data函数、methods中的函数、watch中的函数、computed中的函数
它们的this均为【
Vue
实例对象】
VueComponent
的实例对象,以后简称vc,也可称之为 组件实例对象Vue的实例对象简称vm
分析Vue与VueComponents的关系
实例的隐式原型属性,永远指向自己缔造者的原型对象
Vue与VueComponents的关系示意图:
VueComponent.prototype.__proto__ === Vue.prototype
上面这个式子是上图中黄色的虚线的含义
这样做的原因是:让组件实例对象(vc)可以访问到Vue原型上的属性、方法
Vue单文件组件
export
分别暴露,统一暴露,默认暴露,下图中是最常使用的默认暴露方法
写组件的快捷键:**<v
**,结构、交互、样式的模板可以立刻写出
Vue脚手架
安装
路由
- 本文链接:https://wan-nan.github.io/2022/03/30/vue%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。