导航
Vue.observable()<template>
<div>{{ proxyObj.name }}</div>
</template>
<script>
import { reactive } from 'vue';
export default {
name: 'App',
setup() {
const proxyObj = reactive({
name: 'Lance',
age: 233
});
console.log(proxyObj);
return {
proxyObj
}
}
}
</script>

<template></template>
<script>
import { reactive } from 'vue';
export default {
name: 'App',
setup() {
const obj = reactive(1); // 无法包装基本类型
}
}
</script>

reactive() API 有两条限制:
let state = reactive({ count: 0 })
// 上面的引用 ({ count: 0 }) 将不再被追踪(响应性连接已丢失!)
state = reactive({ count: 1 })
同时这也意味着当我们将响应式对象的属性赋值或解构至本地变量时,或是将该属性传入一个函数时,我们会失去响应性:
const state = reactive({ count: 0 })
// n 是一个局部变量,同 state.count
// 失去响应性连接
let n = state.count
// 不影响原始的 state n++
// count 也和 state.count 失去了响应性连接
let { count } = state
// 不会影响原始的 state
count++
// 该函数接收一个普通数字,并且
// 将无法跟踪 state.count 的变化
callSomeFunction(state.count)
这样赋值页面是不会变化的因为会脱离响应式
let person = reactive<number[]>([]);
setTimeout(() => {
person = [1, 2, 3];
console.log(person);
}, 1000);
解决方案:
import { reactive } from 'vue';
let person = reactive<number[]>([]);
setTimeout(() => {
const arr = [1, 2, 3];
person.push(...arr);
console.log(person);
},1000)
type Person = {
list?:Array<number>
}
let person = reactive<Person>({
list: []
});
setTimeout(() => {
const arr = [1, 2, 3];
person.list = arr;
console.log(person);
}, 1000);
.value 的方式读写属性.value 访问<template>
<div>{{ count }}</div>
</template>
<script>
import { ref } from 'vue';
export default {
name: 'App',
setup() {
const count = ref(0);
console.log("count:", count);
console.log("===");
console.log("count.value:", count.value);
console.log("===");
const obj = ref({
name: 'Lance',
age: 233,
info: {
grade: 120
}
});
console.log("obj", obj);
console.log("===");
console.log("obj.value", obj.value); // 第一层需要 .value 拆包
console.log("===");
console.log("obj.value.info", obj.value.info); // 后续都是 Proxy 对象了,不用拆包
console.log("===");
console.log("obj.value.info.grade", obj.value.info.grade);
return {
count,
obj
}
}
}
</script>

.value 了<template>
<div>{{ proxyObj.count }}</div>
</template>
<script>
import { ref, reactive } from 'vue';
export default {
name: 'App',
setup() {
const count = ref(0);
const proxyObj = reactive({
name: 'Lance',
age: 233,
count // 相当于vue给你解包了:count: count.value
});
console.log(proxyObj.count); // 所以此处不用再 .value,template 中 也不用
return {
proxyObj
}
}
}
</script>
<template>
<div>{{ count }}</div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
name: 'App',
setup() {
const count = ref(0);
const state = reactive({
count
});
const newCount = ref(1);
state.count = newCount; // 新的ref替换旧的ref
console.log("state.count:", state.count); // 新的会覆盖旧的
console.log("count:", count.value); // 原来的不变
return {
count,
state
}
}
}
</script>

<template>
<div>{{ count }}</div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
name: 'App',
setup() {
const count = ref(0);
const arr = reactive([count]);
console.log(arr[0].value); // 需要手动拆包
const map = reactive( new Map( [['name', ref(233)]] ) );
console.log(map.get('name').value); // 需要手动拆包
return {
count
}
}
}
</script>

.value 值;否则就返回原值<template></template>
<script>
import { isRef, ref } from 'vue';
export default {
name: 'App',
setup() {
const info = {
name: 'Lance',
age: 233
};
const refInfo = ref({
name: 'GC',
age: 111
});
const obj = isRef(info) ? info.value : info;
const obj2 = isRef(refInfo) ? refInfo.value : refInfo;
console.log(obj);
console.log(obj2);
}
}
</script>

<template>
<div></div>
</template>
<script>
import { ref, unref } from 'vue';
export default {
name: 'App',
setup() {
const info = {
name: 'Lance',
age: 2333
};
const refInfo = ref({
name: 'GC',
age: 111
});
const obj = unref(info); // 返回原始对象
const obj2 = unref(refInfo); // 会拆包,返回 Proxy 对象
console.log(obj);
console.log(obj2);
}
}
</script>

<template></template>
<script>
import { reactive, toRef } from 'vue';
export default {
name: 'App',
setup() {
const state = reactive({
name: 'Lance'
});
const nameRef = toRef(state, 'name');
nameRef.value = 'GC';
console.log(state.name); // 同步更新了
state.name = 'Lance';
console.log(nameRef.value); // 也更新了
}
}
</script>
<template></template>
<script>
import { reactive, toRef } from 'vue';
function useDoSth(name) {
return `My name is ${name.value}`;
}
export default {
name: 'App',
setup() {
const state = reactive({
name: 'Lance'
});
const nameRef = toRef(state, 'name');
const sentence = useDoSth(nameRef);
console.log(sentence);
}
}
</script>

<template></template>
<script>
import { reactive, toRefs } from 'vue';
export default {
name: 'App',
setup() {
const state = reactive({
name: 'Lance',
age: 233,
info: {
grade: 100
}
});
const stateRefs = toRefs(state);
console.log(stateRefs);
console.log(stateRefs.name.value);
}
}
</script>

<template>
<div>
<!-- 通过 reactive 访问属性 -->
<div>{{ state.name }}</div>
<!-- 通过 toRefs reactive 之后越过对象名直接访问属性 -->
<div>{{ name }}</div>
</div>
</template>
<script>
import { reactive, toRefs } from 'vue';
export default {
name: 'App',
setup() {
const state = reactive({
name: 'Lance',
age: 233,
info: {
grade: 100
}
});
const stateRefs = toRefs(state);
return {
state,
...stateRefs
}
}
}
</script>

<template></template>
<script>
import { reactive, toRefs, isRef } from 'vue';
export default {
name: 'App',
setup() {
const state = reactive({
name: 'Lance',
age: 233,
info: {
grade: 100
}
});
const stateRefs = toRefs(state);
console.log("isRef(stateRefs):", isRef(stateRefs));
console.log("isRef(stateRefs.name):", isRef(stateRefs.name));
return {
state,
...stateRefs
}
}
}
</script>

<template>
<div>
<span>{{ text }}</span>
<input type="text" v-model="text">
</div>
</template>
<script>
import { customRef } from 'vue';
/**
* value: 值
* delay: 延迟
*/
function useDebounce(value, delay = 200) {
let t = null;
// 返回 customRef, customRef 接收一个工厂函数
/**
* track: getter访问时执行
* trigger: setter触发更新时执行
*/
return customRef((track, trigger) => {
// 返回一个对象, 包含 getter、setter
return {
get() {
track();
return value;
},
set(newVal) {
clearTimeout(t);
t = setTimeout(() => {
value = newVal;
trigger();
}, delay);
}
}
});
}
export default {
name: 'App',
setup() {
const text = useDebounce('', 500);
return {
text
}
}
}
</script>
