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