vue3 组合式api(setup)学习

259 阅读3分钟

setup执行的时机

  1. 在beforeCreate之前执行(一次),此时组件对象还没创建;
  2. this是undefined,不能通过this来访问data/computed/methods/props;

setup的返回值

  1. 一般都返回一个对象:为模板提供数据,也就是模板中可以直接使用此对象中的所有属性/方法
  2. 返回对象中的属性会与data函数返回对象合并成为组件对象的属性
  3. 返回对象中的方法会与methods中的方法合并成功组件对象的方法
  4. 如果有重名,setup优先
  5. 注意:一般不要混合使用:methods中可以访问setup提供的属性和方法,但在setup方法中不能访问data和methods;setup不能是async函数:因为返回值不再是return的对象,而不是promise,模板看不到return对象中的属性数据

setup参数

  1. setup(props,context)/setup(props,{attrs,slots,emit})
  2. props:包含props配置声明且传入了所有属性的对象
  3. attrs:包含没有在props配置中声明的属性的对象,相当于this.$attrs
  4. slots:包含所有传入的插槽内容的对象,相当于this.$slots
  5. emit:用来分发自定义事件的函数,相当于this.$emit

reactive与ref细节

  1. 是vue3的composition API中最重要的响应式API
  2. ref用来处理基本类型的数据,reactive用来处理对象(递归深度响应式)
  3. 如果用ref对象/数组,内部会自动将对象/数组转换为reactive的代理对象
  4. ref内部:通过给value属性添加getter/setter来实现对数据的劫持
  5. reactive内部:通过使用Proxy来实现对对象内部所有数据的劫持,并通过Reflect操作对象内部数据
  6. ref的数据操作:在js中要.value,在模板中不需要(内部解析模板时会自动添加.value)

生命周期

与2.x版本生命周期相对应的组合API
。beforeCreate=>使用setup()
。create=>使用setup()
。beforeMount=>onBeforeMount
。mounted=>onMounted
。beforeUpdate=>onBeforeUpdate
。updated=>onUpdated
。beforeDestroy=>onBeforeUnmount
。destroyed=>onUnmounted
。errorCaptured=>onErrorCaptured

toRefs和toref

  1. 把一个响应式对象转换成普通对象,该普通对象的每个property都是一个ref
  2. 应用:当从合成函数返回响应式对象时,toRefs非常有用,这样消费组件就可以在不丢失响应式的情况下对返回的对象进行分解使用
  3. 问题:reactive对象取出的所有属性值都是非响应式的
  4. 解决:利用toRefs可以将一个响应式reactive对象的所有原始属性转换为响应式的ref属性
  • toRef: 复制 reactive 里的单个属性并转成 ref
  • toRefs: 复制 reactive 里的所有属性并转成 ref
//为对象某个属性创建一个ref对象,两者操作的是同一个数据,更新时会同步更新
//和ref的区别为  更改通过ref创建的数据不会影响原数据
//在 自用于父传子 props时尤其好用  会动态改变
setup(){
   const user=reactive({
        name:'李虎',
        age:20
      })
   const name=toRef(user,'name')
   let age=toRef(user,'age')
      const updata=()=>{
        user.name='zs' // 此时 name='zs'
        age.value=30   // 此时 user.age=30
      }
    return {
          user,name,age,updata
      }
import { reactive, toRefs } from 'vue'
export default {
	setup() {
    let info = reactive({
      name: 'Tony',
      greet: 'Hello'
    })
	// 复制整个 info
    let rInfo = toRefs(info)
    // 更改 rInfo.greet
    const onChangeGreet = () => {
      rInfo.greet.value = 'world!'
    }
    return {
      info,
      rInfo,
      onChangeGreet
    }
  }
}
<template>
  <h2>App</h2>
  <h3>foo: {{foo}}</h3>
  <h3>bar: {{bar}}</h3>
  <h3>foo2: {{foo2}}</h3>
  <h3>bar2: {{bar2}}</h3>
</template>
<script lang="ts">
import { reactive, toRefs } from 'vue'
/*
toRefs:
  将响应式对象中所有属性包装为ref对象, 并返回包含这些ref对象的普通对象
  应用: 当从合成函数返回响应式对象时,toRefs 非常有用,
        这样消费组件就可以在不丢失响应式的情况下对返回的对象进行分解使用
*/
export default {

  setup () {

    const state = reactive({
      foo: 'a',
      bar: 'b',
    })

    const stateAsRefs = toRefs(state)

    setTimeout(() => {
      state.foo += '++'
      state.bar += '++'
    }, 2000);

    const {foo2, bar2} = useReatureX()

    return {
      // ...state,
      ...stateAsRefs,
      foo2, 
      bar2
    }
  },
}

function useReatureX() {
  const state = reactive({
    foo2: 'a',
    bar2: 'b',
  })

  setTimeout(() => {
    state.foo2 += '++'
    state.bar2 += '++'
  }, 2000);

  return toRefs(state)
}

</script>

ref获取元素

  1. 利用ref函数获取组件中的标签元素
  2. 功能需求:让输入框自动获取焦点
    <input type="text" ref="inputref">
    setup(){
      const inputref=ref<HTMLElement|null>(null) //名与上述ref='xx' 中的值相同
      onMounted(()=>{
        inputref.value && inputref.value.focus() //自动获得焦点
      })
      return{
        inputref
      }
}