Vue技能
本文最后更新于:8 个月前
熟练使用Vue框架的API,称之为“Vue技能”
Vue技能
一、setup() 和 script setup
1. setup()
setup()
是Vue3独有的生命周期钩子函数,是组件中使用「组合式API」的入口,位于beforeCreate()
之前;setup()
需要返回一个对象1
2
3
4
5
6
7
8
9
10export default{
setup(){
const count = ref(0)
function increase() { count.value++ }
return {
count,
increase,
}
}
}在
setup()
自身没有对组件实例的访问权,this
为undefined
,因为它在beforeCreate()
之前,所以此时实例还不存在。如果在业务逻辑中需要获取组件实例,可以通过getCurrentInstance()
方法1
2
3
4
5
6
7
8import {ref, getCurrentInstance} from 'vue'
export default {
setup() {
const {proxy, ctx} = getCurrentInstance()
const _this = ctx
...
}
}setup()
中返回的对象可以在其它钩子函数中使用,但是反过来不行。(从setup()
返回ref时,会自动解析,所以在setup之外不用再写.value
1
2
3
4
5
6
7
8
9
10
11export default {
setup(){
const count = ref(0)
return {
count
}
},
mounted(){
console.log(this.count)
}
}setup()
有两个参数,分别是props,和上下文对象1
2
3
4
5
6
7
8export default {
setup(props, context){
// 将 `props` 转为一个其中全是 ref 的对象,然后解构
const { title } = toRefs(props)
// context是上下文对象
}
}
2. script setup
<script setup>
是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖,推荐在SFC中使用,<script setup>
里面的内容会被编译成组件setup()
函数的内容。
<script setup>
顶层声明的绑定(变量、函数、import导入的内容)会暴露给模板<script setup>
中不需要显式地返回对象1
2
3
4
5
6
7
8
9
10
11
12
13<script setup>
import { ref } from 'vue'
import { capitalize } from './helpers'
const msg = ref('Hello!')
function log() {
console.log(msg)
}
</script>
<template>
<button @click="log">{{ msg }}</button>
<div>{{ capitalize('hello') }} </div>
</template>使用自定义指令,不需要显式注册
1
2
3
4
5
6
7
8
9
10<script setup>
const vMyDirective = {
beforeMount: (el) => {
// 在元素上做些操作
}
}
</script>
<template>
<h1 v-my-directive>This is a Heading</h1>
</template>更多内容:script setup
二、computed 和 watch
computed | watch | |
---|---|---|
作用 | 计算属性,响应式依赖其它属性计算值,有缓存(“临时快照”) | 侦听属性,监听值的变化,变化时触发回调 |
适用场景 | 模板中需要计算的复杂属性 | 观测值的变化,而完成指定的业务逻辑 |
watch侦听数据源:
- ref、reactive、computed对象(不能是对象的属性)
- getter函数
- 多个上述数据源组成的数组
watch侦听深度
- 对响应式对象,默认是深层侦听
- 对getter函数,默认是浅层侦听,即只有返回不同的对象才触发回调
1
2
3
4
5
6
7
8watch(()=>state.obj1, (newValue, oldValue)=>{
...//回调函数
})
// 只有当返回另一个对象时,才触发,obj1内部属性发生变化不触发,可以通过添加deep参数强制转换成深层监听,如下
watch(()=>state.obj1, (newValue, oldValue)=>{
...//回调函数
}, {deep:true})watch立即回调,默认刚添加回调时是不执行的,可以通过
immediate
参数强制立即执行一次1
2
3watch(source, (newValue, oldValue) => {
// 立即执行,且当 `source` 改变时再次执行
}, { immediate: true })watchEffect,自动侦听副作用函数中的依赖,不需要显式声明监听的对象
watch,只能侦听指定的对象
1
2
3
4
5
6
7
8
9
10// 侦听todoId, watch写法
const todoId = ref(1)
const data = ref(null)
watch(todoId, async () => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
}, { immediate: true })1
2
3
4
5
6
7// 侦听todoId,watchEffect写法
watchEffect(async ()=>{
const response = await fetch(
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
data.value = await response.json()
})
三、v-if 和 v-show
v-if | v-show | |
---|---|---|
作用 | 判断是否渲染节点 | 判断是否隐藏节点(已经渲染) |
控制手段 | 添加 / 删除 dom元素 | 为元素添加 display:none |
编译过程 | 有一个局部编译 / 卸载 的过程 | 基于css切换 |
触发生命周期 | false -> true,触发beforeCreate、created、beforeMount、mounted true -> false,触发beforeDestory、destoryed | 不触发生命周期钩子 |
性能消耗 | 更高的切换消耗 | 更高的初始渲染消耗 |
适用场景 | 不需要频繁切换条件 | 频繁切换条件 |
四、v-model
本质是语法糖,v-bind
与DOM事件监听 的结合。它在内部为不同的组件绑定了参数,并抛出不同的事件
元素 | 动态绑定的参数 | 自动监听的事件 |
---|---|---|
text, textarea | value | input |
checkbox, radio | checked | chagne |
select | value | change |
1 |
|
五、nextTick
1 |
|
Vue中更改响应式状态后,DOM不是立即更新的,而是先缓存到队列中,等到下一个tick
一起执行。nextTick()
在DOM状态改变后立即调用。以下是两种使用方式:
将回调函数传入
nextTick()
的参数1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<script setup>
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
count.value++
// DOM 还未更新
console.log(document.getElementById('counter').textContent) // 0
nextTick(()=>{
console.log(document.getElementById('counter').textContent) // 1
})
}
</script>
<template>
<button id="counter" @click="increment">{{ count }}</button>
</template>await nextTick()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<script setup>
import { ref, nextTick } from 'vue'
const count = ref(0)
async function increment() {
count.value++
// DOM 还未更新
console.log(document.getElementById('counter').textContent) // 0
await nextTick()
// DOM 此时已经更新
console.log(document.getElementById('counter').textContent) // 1
}
</script>
<template>
<button id="counter" @click="increment">{{ count }}</button>
</template>
六、Mixin
抽离公共的业务逻辑,当组件初始化时,按照默认或者自定义的策略进行合并,类似于“对象的继承”
在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立,可以通过 Vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
用法示例(以下使用的是Vue2的声明式API语法)
1 |
|
1 |
|
Vue3不推荐使用Mixin,而是用「组合式函数」替代
七、内置指令
以下列举5个最常用的内置指令,仔细阅读文档,你会发现有很多你未知的用法
1. v-on
- 用途,给元素绑定事件
- 接受的值类型:函数名、内联表达式、对象
- 缩写:
@
- 修饰符:
.stop
,调用event.stopPropagation()
,阻止事件在DOM中继续传播,即阻击下一步的捕获或冒泡阶段.prevent
,调用event.preventDeafult()
,阻止浏览器原生的事件行为.once
,只触发一次处理函数- 其它…
1 |
|
2. v-once
v-once不是v-on.once,而是指元素和组件只渲染一次!
- 用途:声明仅渲染元素和组件一次,并跳过之后的更新。
- 作用:在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。
3. v-bind
- 用途,动态绑定class、attribute、组件的prop
- 缩写:
:
- 修饰符:不是很常用
4. v-model
用途,在「表单输入元素」或「组件」上创建双向绑定
使用范围,
<input>
、<textarea>
、<select>
、自定义组件修饰符(重点!)
.lazy
- 监听change事件而非inpput事件.trim
- 移除输入内容前后的空格(不能自己傻傻去处理了).number
- 将输入的合法字符转为数字
5. v-html
将标签之间的内容作为HTML直接插入。(1)慎用,防止XSS攻击!(2)v-html的内容无法使用scoped的样式
1 |
|
八、自定义指令
1. 作用
自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑
2. 使用方法
一个自定义指令由一个包含类似组件生命周期钩子的对象来定义。钩子函数会接收到指令所绑定元素作为其参数。
eg:自定义focus指令,当input元素被插入到DOM中后,被自动聚焦
1 |
|
在没有使用scipt setup的情况下,需要通过directives选项来注册
1 |
|
也可以注册到全局
1 |
|
- keep-alive
- 组件通信方式
- 生命周期钩子