Vue 基础
内置指令
1、v-bind:单向绑定解析表达式,可简写为::xxx
。
2、v-model:双向数据绑定。
3、v-for:遍历数组、对象、字符串。
4、v-on:绑定事件监听,可简写为 @xxx(如:@click)。
5、v-if:条件渲染(动态控制节点是否存在)。
6、v-else:条件渲染(动态控制节点是否存在)。
7、v-show:条件渲染(动态控制节点是否展示)。
8、v-text:可向其所在的节点中渲染文本内容,它与插值语法的区别在于:v-text 会替换掉节点中的内容,而{{xx}}
插值语法则不会替换。
9、v-html:用法及作用与 v-text 类似,只不过 v-model 可以解析标签,而 v-text 则不行。
1 | <div> |
注意:v-model 处在安全性问题,在网站上动态渲染任意 HTML 是非常危险的,容易导致 XSS 攻击。因此一定要在可信的内容上使用 v-html,不要用在用户提交的内容上。
10、v-cloak:该指令没有值,本质上是一个特殊属性,Vue 实例创建完毕并接管容器后,会删除 v-cloak 属性。可以使用 css 配合 v-cloak 解决网速慢时页面展示出{{xxx}}
的问题。
1 | <style> |
11、v-once:该指令所在节点在初次动态渲染后,就视为静态内容了,以后数据的改变不会引起 v-once 所在结构的更新,可以用于优化性能。
1 | <body> |
12、v-pre:该指令会跳过所在节点的编译过程。可以利用该指令跳过没有使用 vue 的指令语法,或没有使用 vue 插值语法的节点,加快编译。
事件的基本使用
1、使用 v-on:xxx 或 @xxx 绑定事件,其中 xxx 是事件名。
2、事件的回调需要配置在 methods 对象中,最终会挂在 vm 上。
3、methods 中配置的函数,都是被 vue 所管理的函数,其中 this 的指向是 vm 或组件实例对象。
4、methods 中配置的函数,不要用箭头函数,否则 this 就会指向 window,不再指向 vm。
5、@click=”demo” 和 @click=”demo($event)” 效果一致,但后者可以传递其它参数。
6、示例代码如下:
1 | <div id="root"> |
事件修饰符
1、prevent:阻止默认事件。
2、stop:阻止事件冒泡。
3、once:事件只触发一次。
4、capture:使用事件的捕获模式,即事件会在捕获阶段触发,而不是在默认的冒泡阶段触发。
5、self:只有 event.target 是当前操作的元素时才触发事件。
6、passive:事件的默认行为立即执行,无需等待事件回调执行完毕。
7、具体使用方式如下:
1 | <div id="root"> |
键盘事件
1、vue 中常用的按键别名:
回车:enter。
删除:delete(捕获”删除”和”退格”键)。
退出:esc。
空格:space。
换行:tab(特殊,必须配合 keydown 去使用)。
上:up。
下:down。
左:left。
右:right。
2、vue 为提供别名的按键,可以使用按键原始的 key 值去判定,但注意要转为 kebab-case(短横线命名)。
3、系统修饰键(用法特殊):ctrl、alt、shift、meta。
配合 keyup 使用:按下修饰键的同时,再按下其它键,随后释放其它键,事件才被触发。
配合 keydown 使用:正常触发事件。
4、可以使用 keyCode 去指定具体的按键(不推荐)。
5、Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名。
计算属性 computed
1、定义:要用的属性不存在,要通过已有属性计算得来。
2、原理:底层借助 Object.defineproperty 方法提供的 getter 和 setter 实现。
3、get 函数什么时候执行?
初次读取时会执行一次。
当依赖的数据发生改变时会被再次调用。
4、优势:与 methods 实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 计算属性最终会出现在 vm 上,直接读取使用即可。
- 如果计算属性要被修改,那必须写 set 函数去响应修改,且 set 中要引起计算时依赖的数据发生改变。
5、具体代码示例如下:
1 |
|
watch 与 computed 的差异
1、computed 能完成的功能,watch 都能完成。
2、watch 能完成的功能,computed 不一定能完成,例如:watch 可以进行异步操作。
- 所被 vue 管理的函数,最好写成普通函数,这样 this 的指向才是 vm 或组件实例对象。
- 所有不被 vue 所管理的函数(定时器的回调函数、ajax 的回调函数等),最好写成箭头函数,这样 this 的指向才是 vm 或组件实例对象。
3、使用 watch 实现计算属性:
1 |
|
监视属性 watch
1、当被监视的属性变化时,回调函数(handler)自动调用。
- 注意:回调函数(handler)名称不能随意乱写,否则会报错。
2、监视的属性必须存在,才能进行监视。
3、监视的两种写法:
new Vue 时传入 watch 配置。
创建 vm 之后,通过 vm.$watch 实现监视。
4、深度监测:
vue 中的 watch 默认不监测对象内部值的变化(单层级对象)。
配置 deep:true 可以监测对象内部值的变化(多层级对象)。
- vue 自身可以监测对象内部值的改变,但 vue 提供的 watch 默认不可以。
- 使用 watch 时根据数据的具体结构,决定是否采用深度监测。
5、具体使用方式如下:
1 |
|
绑定样式
1、绑定 class 样式写法为:class=”xxx”,xxx 可以是字符串,对象,数组。
字符串写法适用于类名不确定,个数不确定,名字不确定的情况。
对象写法适用于要绑定多个样式,个数不确定,名字也不确定的情况。
数组写法适用于要绑定多个样式,个数确定,名字也确定,但是不确定用不用的情况。
2、绑定 style 样式写法为:
:style=”{fontSize: xxx}” 其中 xxx 是动态的。
:style=”[a,b]” 其中 a、b 是样式对象。
3、具体使用示例如下:
1 |
|
条件渲染
v-if
1,v-if 写法:
1 | v-if = '表达式' |
2,v-if 适用于切换频率较低的场景,因为它会将隐藏的元素直接从元素所在位置删除。
3,v-if 可以和 v-else-if、v-else 一起使用,但是这三者之间必须紧紧挨在一起,中间不能插入其它元素,否则判断将会被打断,导致条件判断不生效。
v-show
1,v-show 写法:
1 | v-show = '表达式' |
2,v-show 适用于切换频率较高的场景,因为其特点就是隐藏的 DOM 元素是使用 display:none
进行隐藏的,元素依然存在。
使用 v-show 时,该元素一定能获取到,但是使用 v-if 时,元素可能无法获取到。
条件渲染具体使用示例
1 | <div id="root"> |
template 可以防止在 3 个 h2 元素外包一层父元素,从而导致破坏原有的 DOM 结构,但是 template 只能配合 v-if 进行使用,不能配合 v-show 进行使用。
列表渲染 v-for
1、v-for 用于展示列表数据。
2、语法:v-for=”(item, index) in xxx” :key=”唯一标识(如:id)”
3、v-for 可遍历:数组、对象、字符串、指定对象。
4、具体使用方式如下:
1 |
|
key 的作用(原理)
1、虚拟 dom 中 key 的作用:
- key 是虚拟 dom 对象的标记,当数据发生变化时,vue 会根据「新数据」生成「新的虚拟 dom」,随后 vue 进行「新虚拟 dom」的差异比较。
2、虚拟 dom 对比规则:
当旧虚拟 dom 中找到了与新虚拟 dom 相同的 key 时:
若虚拟 dom 中内容没变,直接使用之前的真实 dom。
若虚拟 dom 中内容变了,则生成新的真实 dom,随后替换掉页面上之前的真实 dom。
当旧虚拟 dom 中未找到与新虚拟 dom 相同的 key 时:
- 创建新的真实 dom,随后渲染到页面中。
3、用 index 最为 key 可能引发的问题:
若对数据进行逆序添加、逆序删除等破坏顺序操作时,会产生没有必要的真实 dom 更新,虽然对界面没有什么影响,但是效率极低。
如果结构中还包含输入类的 dom 时,会产生错误 dom 更新,导致更新的界面出问题。
4、开发中如何选择使用的 key:
最好使用每条数据的唯一标识,比如:id。
如果不存在对数据的逆序添加,逆序删除等破坏顺序的操作,仅用于渲染列表用于展示时,使用 index 作为 key 是没有问题的。
列表过滤
1、可通过 watch 实现也可通过 computed 计算属性实现,具体实现方式如下:
1 |
|
Vue 数据监听的原理
1、vue 会监视 data 中所有层次的数据。
2、vue 中通过 setter 实现监视,但是要在 new Vue 时就传入要监视的数据。
对象中一开始没有定义,在后来追加的属性,vue 默认不做响应式处理。
如果需要给后添加的属性做响应式,需要使用如下 API:
- Vue.set(target, key, value) 或 vm.$set(target, key, value)。
3、如果要检测数组中的数据,需要通过包裹数组更新元素的方法实现,本质就是:
首先调用数组原生的方法对数组进行更新。
重新解析模版,进而更新页面。
4、在 vue 修改数组中的某个元素一定要用如下方法:
push、pop、shift、unshift、splice、sort、reverse。
Vue.set() 或 vm.$set()。
注意千万不能使用 set 给 vm 或 vm 的根数据对象中添加属性。
5、具体使用实例如下:
1 | // 更新对象 |
Vue 表单收集
1、<input type="text" />
则 v-model 收集的是 input 中用户输入的 value 值。
2、<input type="radio" />
则 v-model 收集的是 input 中的 value 值,但是需要手动给 input 设置 value 值。
3、<input type="checkbox" />
的情况:
没有配置 input 的 value 属性时,那么收集的就是 checked(勾选或为勾选,是个 boolen 值)。
当配置了 input 的 value 属性时:
v-model 的初始值是非数组,那么收集的就是 checked(勾选或为勾选,是个 boolen 值)。
v-model 的初始值是数组,那么收集的就是 value 组成的数组。
v-model 的三个修饰符:
- lazy: 失去焦点再收集数据。
- number: 输入字符串转为有效的数字。
- trim: 去除输入的首尾空格。
5、具体使用示例如下:
1 |
|
过滤器
1、过滤器的定义就是对要显示的数据进行特定格式化后再显示(适用于一些简单的逻辑处理)。
2、定时器语法:
注册过滤器:
Vue.filter(name, callback)
或new Vue({filters:{...}})
。使用过滤器:
{{xxx | 过滤器名称}}
或 v-bind: 属性 = ‘xxx | 过滤器名称’。
过滤器说明:
- 过滤器也可以接受额外的参数,但第一个参数永远都是需要过滤的属性(即
{{xxx | 过滤器名称}}
中的 xxx),第二个参数才是额外传入的参数。- 多个过滤器可以进行串联使用。
- 过滤器并没有改变原本的数据,而是产生新的对应的数据。
3、具体使用如下:
1 |
|
自定义指令
1、局部指令定义语法:
1 | // 写法一 |
2、全局指令:
1 | // 写法一 |
3、配置对象中常用的 3 个回调:
bind:在指令与元素成功绑定时调用。
inserted:在指令所在元素被插入页面时调用。
update:在指令所在模版结构被重新解析时调用。
指令定义时不加 v-,但使用时要加 v-。指令名如果是多个单词,要使用 kebab-case 命名方式,不要用 camelCase 命名。
4、具体使用方式如下:
1 |
|
生命周期
1、常用的生命周期钩子主要有以下两个:
mounted:其中可发送 ajax 请求、启动定时器、绑定自定义事件、订阅消息等初始化操作。
berforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等收尾工作。
2、关于销毁 Vue 实例:
销毁后借助 vue 开发者工具看不到任何消息。
销毁后自定义事件会失效,但原生 DOM 事件依然有效。
一般不会在 beforDestory 中操作数据、因为即使操作数据,也不会再触发更新流程了。
VueComponent
1、vue 中每个组件本质是一个名为 VueComponent 的构造函数,且不失程序员定义的,而是 Vue.extend 生成的。
2、如我们只需要写一个<demo /> 或者 <demo><demo />
,Vue 解析时就会帮我们创建 school 组件的实例对象,即 Vue 帮我们执行:new VueComponent(options)
。
3、特别注意:每次调用 Vue.extend,返回的都是一个全新的 VueComponent。
4、关于 this 的指向:
组件配置中:data 函数、methods 中的函数、watch 中的函数、computed 中的函数它们的 this 都是 VueComponent 实例对象。
new Vue(options)配置中,data 函数、methods 中的函数、watch 中的函数、computed 中的函数都是指向 Vue 实例对象。
render 函数
1、vue.js 与 vue.runtime.xxx.js 的区别:
vue.js 是完整版的 vue,包含核心功能和模板解析器。
vue.runtime.xxx.js 是运行版的 vue,只包含核心功能,没有模板解析器。
2、因为 vue.runtime.xxx.js 没有模板解析器,所以不能使用 template 配置项,需要使用 render 函数接收到的 createElement 函数去指定具体内容。
混合 mixin
1、混合功能:可以把多个组件共用的配置提取成一个混入对象。
2、混合的定义方式如下:
1 | export const mixin = { |
3、混合的使用,有如下两种方式:
全局混入:Vue.mixin(xxx)。
局部混入:mixins:[‘mixin1’, ‘mixin2’]。
4、混合具体使用方式:
1 | <script> |
说明:在定义 state 属性时,如果组件自身上存在于混合中相同的属性,那么以自身的为准,如果在生命周期中如 mounted 中同时定义了某些方法,那么会将它们进行混合,两者并存,并且会先执行混合中的方法。
plugins(插件)
1、定义 plugins.js 文件:
1 | export default { |
2、应用 plugins:
1 | import Vue from 'vue' |
3、在组件中使用 plugins 中定义的全局指令,过滤器等:
1 | <template> |
自定义事件
1、自定义事件说明:
自定义事件是一种组件间通信的方式,适用于:子组件像父组件传递数据。
使用场景:A 是父组件,B 是子组件,B 想给 A 传递数据,那么就要在 A 中给 B 绑定自定义事件(事件的回调在 A 中)。
绑定自定义事件的方式:
方式一:在父组件中:
<Demo @demo="demo" />
或<Demo v-on:demo="demo" />
方式二:在父组件中:
1
2
3
4
5
6
7<Demo ref="demo" />
<!-- ... -->
mounted(){ this.$refs.demo.$on('xxx', () => {
<!-- do something... -->
}) }- 如果想让自定义事件只能触发一次,可以使用 once 修饰符,或者 $once 方法。
触发自定义事件:
this.$emit('xxx', data)
。解绑自定义事件:
this.$off('xxx')
。组件上也可以绑定原生 DOM 事件,需要使用 native 修饰符。
注意:通过
this.$refs.xxx.$on('xxx', 回调)
绑定自定义事件时,回调要么配置在 methods 中,要么就用箭头函数,否则 this 指向会出现问题。
2、自定义事件具体写法:
- App 组件
1 | <template> |
使用 ref 实现自定义事件时,绑定的回调需要注意 this 指向问题,最好在 methods 中先定义好回调,或者使用箭头函数。
如果要给组件绑定原生事件(如:click),需要给事件加上 native 修饰符,否则将被视为自定义事件,需要在被绑定的组件中使用$emit 触发该事件。
- School 组件
1 | <template> |
- Student 组件
1 | <template> |
- Teacher 组件
1 | <template> |
全局事件总线
1、全局事件总线是一种组件通信的方式,适用于任意组件间的通信。
2、安装全局事件总线:
1 | new Vue({ |
3、使用事件总线:
- 接收数据:A 组件想接收数据,则在 A 组件中给 $bus 绑定自定义事件,事件的回调留在 A 组件自身。
1 | mothods(){ |
- 提供数据:
this.$bus.$emit('xxx', data)
4、最好在 beforeDestroy 生命周期钩子中,用 $off
解绑当前组件所用到的事件。
5、事件总线具体使用:
- main.js
1 | import Vue from "vue"; |
- Student.vue
1 | <template> |
- School.vue
1 | <template> |
nextTick
1、语法:this.$nextTick(callback)
。
2、作用:在下一次 DOM 更新结束后再执行其指定的回调。
3、使用时机:当改变数据后,要基于更新后新的 DOM 元素进行某些操作时,要在 nextTick 所指定的回调函数中执行。
1 | methods () { |
slot 插槽
1、slot 默认插槽的基本使用方式:
- App.vue
1 | <template> |
- Category.vue
1 | <template> |
2、具名插槽的基本使用:
- App.vue
1 | <template> |
- Category.vue
1 | <template> |
3、作用域插槽理解:数据在组件自身,但根据数据生成的结构需要组件的使用者来决定(games 数据在 Category 组件中,但使用数据所遍历出来的结构由 App 组件决定)。具体使用如下:
- App.vue
1 | <template> |
- Category.vue
1 | <template> |
Vuex
注册 store
- main.js
1 | import Vue from "vue"; |
创建 store
- store/index
1 | import Vue from "vue"; |
使用 Vuex 中存储的 state
- App.vue
1 | <template> |
- count.vue
1 | <template> |
mapState、mapGetters、mapMutations、mapActions
1、mapState 方法:用于映射 state 中的数据为计算属性。
2、mapGetters 方法:用于映射 getters 中的数据为计算属性。
3、mapMutations 方法:用于生成与 mutations 对话的方法,即:包含 $store.commit(xxx) 的函数。
4、mapActions 方法:用于生成与 actions 对话的方法,即:包含 $store.dispatch(xxx) 的函数。
5、具体使用方式如下:
1 | <template> |
使用 vuex 实现数据共享
- Count.vue
1 | <template> |
- Person.vue
1 | <template> |
store 模块化写法
- store/index
1 | import Vue from "vue"; |
- store/count
1 | export default { |
- store/person
1 | import axios from "axios"; |
组件中如何使用模块化的 store
1、借助 mapState、mapAction、mapMutations、mapGetters 实现模块化写法:
- Count.vue
1 | <template> |
2、不借助 mapState、mapAction、mapMutations、mapGetters 手动实现模块化写法(调用 dispatch、mutations 等):
- Person.vue 模块化写法
1 | <template> |
路由
vue-router 的理解
1、vue 中的一个插件库,专门用来实现 SPA 应用。
路由的理解
1、什么是路由:
一个路由就是一组映射关系(key-value)。
key 为路径、value 可能是 function 或 component。
路由分类
后端路由
1、后端路由理解:value 是 function,用于处理客户端提交的请求。
2、工作过程:服务器收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应数据。
前端路由
1、前端路由理解:value 是 component,用于展示页面内容。
2、工作过程:当浏览器的路径改变时,对应的组件就会显示。
基本路由
1、安装 vue-router,命令:npm i vue-router -S
。
2、应用插件:Vue.use(VueRouter)
。
3、编写 router 配置项:
1 | import VueRouter from "vue-router"; |
4、实现切换(active-class 可配置高亮样式):
1 | <router-link active-class="active" to="/home">Home</router-link> |
5、指定展示位置:
1 | <router-view></router-view> |
6、基本使用方式如下:
1 | <template> |
嵌套(多级)路由
1、配置路由规则,使用 children 配置项:
1 | routes: [ |
注意:二级路由 path 前面不需要再写
/
。
2、跳转(需要写完整路径):
1 | <router to="/home/news">News</router> |
3、具体使用如下:
- router/index
1 | import VueRouter from "vue-router"; |
- Home.vue
1 | <template> |
- Message.vue
1 | <template> |
- News.vue
1 | <template> |
命名路由
1、作用:可以简化路由的跳转。
2、具体使用:
- 给路由命名:
1 | { |
- 简化跳转:
1 | <!-- 简化前,需要写完整的路径 --> |
路由传参
传递 query 参数
1、传递 query 参数的两种方式:
1 | <!-- 使用模板字符串写法传递query参数 --> |
2、接受 query 参数的方式:
1 | $route.query.id; |
3、query 参数具体使用方式如下:
- router/index
1 | import VueRouter from "vue-router"; |
- Message.vue
1 | <template> |
- Detail.vue
1 | <template> |
传递 params 参数
1、配置路由,声明接受 params 参数:
1 | { |
2、传递参数:
1 | <!-- 跳转并携带params参数,to的字符串写法 --> |
注意:路由携带 params 参数时,如果使用 to 的对象写法,则不能使用 path 配置项,必须使用 name 配置。
3、接收 params 参数:
1 | $route.params.id; |
4、params 参数具体使用方式如下:
- router/index
1 | import VueRouter from "vue-router"; |
- Message.vue
1 | <template> |
- Detail.vue
1 | <template> |
路由的 props 配置
1、路由的 props 配置能让路由组件更方便的收到参数。
1 | { |
注意:props 作为布尔值的写法不适用于 query 参数,只适用于 params 参数。
2、具体使用方式如下:
- router/index
1 | import VueRouter from "vue-router"; |
- Detail.vue
1 | <template> |
router-link 标签的 replace 属性
1、作用:控制路由跳转时操作浏览器历史记录的模式。
2、浏览器的历史记录有两种写入方式:分别为 push 和 replace,push 是追加历史记录,replace 是替换当前记录,路由跳转时默认为 push。
3、开启 replace 模式的方式:<router-link replace to="/xxx">xxx</router-link>
编程式路由导航
1、作用:不借助 router-link 标签实现路由跳转,让路由跳转更加灵活。
2、具体使用方式如下:
1 | this.$router.push({ |
缓存路由组件
1、作用:让不展示的路由组件保持挂载,不被销毁。
2、具体使用方式:
1 | <!-- 缓存一个的写法,注意:include包含的是组件名 --> |
keep-alive 包裹的 router-view 必须是当前组件所展示的位置。其中 include 包含的是组件的组件名。如果不写 include,则表示缓存所有未展示的组件。
activeted、deactivated
1、作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
activeted:当路由组件被激活时触发。
deactivated:当路由组件失活时触发。
2、activeted、deactivated 配合 keep-alive 具体使用方式如下:
1 | <template> |
路由守卫
1、作用:对路由进行权限控制。
2、分类:全局路由守卫、独享守卫、组件内守卫。
3、全局路由守卫:
1 | // 全局前置路由守卫,会在初始化的时候被调用,以及每次路由切换之前被调用 |
4、独享路由守卫:
1 | beforeEnter: (to, from, next) => { |
独享路由守卫只有前置守卫,没有后置守卫,但是可以配合全局后置守卫一起使用实现具体功能。
5、组件内路由守卫:
1 | // 进入守卫,通过路由规则点击router-link或者使用$route.push()),进入该组件时被调用 |
6、beforeEatch 前置路由守卫具体使用:
- router/index
1 | import VueRouter from "vue-router"; |
- 借助 meta 属性进行权限校验
1 | import VueRouter from "vue-router"; |
7、afterEatch 后置路由守卫具体使用:
- 使用后置路由守卫实现 document.title 的实时更改
1 | import VueRouter from "vue-router"; |
8、beforeEnter 独享路由守卫具体使用:
1 | import VueRouter from "vue-router"; |
9、组件内路由守卫具体使用:
1 | <template> |
路由器的两种工作模式
1、对于一个 url 来说,什么是 hash 值?#及其后面的内容就是 hash 值。
2、hash 值不会包含在 HTTP 请求中,即 hash 值不会带给服务器。
3、hash 模式:
地址中永远带着#号,不美观。
若以后将地址通过第三方手机 App 分享,若 App 校验严格,则地址会被标记为不合法。
兼容性较好。
4、history 模式:
地址干净,美观。
兼容性和 hash 模式相比略差。
应用部署上线时需要后端人员支持,解决刷新页面服务端出现 404 的问题。
5、更改路由工作方式的方法:
1 | import VueRouter from "vue-router"; |
Vue 高级
setup
setup 方法说明
1,setup 是 Vue3.x 新增的一个选项,它是组件内使用 Composition API 的入口。
setup 执行时机
2,setup 会在 beforeCreate 之前执行,而不是在 beforeCreate 和 created 之间执行。
setup 参数说明
1,setup 接受两个参数,分别为:
props: 组件传入的属性。
context:是一个对象,由于 setup 中不能访问 Vue2 中最常用的 this 对象,所以 context 中就提供了 this 中最常用的三个属性:attrs、slot 和 emit,分别对应 Vue2.x 中的 $attr属性、slot插槽 和$emit 发射事件。并且这几个属性都是自动同步最新的值,所以我们每次使用拿到的都是最新值。
2,setup 中接受的 props 是响应式的, 当传入新的 props 时,会及时被更新。由于是响应式的, 所以不可以使用 ES6 解构,解构会消除它的响应式。如下写法就会消除响应式:
1 | // demo.vue |
3,如果在开发中即想使用解构,又不消除 props 的响应式,就可以使用 toRefs 解决,因为 toRefs 能将 reactive 对象转化为属性全部为 ref 对象的普通对象。具体使用方式如下:
1 | <template> |
reactive、ref 与 toRefs
1,在 vue2.x 中, 定义数据都是在 data 中,但是 Vue3.x 可以使用 reactive 和 ref 来进行数据定义。
reactive 与 ref 的区别
1,reactive 主要用于处理对象的双向绑定,但是不能处理基本类型,例如 string、number、boolean 等。
2,ref 主要用于处理 js 基础类型的双向绑定,但也能处理对象的数据绑定,如下:
1 | setup() { |
4,toRefs 用于将一个 reactive 对象转化为属性全部为 ref 对象的普通对象。
- 不使用 toRefs 的书写方式如下:
1 | <template> |
- 使用 toRefs 的书写方式如下:
1 | <template> |
使不使用 toRefs 的主要区别在于不使用 toRefs 时,姓名与年龄绑定到页面上时,需要使用 user.nickname,user.age,而使用 toRefs 时,绑定姓名与年龄到页面上只需要使用 nickname,age 即可。
vue3.x 生命周期
vue3.x 生命周期图谱
vue3.x 生命周期写在 setup 方法中,同时声明周期钩子都是以 onXxx 开头的,如:onMounted、onUpdated 等等。
watch 与 watchEffect
watch 方法说明
1,watch 函数用来侦听特定的数据源,并在回调函数中执行副作用。默认情况是惰性的,也就是说仅在侦听的源数据变更时才执行回调。
2,使用语法如下:
1 | watch(source, callback, [options]); |
watch 参数说明
1,source:可以支持 string、Object、Function、Array,用于指定要侦听的响应式变量。
2,callback:执行的回调函数。
3,options:支持 deep、immediate 和 flush 选项。
watch 具体使用
1,监听 reactive 定义的数据:
1 | import { defineComponent, ref, reactive, toRefs, watch } from "vue"; |
2,监听 ref 定义的数据:
1 | const year = ref(0); |
3,侦听多个数据:
- 当我们需要侦听多个数据源时,可以进行合并,同时侦听多个数据,如下:
1 | watch([() => state.age, year], ([newAge, newYear], [oldAge, oldYear]) => { |
4,侦听复杂的嵌套对象:
1 | const state = reactive({ |
如果不使用第三个参数 deep:true,是无法监听到数据变化的。前面我们提到,默认情况下,watch 是惰性的,那什么情况下不是惰性的,可以立即执行回调函数呢?只需要设置第三个参数 immediate: true 即可。
5,stop 停止监听:
- 我们在组件中创建的 watch 监听,会在组件被销毁时自动停止。如果在组件销毁之前我们想要停止掉某个监听,可以调用 watch() 函数的返回值,操作如下:
1 | const stopWatchRoom = watch( |
watchEffect 方法说明
1,watchEffect 与 watch 使用上的区别:
1 | import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue"; |
上述代码执行结果首先打印一次 state 和 year 值,然后每隔一秒,打印 state 和 year 值。从上面的代码可以看出,并没有像 watch 一样需要先传入依赖,watchEffect 会自动收集依赖, 只要指定一个回调函数。在组件初始化时,会先执行一次来收集依赖,然后当收集到的依赖中数据发生变化时,就会再次执行回调函数。
watchEffect 与 watch 的区别
1,watchEffect 不需要手动传入依赖。
2,watchEffect 会在组件初始化时先执行一次用来自动收集依赖。
3,watchEffect 无法获取到变化前的值,只能获取变化后的值。
slot 具名插槽语法
vue2.x 具名插槽写法
1 | // 子组件中 |
vue2.x 作用域插槽写法
1,如果需要在 slot 上面绑定数据,可以使用作用域插槽,实现如下:
1 | // 子组件 |
vue3.x 中使用插槽
1,在 Vue2.x 中具名插槽和作用域插槽分别使用 slot 和 slot-scope 来实现,在 Vue3.0 中将 slot 和 slot-scope 进行了合并统一使用。Vue3.0 中 使用 v-slot 实现:
1 | // 父组件中使用 |
自定义指令
vue2.x 实现自定义指令
1,实现实例代码如下:
1 | // 注册一个全局自定义指令 `v-focus` |
2,在 Vue 2 中,自定义指令通过以下几个可选钩子创建:
bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。
vue3.x 对自定义指令 API 的变更
1,vue2.x 与 vue3.x 自定义指令 API 的区别:
1 | bind --------> beforeMount |
2,在 vue3.x 中,可以使用如下方式实现自定义指令:
1 | const { createApp } from "vue" |
发布时间: 2019-05-16
最后更新: 2021-12-09
本文标题: Vue
本文链接: https://dnhyxc.gitee.io/2019/05/16/vue/
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处!