Vue3
# Vue3.0工程
# Vue-cli创建
# 查看@vue/cli版本,保证@vue/cli版本在4.5.0以上
vue --version
vue -V
# 安装或者升级@vue/cli
npm install -g @vue/cli
# 创建项目
vue create <project-name>
# 启动
cd <project-name>
npm run serve
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# Vite创建
npm init vite-app vue3_test_vite
npm init vue@latest
1
2
2
# 生命周期
# 组合式API
# 生命周期钩子函数
onBeforeMount /* 在组件被挂载之前被调用 */
onMounted /* 在组件挂载完成后执行 */
onBeforeUpdate /* 在组件即将因为响应式状态变更而更新其 DOM 树之前调用 */
onUpdated /* 在组件因为响应式状态变更而更新其 DOM 树之后调用 */
onBeforeUnmount /* 在组件实例被卸载之前调用 */
onUnmounted /* 在组件实例被卸载之后调用 */
1
2
3
4
5
6
2
3
4
5
6
# setup
- 是所有的
Composition
API(组合API) - 组件中所用到数据方法等均要配置在setup中
- setup两种返回值
- 返回对象
- 返回渲染函数
- setup的参数
- props 值为对象,包含外部传递过来,且组件内部声明接收了的属性
- context 上下文对象
attrs
值为对象,包含组件外部传递过来,但没有在props配置中声明的属性,相当于v2中的this.$attrsslots
收到的插槽内容,相当于this.$slotsemit
分发自定义事件的函数,相当于this.$emit
setup(props,context){
let title = 'hello';
// 对象返回
return{
title,
}
// 渲染函数
return ()=>h('h1','hello')
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
注意
- Vue2配置(data,methods,computed等)中可以访问到setup中的属性,方法
- setup中不能访问Vue2配置(data,methods,computed...)
- 如果Vue2和Vue3中有重名,setup优先
- setup不能是一个async函数,因为返回值不是return对象,而上一个Promise
- setup在beforeCreate之前执行一次,this时undefined
# 核心
# ref()
定义一个响应式的数据
说明
- 接受的数据可以是基本类型,也可以是对象类型
- 基本类型的数据:响应式依然是靠
Object.defineProperty()
的get
与set
完成的 - 对象类型的数据:内容使用了Vue3.0中的一个新函数
reactive
函数 - 模版中使用不需要
.value
<script>
import { ref } from 'vue';
export default {
name: 'App',
data(){
return{}
},
setup(){
let city = ref('北京');
function change(){
city.value = '上海'
}
return{
city
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# computed()
import { computed } from 'vue'
export default{
setup(){
let person = reactive({
firstName:'张',
lastName:'三'
})
// 只读写法
person.getName = computed(function(){
return person.firstName + '-' + person.lastName
})
// 完整写法(读和写)
person.getName = computed({
get(){
return person.firstName + '-' + person.lastName
},
set(value){
// 赋值
person.firstName = value.split(',')[0]
}
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# reactive()
定义一个对象类型的响应式数据
说明
reactive
接受一个对象或数组,代理对象(Proxy的实例对象)- reactive定义的对象是深层次的
- 内部基于ES6的Proxy实现,通过代理对象操作源对象内部数据进行操作
<script>
import { reactive } from 'vue';
export default {
name: 'App',
data(){
return{}
},
setup(){
let citys = reactive(['北京','上海','广州','深圳']);
function change(){
citys[0] = '杭州'
}
return{
citys
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# ref与reactive区别
- 定义数据角度对比
- ref用来定义:
基本类型数据
- reactive用来定义:
对象或数组类型数据
- 注意❗️ :ref也可以用来定义对象或数组类型数据,内部会自动通过
reactive
转为代理对象
- ref用来定义:
- 从原理角度对比
- ref通过
Object.defineProperty()
的get与set来实现响应式(数据劫持) - reactive通过使用
Proxy
来实现响应式(数据劫持),并通过Reflect
操作源对象内部的数据
- ref通过
- 从使用角度对比
- ref定义的数据:操作数据需要
.value
,读取数据时模版直接读取,不需要.value
- reactive定义的数据:操作数据与读取数据都不需要
.value
- ref定义的数据:操作数据需要
# watch() - 监听函数
需要指明监视的属性,也要指明监视的回调
import { ref,reactive,watch} from 'vue'
export default {
setup(){
/**
* {immediate:true,deep:true}
* immediate:true 在第一次进入页面时就会监听
* deep 用来深度监听
*/
// 1.监听ref中定义的一个数据
watch(a,(newVal,oldVal)=>{});
// 2.监听ref中多定义的所有ref数据
watch([a,d],(newVal,oldVal)=>{});
// 3.监听reactive所定义的一个响应式数据中的全部数据
/**
* 1. 无法正确的获取oldVal(若需要获取oldVal,需要将属性设置到ref函数中)
* 2. 强制开启深度监听默认deep:true 设置deep:false无效
*/
watch(c,(newVal,oldVal)=>{},{deep:false});
// 4.监听reactive所定义的一个响应式数据中的某个数据
watch(()=>b.num,(newVal,oldVal)=>{});
// 5.监听reactive所定义的一个响应式数据中的某些数据
watch([()=>b.age,()=>b.num],(newVal,oldVal)=>{});
// 6.监视reactive所定义的对象中的某个属性(对象),需要设置deep:true,否则监视不到
watch(()=>b.work,(newVal,oldVal)=>{},{immediate:true,deep:true});
}
}
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
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
# watchEffect()
不用指明监视哪个属性,回调中用到哪个属性,就监视哪个属性,只要回调中用到的数据发生变化,则直接重新执行回调
watchEffect(()=>{})
1
# 工具
# toRef与toRefs
作用为将响应式中的对象某个属性单独提供给外部使用
- 创建一个ref对象,其中的value值指向另一个对象中的某个属性
toRef
创建单个ref对象,toRefs
批量创建多个ref对象
const x = toRef({},'属性')
const x = toRefs({})
1
2
2
# hook函数
本质是一个函数,把setup中使用的Composition API进行了封装,类似于Vue2中的mixin
- 创建模块文件
import {reactive,onMounted,onBeforeUnmount} from 'vue'
export default function(){
let ponent = reactive({
x:0,
y: 0
})
function savepon(event){
ponent.x = event.pageX
ponent.y = event.pageY
}
onMounted(()=>{
window.addEventListener('click',savepon)
})
onBeforeUnmount(()=>{
window.removeEventListener('click',savepon)
})
return ponent;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 引入
import userPon from '../hooks/userpon'
export default {
setup(){
let ponent = userPon()
return{
ponent
}
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# provide与inject
provide()提供一个值,可以在应用中的所有后代组件中注入使用。用于实现祖组件与后代组件间的通信
// 祖组件
import { provide } from 'vue'
export default {
setup(){
provide('message','hello')
}
}
// 后代组件
import { inject } from 'vue'
export default {
setup(){
// 使用inject接收,后代组件接收的是Proxy格式,是响应式
const x = inject('message')
return {x}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 创建hooks文件
import {reactive,onMounted,onBeforeUnmount} from 'vue'
export default function(){
let point = reactive({
x:0,
y: 0
})
function savePoint(event){
point.x = event.pageX
point.y = event.pageY
}
onMounted(()=>{
window.addEventListener('click',savePoint)
})
onBeforeUnmount(()=>{
window.removeEventListener('click',savePoint)
})
return point;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 引用
import usepoint from './usepoint.js'
export default{
setup(){
const point = usepoint
return{point}
}
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# shallowReactive与shallowRef
shallowReactive
: 只处理对象最外层属性的响应式(浅响应式)。shallowRef
: 只处理基本数据类型的响应式, 不进行对象的响应式处理- 使用场景
- 一个结构对象,有多层结构,但只是最外层属性变化 (
shallowReactive
) - 一个结构对象,后续不会修改对象中的属性,而是生成新的对象来替换 (
shallowRef
)
- 一个结构对象,有多层结构,但只是最外层属性变化 (
# readonly与shallowReadonly
readonly
让一个人响应式数据变为只读
(深只读)。shallowReadonly
让一个响应式数据变为只读
(浅只读,对象中嵌套的多层结构可以修改)
import {readonly,shallowReadonly} from 'vue'
export default {
setup(){
let per = reactive({
name:'东',
age:20,
work:{
num:{
games:100
}
}
})
// 深只读
let person = readonly(per);
// 浅只读
let person = shallowReadonly(per);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# toRaw与markRaw
toRaw
- 作用:将一个由
reactive
生成的响应式对象转为普通对象 - 场景:用于读取响应式对象对应的普通对象,对其所有操作,不会引起页面更新
- 作用:将一个由
markRaw
- 作用: 标记一个对象,使其永远不会再成为响应式对象
- 场景:
- 复杂的第三方库
- 渲染具有不可变数据的大列表,跳过响应式转换可以提高性能
# customRef自定义ref
创建一个自定义的 ref,显式声明对其依赖追踪和更新触发的控制方式。
import { customRef } from 'vue'
export default {
setup(){
function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track() // 通知vue去跟踪value大变化
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger() // 通知Vue重新解析模版
}, delay)
}
}
})
}
const x = useDebouncedRef('hello')
return{
x
}
}
}
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
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
# 判断响应式数据
# isRef()
判断一个值是否为一个ref对象
# isReactive()
检查一个对象是否是由
reactive
创建的响应式代理
# isReadonly()
检查一个对象是否是由
readonly
创建的只读代理
# isProxy()
检查一个对象是否是由
reactive
或者readonly
方法创建的代理
# Composition API的优势
- Options API问题
使用传统Options API当数据复杂时,新增或修改一个需求,就需要在各个函数里面进行修改
- Composition API
通过hook函数将各功能模块拆分出去,增强代码的可维护性
2.x全局API | 3.x实例API |
---|---|
Vue.config.xxx | app.config.xxx |
Vue.congig.productionTip | 移除 |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.globalProperties |
上次更新: 2024/10/09, 16:59:47