一、vue3的基本介绍及项目创建
Vue是一套用于构建用户界面的
渐进式框架
。Vue.js 3.0 “One Piece” 正式版在2020年9月份发布,经过了2年多开发, 100+位贡献者, 2600+次提交, 600+次PR,同时Vue3也支持Vue2的大多数特性,且,更好的支持了TypeScript,也增加了很多的新特性,如:Composition API,新组件(Fragment/Teleport/Suspense)等等
详细介绍以及项目创建方式,可见之前发布的文章——
二、常用的组合API(setup、ref、reactive)
(一)setup
- 新的option, 所有的组合API函数都在此使用, 只在初始化时执行一次
- 函数如果返回对象, 对象中的属性或方法, 模板中可以直接使用
export default {
name: "toRefs",
setup () {
let a = 6
return {
a
},
}
}
(二)ref
● 作用: 定义一个数据的响应式
●语法: const xxx = ref(initValue):
○创建一个包含响应式数据的引用(reference)对象
○js中操作数据: xxx.value
○模板中操作数据: 不需要.value
●一般用来定义一个基本类型的响应式数据
<template>
<h2>{{count}}</h2>
<hr>
<button @click="update">更新</button>
</template>
<script>
import {
ref
} from 'vue'
export default {
/* 在Vue3中依然可以使用data和methods配置, 但建议使用其新语法实现 */
// data () {
// return {
// count: 0
// }
// },
// methods: {
// update () {
// this.count++
// }
// }
/* 使用vue3的composition API */
setup () {
// 定义响应式数据 ref对象
const count = ref(1)
console.log(count)
// 更新响应式数据的函数
function update () {
// alert('update')
count.value = count.value + 1
}
return {
count,
update
}
}
}
</script>
(三)reactive
- 作用: 定义多个数据的响应式
- const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
- 响应式转换是“深层的”:会影响对象内部所有嵌套的属性
- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的
<template>
<h2>name: {{state.name}}</h2>
<h2>age: {{state.age}}</h2>
<h2>wife: {{state.wife}}</h2>
<hr>
<button @click="update">更新</button>
</template>
<script>
/*
reactive:
作用: 定义多个数据的响应式
const proxy = reactive(obj): 接收一个普通对象然后返回该普通对象的响应式代理器对象
响应式转换是“深层的”:会影响对象内部所有嵌套的属性
内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据都是响应式的
*/
import {
reactive,
} from 'vue'
export default {
setup () {
/*
定义响应式数据对象
*/
const state = reactive({
name: 'tom',
age: 25,
wife: {
name: 'marry',
age: 22
},
})
console.log(state, state.wife)
const update = () => {
state.name += '--'
state.age += 1
state.wife.name += '++'
state.wife.age += 2
}
return {
state,
update,
}
}
}
</script>
以上三者的细节出可跳转到之前的文章——
三、比较Vue2与Vue3的响应式
(一)Vue2
- 对象: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
- 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
(二)Vue3
- 通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等…
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
- 通过 Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
1.Reflect.get(target, propertyKey)
参数 (1)target:需要取值的目标对象
(2)propertyKey:需要获取的值的键值
(3)返回值:属性的值
2.Reflect.set(target, propertyKey, value)
参数 (1)target:设置属性的目标对象。
(2)propertyKey:设置的属性的名称。
(3) value:设置的值
(4)返回值:返回一个 Boolean 值表明是否成功设置属性。
详情请跳转到之前发布的文章——
四、计算属性与监视
-
computed函数:
- 与computed配置功能一致
- 有getter和setter
-
watch函数
- 与watch配置功能一致
- 只有getter
- 监视指定的一个或多个响应式数据, 一旦数据变化, 就自动执行监视回调
- 默认初始时不执行回调, 但可以通过配置immediate为true, 来指定初始时立即执行第一次
- 通过配置deep为true, 来指定深度监视
-
watchEffect函数
- 不用直接指定要监视的数据, 回调函数中使用的哪些响应式数据就监视哪些响应式数据
- 默认初始时就会执行第一次, 从而可以收集需要监视的数据
- 监视数据发生变化时回调
详情请跳转到——
五、Vue3与Vue2的生命周期对比
与 2.x 版本生命周期相对应的组合式 API
-
beforeCreate -> 使用
setup()
-
created -> 使用
setup()
-
beforeMount ->
onBeforeMount
-
mounted ->
onMounted
-
beforeUpdate ->
onBeforeUpdate
-
updated ->
onUpdated
-
beforeDestroy ->
onBeforeUnmount
-
destroyed ->
onUnmounted
-
errorCaptured ->
onErrorCaptured
新增的钩子函数
组合式 API 还提供了以下调试钩子函数:
- onRenderTracked
- onRenderTriggered
六、自定义hook函数
- 使用Vue3的组合API封装的可复用的功能函数
- 自定义hook的作用类似于vue2中的mixin(混入)技术
- 自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂
- 需求1: 收集用户鼠标点击的页面坐标hooks/useMousePosition.ts
1.创建一个hook函数的ts文件
import { ref, onMounted, onUnmounted } from 'vue'
/*
收集用户鼠标点击的页面坐标
*/
export default function useMousePosition () {
// 初始化坐标数据
const x = ref(-1)
const y = ref(-1)
// 用于收集点击事件坐标的函数
const updatePosition = (e: MouseEvent) => {
x.value = e.pageX
y.value = e.pageY
}
// 挂载后绑定点击监听
onMounted(() => {
document.addEventListener('click', updatePosition)
})
// 卸载前解绑点击监听
onUnmounted(() => {
document.removeEventListener('click', updatePosition)
})
return {x, y}
}
2.在需要的页面引入即可使用hook中的数据及方法
<template>
<div>
<h2>x: {{x}}, y: {{y}}</h2>
</div>
</template>
<script>
import {
ref
} from "vue"
/*
在组件中引入并使用自定义hook
自定义hook的作用类似于vue2中的mixin技术
自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂
*/
import useMousePosition from './hooks/useMousePosition'
export default {
setup() {
const {x, y} = useMousePosition()
return {
x,
y,
}
}
}
</script>
七、toRefs
把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref
应用:
当从合成函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应式的情况下对返回的对象进行分解使用
问题:
reactive 对象取出的所有属性值都是非响应式的
解决:
利用 toRefs 可以将一个响应式 reactive 对象的所有原始属性转换为响应式的 ref 属性
<template>
<h2>App</h2>
<h3>foo: {{foo}}</h3>
<h3>bar: {{bar}}</h3>
<h3>foo2: {{foo2}}</h3>
<h3>bar2: {{bar2}}</h3>
</template>
<script lang="ts">
import { reactive, toRefs } from 'vue'
/*
toRefs:
将响应式对象中所有属性包装为ref对象, 并返回包含这些ref对象的普通对象
应用: 当从合成函数返回响应式对象时,toRefs 非常有用,
这样消费组件就可以在不丢失响应式的情况下对返回的对象进行分解使用
*/
export default {
setup () {
const state = reactive({
foo: 'a',
bar: 'b',
})
const stateAsRefs = toRefs(state)
setTimeout(() => {
state.foo += '++'
state.bar += '++'
}, 2000);
const {foo2, bar2} = useReatureX()
return {
// ...state,
...stateAsRefs,
foo2,
bar2
}
},
}
function useReatureX() {
const state = reactive({
foo2: 'a',
bar2: 'b',
})
setTimeout(() => {
state.foo2 += '++'
state.bar2 += '++'
}, 2000);
return toRefs(state)
}
</script>
八、ref获取元素
注意:在script的标签内要加入
lang=”ts”
利用ref函数获取组件中的标签元素
注意:声明一个 ref 来存放该元素的引用
必须和模板里的 ref 同名
功能需求: 让输入框自动获取焦点
<template>
<h2>App</h2>
<input type="text">---
<input type="text" ref="inputRef">
</template>
<script lang="ts">
import { onMounted, ref } from 'vue'
/*
ref获取元素: 利用ref函数获取组件中的标签元素
功能需求: 让输入框自动获取焦点
*/
export default {
setup() {
//声明一个 ref 来存放该元素的引用
//必须和模板里的 ref 同名
const inputRef = ref<HTMLElement|null>(null)
onMounted(() => {
inputRef.value && inputRef.value.focus()
})
return {
inputRef
}
},
}
</script>
九、Vue3中是否使用<script setup>父子传参的不同(重点)
个人认为这是Vue3中很重要的一个点,而且当你熟悉了以后会发现他真的比Vue2方便好多,其中详情请跳转到单独的文章——