1. Composition API(常用部分)
文檔:
setup
- 新的option, 所有的組合API函數(shù)都在此使用, 只在初始化時執(zhí)行一次
- 函數(shù)如果返回對象, 對象中的屬性或方法, 模板中可以直接使用
ref
- 作用: 定義一個數(shù)據(jù)的響應式
- 語法: const xxx = ref(initValue):
- 創(chuàng)建一個包含響應式數(shù)據(jù)的引用(reference)對象
- js中操作數(shù)據(jù): xxx.value
- 模板中操作數(shù)據(jù): 不需要.value
- 一般用來定義一個基本類型的響應式數(shù)據(jù)
<template>
<h2>{{count}}</h2>
<hr>
<button @click="update">更新</button>
</template>
<script>
import {
ref
} from 'vue'
export default {
/* 在Vue3中依然可以使用data和methods配置, 但建議使用其新語法實現(xiàn) */
// data () {
// return {
// count: 0
// }
// },
// methods: {
// update () {
// this.count++
// }
// }
/* 使用vue3的composition API */
setup () {
// 定義響應式數(shù)據(jù) ref對象
const count = ref(1)
console.log(count)
// 更新響應式數(shù)據(jù)的函數(shù)
function update () {
// alert('update')
count.value = count.value + 1
}
return {
count,
update
}
}
}
</script>
3) reactive
- 作用: 定義多個數(shù)據(jù)的響應式
- const proxy = reactive(obj): 接收一個普通對象然后返回該普通對象的響應式代理器對象
- 響應式轉換是“深層的”:會影響對象內部所有嵌套的屬性
- 內部基于 ES6 的 Proxy 實現(xiàn)梢睛,通過代理對象操作源對象內部數(shù)據(jù)都是響應式的
<template>
<h2>name: {{state.name}}</h2>
<h2>age: {{state.age}}</h2>
<h2>wife: {{state.wife}}</h2>
<hr>
<button @click="update">更新</button>
</template>
<script>
/*
reactive:
作用: 定義多個數(shù)據(jù)的響應式
const proxy = reactive(obj): 接收一個普通對象然后返回該普通對象的響應式代理器對象
響應式轉換是“深層的”:會影響對象內部所有嵌套的屬性
內部基于 ES6 的 Proxy 實現(xiàn)皿淋,通過代理對象操作源對象內部數(shù)據(jù)都是響應式的
*/
import {
reactive,
} from 'vue'
export default {
setup () {
/*
定義響應式數(shù)據(jù)對象
*/
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>
shallowRef and shallowReactive
shallowReactive : 只處理了對象內最外層屬性的響應式(也就是淺響應式)
shallowRef: 只處理了value的響應式, 不進行對象的reactive處理
什么時候用淺響應式呢?
一般情況下使用ref和reactive即可
如果有一個對象數(shù)據(jù), 結構比較深, 但變化時只是外層屬性變化 ===> shallowReactive
如果有一個對象數(shù)據(jù), 后面會產生新的對象來替換 ===> shallowRef
<template>
<div>
<div>
<p>{{ counter.name }}</p>
<button @click="handleCounter">add</button>
</div>
<div>
<p>{{ user.name }}</p>
<p>{{ user.age }}</p>
<p>{{ user.hobby }}</p>
<p>{{ user.child.value }}</p>
<button @click="updateUser">update</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, shallowReactive, shallowRef } from 'vue';
export default defineComponent({
setup() {
// const counter = shallowRef(0);
const counter = shallowRef({
name: 'wanglizhi'
});
const user = shallowReactive({
name: 'wanglizhi',
age: 18,
child: {
id: 1,
value: '11',
},
hobby: ['唱歌', '跳舞'],
});
function handleCounter() {
counter.value.name = 'Leo';
console.log(counter)
}
function updateUser() {
// user.name = 'Leo';
// user.age = 20;
user.hobby[0] = '吃飯';
user.child.value = '222';
console.log(user)
}
return {
counter,
user,
handleCounter,
updateUser,
};
},
});
</script>
<style></style>
readonly and shallowReadonly
readonly:
深度只讀數(shù)據(jù)
獲取一個對象 (響應式或純對象) 或 ref 并返回原始代理的只讀代理溃斋。
只讀代理是深層的:訪問的任何嵌套 property 也是只讀的恤左。
shallowReadonly
淺只讀數(shù)據(jù)
創(chuàng)建一個代理缆巧,使其自身的 property 為只讀,但不執(zhí)行嵌套對象的深度只讀轉換
應用場景:
在某些特定情況下, 我們可能不希望對數(shù)據(jù)進行更新的操作, 那就可以包裝生成一個只讀代理對象來讀取數(shù)據(jù), 而不能修改或刪除
<template>
<div>
<div>
<p>{{ JSON.stringify(state) }}</p>
<button @click="update">update</button>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, readonly, shallowReadonly } from 'vue';
export default defineComponent({
setup() {
const state = shallowReadonly({
name: 'wanglizhi',
age: 18,
child: {
name: 'xiaowang',
age: 10,
child: {
name: 'wang',
age: 1
}
}
})
function update() {
state.name = 'Leo';
state.child.name = 'Leo1';
state.child.child.name = 'Leo2';
console.log(state)
}
return {
state,
update,
};
},
});
</script>
<style></style>
toRaw and markRaw
toRaw
返回由 reactive 或 readonly 方法轉換成響應式代理的普通對象狡忙。
這是一個還原方法燎竖,可用于臨時讀取,訪問不會被代理/跟蹤哥捕,寫入時也不會觸發(fā)界面更新牧抽。
markRaw
標記一個對象,使其永遠不會轉換為代理遥赚。返回對象本身
應用場景:
有些值不應被設置為響應式的扬舒,例如復雜的第三方類實例或 Vue 組件對象。
當渲染具有不可變數(shù)據(jù)源的大列表時凫佛,跳過代理轉換可以提高性能讲坎。
<template>
<div>
<h2>toRaw and markRow</h2>
<div>
<p>{{ JSON.stringify(state) }}</p>
<button @click="update">update</button>
</div>
<hr>
</div>
</template>
<script lang="ts">
import { defineComponent, toRaw, markRaw, reactive } from 'vue';
export default defineComponent({
setup() {
const obj = {
name: 'wanglizhi',
age: 18,
child: {
name: 'xiaowang',
age: 10,
child: {
name: 'wang',
age: 1,
},
},
};
const obj3 = markRaw(obj);
const state = reactive(obj3);
const obj2 = toRaw(state);
function update() {
state.name = 'Leo';
state.child.name = 'Leo1';
state.child.child.name = 'Leo2';
console.log('obj', obj);
console.log('state', state);
console.log('obj2', obj2);
console.log(obj === state)
console.log(obj2 === obj2)
}
return {
state,
update,
};
},
});
</script>
<style></style>
toRef 孕惜、toRefs、 isRef and unref
toRef
為源響應式對象上的某個屬性創(chuàng)建一個 ref對象, 二者內部操作的是同一個數(shù)據(jù)值, 更新時二者是同步的
區(qū)別ref: 拷貝了一份新的數(shù)據(jù)值單獨操作, 更新時相互不影響
應用: 當要將 某個prop 的 ref 傳遞給復合函數(shù)時晨炕,toRef 很有用
toRefs
將響應式對象轉換為普通對象衫画,其中結果對象的每個 property 都是指向原始對象相應 property 的ref
。
isRef
判斷是否為ref
unref
如果參數(shù)為 ref
瓮栗,則返回內部值削罩,否則返回參數(shù)本身。這是 val = isRef(val) ? val.value : val
费奸。
<template>
<div>
<h2>toRef and toRefs</h2>
<div>
<p>{{ JSON.stringify(state) }}</p>
<button @click="update">update</button>
</div>
<hr>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRef, toRefs, isRef, unref } from 'vue';
export default defineComponent({
setup() {
const obj = {
name: 'wanglizhi',
age: 18,
child: {
name: 'xiaowang',
age: 10,
child: {
name: 'wang',
age: 1,
},
},
};
const state = reactive(obj);
const obj2 = toRef(state, 'name');
const obj3 = toRefs(state)
function update() {
// state.name = 'Leo';
// state.child.name = 'Leo1';
// state.child.child.name = 'Leo2';
// obj2.value = 'haha'
obj3.name.value = 'hehe'
console.log('obj', obj);
console.log('state', state);
console.log('obj2', obj2);
console.log('obj3', obj3);
console.log(isRef(state))
// console.log(isRef(obj2))
// console.log(isRef(obj3))
// console.log(isRef(obj3.name))
// console.log(unref(state))
// console.log(unref(obj2))
}
return {
state,
update,
};
},
});
</script>
<style></style>