vue3.0 新特性之 setup

vue3.0 新特性之 setup

  • setup应该如何使用?
    • 生命周期
    • ref, reactive - data
    • setup - methods
    • setup - watch
    • setup参数
    • mixin的优化

setup应该如何使用?

直接定义setup() {} 就可以使用了(doge)
下面将对比2.0的一些使用方式;

需注意:

  1. 由于在执行 setup函数的时候,还没有执行 Created 生命周期方法,所以在 setup 函数中,无法使用 data 和 methods 的变量和方法
  2. setup函数只能是同步的不能是异步的
  3. 返回对象中的属性可直接在模板中使用

生命周期

对比2.0

  1. beforeCreate -> use setup()
  2. created -> use setup()
  3. beforeMount -> onBeforeMount
  4. mounted -> onMounted
  5. beforeUpdate -> onBeforeUpdate
  6. updated -> onUpdated
  7. beforeDestroy -> onBeforeUnmount
  8. destroyed -> onUnmounted
  9. errorCaptured -> onErrorCaptured
import {
     defineComponent,  onBeforeMount,  onMounted,  onBeforeUpdate,
 onUpdated,  onBeforeUnmount,  onUnmounted, onErrorCaptured } from 'vue';

ref, reactive - data

这里以ts版为例:

import {
     defineComponent,  ref, toRefs } from 'vue';
const HelloWorld = defineComponent({
     
 setup(props, context) {
     
   /** 2.0 的data
   * data() {
   			return {
   				age: 20
   			}
   *	}
   */


 	//让目标数据响应式改变,数据改变影响视图(vue2.0的data);有点像react 的 useState的味道
   const name = ref('pika');
   /**
   * 注意点:一次一个值;获取或赋值需要跟上“.value”后缀
   * console.log("data:" + name.value);
   */


    // 当变量过多时 一堆 ref()很繁琐,reactive出现了,传一个对象,键值对的形式定义;返回一个响应式对象
   const testmr = reactive({
     
     name: 'caomingrui -- 咿呀咿呀',
     age: 20
   });
   /**
   * 注意点:传入"{  }",查询赋值操作不需要加上".value"后缀
   * 传入"ref()"对象,后续操作需要解套ref
   * 例: const cmrs = reactive(ref(0));
   * console.log(cmrs.value)
   */

   //reactive对象复杂时,引用起来比较繁琐“{
     { testmr.name }}”
   //torefs就出现了,将reactive创建的响应式对象转化为普通对象,转化后都是ref()类型响应式数据
   const test = toRefs( testmr );
   //你也可以传入普通对象
   
   return {
     
    	name,
    	testmr,
    	...test ,
    	...toRefs( testmr ), //也可以这样
   }
 }
});

export default HelloWorld;

setup - methods

这里以ts版为例:

import {
     defineComponent,  ref, toRefs } from 'vue';
const HelloWorld = defineComponent({
     
 setup(props, context) {
     
   /** 2.0 的 methods
   * methods: {
   			increment () {
   					this.cont ++;
   			}
   *	}
   */
   const count: any = ref(0);
   
   const increment = () => {
     
       count.value ++;
   }
   
   // 你也可以利用computed实现
   const double = computed(() => count.value * 2);
   
   return {
     
       count,
       double,
       increment
   	}

 	}
});

export default HelloWorld;

setup - watch

这里以ts版为例:

import {
     defineComponent,  ref, toRefs } from 'vue';
const HelloWorld = defineComponent({
     
 setup(props, context) {
     
   const name = ref(' 武德 ')const testmr = reactive({
     
     name: 'caomingrui -- 咿呀咿呀',
     age: 20
   }); 
   
   // 你可以:直接放ref
   watch(name, () => {
     
     console.log(name.value);
   })
  	// 也可以:放ref的value值
   watch(() => testmr.name, (val, oldval) => {
     
        console.log(val);
        console.log(oldval);
   })
   
   // 3.0 还有watchEffect
   //它会收集匿名函数内状态,当状态改变时,改函数会再次执行。你也可以通过赋值调用停止监听状态。
   const stop = watchEffect(() => console.log('嘿嘿我出现了' + testmr.name) );
   // 这里测试用,监听testmr.name新值,从而停止watchEffect监听
   watch(() => testmr.name, (val, oldval) => {
     
     if (val == '耗子尾汁') {
     
       stop();
     }
   })
   // 需注意:watchEffect在setup或生命周期中注册的话,组件停止挂载将会自动停止哦

   return {
     
           name,
           ...toRefs( testmr ),
       	}
 	}
});

export default HelloWorld;

那么watch与watchEffect 区别是啥?

  • 不需要手动传入依赖
  • 每次初始化时会执行一次回调函数来自动获取依赖
  • 无法获取到原值,只能得到变化后的值

setup参数

 import {
     defineComponent,  ref, toRefs } from 'vue';
 const HelloWorld = defineComponent({
     
	 props:{
     
	    msg: {
      type: String }
	  },
	  setup(props, context) {
     
		// props: 组件传递的参数
		// 需注意:组件传递的参数,不要使用解构赋值,会使得参数失去响应性
		// console.log(props.msg); 
		
		// context上下文对象, 对应2.0(setup没有this)
		// context.parent === this.$parent
		// context.root === this
		// context.emit === this.$emit
		// context.refs === this.$refs
		// context.slots === this.slots

	    return {
     
	    	}
	  	}
});

export default HelloWorld;

mixin的优化

首先我们知道,当我们一个组件混入大量不同的 mixins 的时候,会存在两个非常明显的问题:命名冲突和数据来源不清晰。首先每个 mixin 都可以定义自己的 props、data,它们之间是无感的,所以很容易定义相同的变量,导致命名冲突。

  • 例1
import {
      ref, computed } from "vue";

export default function () {
     
    const count: any = ref(0);
    const double = computed(() => count.value * 2);

    const increment = () => {
     
        count.value ++;
    }

    return {
     
        count,
        double,
        increment
    }
}

组件中使用:

import {
     defineComponent,  ref, toRefs } from 'vue';
import testHook from "@/assets/mixin/test"
const HelloWorld = defineComponent({
     
 setup(props, context) {
     
   const {
      count, double, increment } = testHook();
   return {
     
           count,
           double,
           increment 
       	}
 	}
});

export default HelloWorld;
  • 例2 - 也可以传参使用
import {
      ref, computed, reactive, toRefs } from "vue";

export const Test2 = (obj: any) => {
     
    const {
      testa, testb } = obj;
    const data = reactive({
     
        testa,
        testb
    })

    const double = computed(() => data.testa + '@com');

    const changeTestb = () => {
     
        data.testb = 'is a test data, right?';
    }

    const refData = toRefs(data);

    return {
     
        ...refData,
        changeTestb,
        double
    }
}

组件使用:

import {
     defineComponent,  ref, toRefs } from 'vue';
import {
      Test2 } from "@/assets/mixin/test2"
const HelloWorld = defineComponent({
     
 setup(props, context) {
     
 	
   const testnum = reactive(Test2({
      testa: 1, testb: 2 }))
   
   return {
     
          ...toRefs(testnum) // templat中可以直接使用Test2中的所有属性方法
       	}
 	}
});

export default HelloWorld;

相关笔记整理

你可能感兴趣的:(前端Vue,vue,vue.js)