反应系统
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>
|