反应系统

javascript: proxy 与 reflect
javascript 可以基于一个对象去创建 proxy 对象,这样就可以去拦截对这个对象的一些操作了,比如说访问或设置这个对象的属性的时候,就可以做一些额外的检查。

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
28
29
30
31
created() {
const user = {
name: '嘻嘻',
};

//handler就是处理器,在里面你可以拦截处理对象的行为,target就是对象,property是属性名字,value是具体的值
const handler = {
get(target, property) {
return target[property];
},
set(target, property, value) {
if (property == 'name') {
if (value.length > 10) {
throw new Error('名字好长');
}
}

return Reflect.set(target, property, value); //默认的设置属性的行为
},
};
const userProxy = new Proxy(user, handler);

try {
userProxy.name = '哈哈哈哈哈哈哈';
} catch (error) {
console.log('错误', error.message);
}

console.log(userProxy.name);
},
};

理解反应系统
我们在组件里添加的数据,绑定在模板上去使用,数据发生变化后,组件会重新渲染,显示更新后的内容。用的是 javascript 里的 proxy,proxy 可以拦截处理对象的行为。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<h3>{{ name }}</h3>
</template>

<script>
export default {
data() {
return {
name: 'nihao~',
};
},
created() {
console.log(this.$data);
},
};
</script>

打印出来的就是一个 proxy 对象。


composition API:组合式接口
之前创建 vue 组件用的是 optionsAPI 选项式的接口,就是在组件里使用 data,computed,methods,watch 等。vue3 提供了新的创建组件的方法,就是使用 compostionAPI,可以翻译成组合式接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<h3>{{ name }}</h3>
</template>

<script>
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = '哈哈';
return {
name,
};
},
};
</script>

<style>
@import './styles/app.css';
</style>

声明具有反应特性的数据
在 setup 里返回的数据不具有反应的特性,如果你想让单个属性具有反应特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<h3 @click="name = 'xixi'">{{ name }}</h3>
</template>

<script>
import { ref } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

//用ref处理后的得到的数据里有个value属性,这个属性的值就是字符串本身
console.log(name.value);
return {
name,
};
},
};
</script>

声明具有反应特性的数据
如果你想让某个对象具有反应特性,可以使用 reactive。

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
<template>
<h3 @click="name = 'xixi'">{{ name }}</h3>
<div @click="user.name = 'cxncxn'">{{ user.name }}</div>
</template>

<script>
import { reactive, ref } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const user = reactive({
name: 'cxn',
});
console.log(user);

//用ref处理后的得到的数据里有个value属性,这个属性的值就是字符串本身
console.log(name.value);
return {
name,
user,
};
},
};
</script>

解构反应数据
需要使用 toRefs。

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
<template>
<h3 @click="name = 'xixi'">{{ name }}</h3>
<div @click="username = 'cxncxn'">{{ username }}</div>
</template>

<script>
import { reactive, ref, toRefs } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const user = reactive({
username: 'cxn',
});
console.log(user);

// const { username } = toRefs(user); //第一种结构方法

return {
name,
...toRefs(user), //第二种更简便的方法,使用展开运算符。
};
},
};
</script>

组合接口

提供组件方法
使用选项 API,定义方法需要先用 methods,在组合式接口中定义方法是这样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<h3 @click="changeName">{{ name }}</h3>
</template>

<script>
import { reactive, ref, toRefs } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const changeName = () => {
name.value = '咕咕';
};

return {
name,
changeName,
};
},
};
</script>

生命周期方法
在选项式接口中,使用生命周期方法就是添加 created、mounted 等方法。在 compositionAPI 中不需要 created 这个生命周期方法, 你可以直接把要在 created 做的事情写在 setup 里。

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
<template>
<h3 @click="changeName">{{ name }}</h3>
</template>

<script>
import { ref, onMounted } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const changeName = () => {
name.value = '咕咕';
};

//生命周期
onMounted(() => {
console.log('mounted');
});

return {
name,
changeName,
};
},
};
</script>

监视数据
在 optionsAPI 里你可以把监视器放在 watch 里面,在 composition 创建监视器是这样的。

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
28
29
30
31
32
<template>
<h3 @click="changeName">{{ name }}</h3>
</template>

<script>
import { ref, onMounted, watch } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const changeName = () => {
name.value = '咕咕';
};

//生命周期
onMounted(() => {
console.log('mounted');
});

// 监视数据
watch(name, (newName, oldName) => {
console.log(newName, oldName);
});

return {
name,
changeName,
};
},
};
</script>

计算属性
在 optionsAPI 里使用 computed,在 comPositionAPI 创建的组件是这样的。

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
28
29
30
31
32
33
34
35
36
<template>
<h3 @click="changeName">{{ nameEmoji }}</h3>
</template>

<script>
import { ref, onMounted, watch, computed } from 'vue';
export default {
setup() {
//compositionAPI 的一个入口,组件在创建前会执行这个方法
const name = ref('哈哈');

const changeName = () => {
name.value = '咕咕';
};

//生命周期
onMounted(() => {
console.log('mounted');
});

// 监视数据
watch(name, (newName, oldName) => {
console.log(newName, oldName);
});

//计算属性
const nameEmoji = computed(() => `${name.value}😝`);

return {
name,
changeName,
nameEmoji,
};
},
};
</script>