Vue3第二篇setup简介之监视与计算属性

1,256 阅读3分钟

setup

一、setup拉开序幕

这是vue3中composition API的入口,可以说为vue3拉开序幕

  • 执行时机

    beforeCreate之前执行,因此this是不可用的,为undefined

  • 参数

    接收两个参数propscontext

    • props--外部组件传过来的东西

      值为对象,包含组件外部传递过来,且组件内部声明接收了的属性

    • context--上下文对象

      • attrs:值为对象,包含组件外传过来但是并没有在props配置中声明的属性,相当于vue2中的this.$attrs

      • slots:收到的插槽的内容,相当于this.$slots

      • emits:分发自定义事件的函数,相当于this.$emit

        使用时,使用context.emit('xx', value)

        还需要在setup中进行声明:emits:['xx']

        emits: ['hello'],
          setup(props, context) {
            function hello(){
              context.emit('hello', 666)
            }
            return {hello}
          }
        

image-20210714171924282


二、setup中的watch函数

//三个参数
watch(params,handler(new, old), {immediate:true, deep:true})
  • params:监视的属性
  • handler():回调函数
  • immediate和deep配置项

两个小坑

  • 监视reactive定义的响应式数据时,oldValue无法正确获取,并强制开启了深度监视,并且deep配置失效
  • 监视reactive定义的响应式数据中的某个属性(也是一个对象)时,deep的配置有效

因此,如果要单独获取一个变量的oldValue时,需要将该变量单独使用ref定义!

export default {
  setup() {
    let sum = ref(0);
    let msg = ref('hello, ding')
    let person = reactive({
      name: 'lijing',
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

    //情况一:监视ref定义的一个响应式数据
    watch(sum, (newValue, oldValue) => {
      console.log('sum changed', newValue, oldValue);
    }, {immediate: true})

    //情况二:监视ref所定义的多个响应式数据,此时newValue和oldValue为数组
    watch([sum,msg], (newValue, oldValue) => {
      console.log(newValue);
      console.log(oldValue);
    })

    //情况三:监视reactive所定义的响应式数据
    // 注意:1.此处无法正确获取到oldValue
    // 注意:2.强制开启了深度监视,即使配置了deep为false也无效,依然深度监视
    watch(person, (newValue, oldValue) => {
      console.log('person information changed!', newValue, oldValue);
    }, {deep: false})//此处的deep配置无效

    //情况四:监视reactive所定义的一个响应式数据中的某一个属性
    //不能直接使用person.age这种写法,需要写成函数
    watch(() => person.age, (newValue, oldValue) => {
      console.log('person age changed!', newValue, oldValue);
    }, {deep: false})

    //情况五:监视reactive所定义的一个响应式数据中的某些属性,类似情况二写成数组
    watch([() => person.age, () => person.name], (newValue, oldValue) => {
      console.log('person name age changed!', newValue, oldValue);
    })

    //情况六特殊情况
    watch(() => person.job, (newValue, oldValue) => {
      console.log('person job changed!', newValue, oldValue);
    }, {deep: true})//此处监视的reactive定义的对象中的某个对象属性,必须要有deep配置,否则无效

    return {sum, msg, person}
  }
}

注意事项:当使用ref定义对象数据时,监视对象有两种办法,一是.value,二是开启深度监视

不过依然拿不到oldValue

export default {
  setup() {
    let person = ref({
      name: 'lijing',
      age: 18,
      job: {
        j1: {
          salary: 20
        }
      }
    })

    // 方法一:使用.value,监视的是RefImpl对象中的value,是一个proxy对象
    watch(person.value, (newValue, oldValue) => {
      console.log('person information changed!', newValue, oldValue);
    }, {deep: false})//此处的deep配置无效

    //方法二:开启深度监视
    watch(person, (newValue, oldValue) => {
      console.log('person age changed!', newValue, oldValue);
    }, {deep: true})

    return {person}
  }
}

watchEffect

我不说我监视谁,用到了谁就监视谁!

export default {
  setup() {
    xxxx

    watchEffect(() => {
      //此处用到了谁就监视谁,逻辑就会走一遍
    })

    return {person}
  }
}

watchEffectcomputed的区别:

  • computed:注重的是计算出来的值,回调函数有个返回值,必须要写返回值
  • watchEffect:更注重的是过程,回调函数的函数体,不需要返回值

三、setup中的computed函数

与vue2中的配置基本一致

setup(){   
//计算属性的简写形式
    let fullName = computed(() => {
      return person.firstName + '-' + person.lastName;
    })
    //计算属性的完整写法
    let fullName1 = computed({
      get(){
        return person.firstName + '-' + person.lastName;
      },
      set(value){
        const nameArr = value.split('-');
        person.firstName = nameArr[0];
        person.lastName = nameArr[1];
      }
    })
}