跳至主要內容

CompositionAPI

Mr.Dylin...大约 5 分钟

CompositionAPI

1. setup()

setup函数是一个新的组件选项。作为在组件内使用Composition API的入口点。它会在beforeCreate钩子之前被调用,所有变量、方法都在setup函数中定义,之后return出去供外部使用

该函数有2个参数: props context

其中context是一个上下文对象,具有属性(attrs,slots,emit,parent,root),其对应于vue2中的this.$attrs,this.$slots,this.$emit,this.$parent,this.$root。

*注意:this关键字在setup()函数内部不可用,在方法中访问setup中的变量时,直接访问变量名就可以使用。

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}
 
 
 
 
 
 
 
 

props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性

2. reactive, ref

reactive和ref都是vue3中用来创建响应式数据的api,作用等同于在vue2中的data,不同的是他们使用了ES6的Porxy API解决了vue2 defineProperty 无法监听数组和对象新增属性的缺陷

区别

使用时在setup函数中需要通过内部属性.value来访问ref数据,return出去的ref可直接访问,reactive可以直接通过创建对象访问 ref接受一个参数,返回响应式ref对象,一般是基本类型值(String 、Nmuber 、Boolean 等)或单值对象。如果传入的参数是一个对象,将会调用 reactive 方法进行深层响应转换(此时访问ref中的对象会返回Proxy对象,说明是通过reactive创建的);引用类型值(Object 、Array)使用reactive

<template>
  <div class="contain">
    <el-button type="primary" @click="numadd">add</el-button>
    <span>{{ `${state.str}-${num}` }}</span>
  </div>
</template>

<script lang="ts">
  import { reactive, ref } from 'vue';
  interface State {
    str: string;
    list: string[];
  }

  export default {
    setup() {
      const state = reactive<State>({
        str: 'test',
        list: [],
      });
      //ref需要加上value才能获取
      const num = ref(1);
      const numadd = () => {
        num.value++;
      };
      return { state, numadd, num };
    },
  };
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 










3. toRefs

将传入的对象里所有的属性的值都转化为响应式数据对象(ref) 使用reactive return 出去的值每个都需要通过reactive对象 .属性的方式访问,也可以通过解构赋值的方式,但是直接解构的参数不具备响应式,此时可以使用到这个api(也可以对props中的响应式数据做此处理)

<template>
<div class="contain">
 <el-button type="primary" @click="numadd">add</el-button>
-    <span>{{ `${state.str}-${num}` }}</span>
+    <span>{{ `${str}-${num}` }}</span>
</div>
</template>

<script lang="ts">
import { reactive, ref, toRefs } from 'vue';
interface State {
 str: string;
 list: string[];
}

export default {
 setup() {
   const state = reactive<State>({
     str: 'test',
     list: [],
   });
   //ref需要加上value才能获取
   const num = ref(1);
   const numadd = () => {
     num.value++;
   };
-      return { state, numadd, num };
+      return { ...toRefs(state), numadd, num };
 },
};
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 












4. toRef

toRef 用来将引用数据类型或者reavtive数据类型中的某个值转化为响应式数据

5. isRef

判断是否是ref对象,内部是判断数据对象上是否包含__v_isRef属性且值为true。

    setup() {
      const one = ref(0);
      const two = 0;
      const third = reactive({
        data: '',
      });
      let four = toRef(third, 'data');
      const { data } = toRefs(third);
      
      console.log(isRef(one)); // true
      console.log(isRef(data)); // true
      console.log(isRef(four)); // true
      console.log(isRef(two)); // false
      console.log(isRef(third)); // false
    }

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

6. unref

如果参数为ref,则返回内部原始值,否则返回参数本身。内部是val = isRef(val) ? val.value : val的语法糖。

    setup() {
      const hello = ref('hello');
      console.log(hello); // { __v_isRef: true,value: "hello"... }
      const newHello = unref(hello);
      console.log(newHello); // hello
    }

 
 
 
 
 
 
 

7. watch

语法为:watch(source, callback, options)

source:用于指定监听的依赖对象,可以是表达式,getter函数或者包含上述两种类型的数组(如果要监听多个值)

callback:依赖对象变化后执行的回调函数,带有2个参数:newVal,oldVal。如果要监听多个数据每个参数可以是数组 [newVal1, newVal2, ... newValN],[oldVal1, oldVal2, ... oldValN]

options:可选参数,用于配置watch的类型,可以配置的属性有 immediate(立即触发回调函数)、deep(深度监听)

      let title = ref('Create');
      let num = ref(0);
      const state = reactive<State>({
        nums: 0,
        list: [],
      });
      
      // 监听ref
      watch(title, (newValue, oldValue) => {
         /* ... */
      });

      // 监听reactive
      watch(
        // getter
        () => state.list.length,
        // callback
        (v = 0) => {
          state.nums = v;
        },
         // watch Options
        { immediate: true }
      );
      
      // 监听多个ref
      watch([title, num], ([newTitle, newNum], [oldTitle, oldNum]) => {
        /* ... */
      });      
      
      // 监听reactive多个值
      watch([() => state.list, () => state.nums], ([newList, newNums], [oldList, oldvNums]) => {
        /* ... */
      });

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 














8. watchEffect

立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更是重新运行该函数.

9. computed

传入一个getter函数,返回一个默认的ref对象.

let title = ref('Create');
const vTitle = computed(() => '-' + title.value + '-');
 
 

反转字符串

setup() {
    const state = reactive({
     value: '',
     rvalue: computed(() =>
           state.value
             .split('')
             .reverse()
             .join('')
     )
   })
   return toRefs(state)
 }

 
 
 
 
 
 
 
 
 
 
 
 
 

computed支持读写操作

当给computed传递的是一个方法的时候默认就是只读模式,不可以进行修改操作

// 只读模式操作
const count = ref(1)
const plusOne = computed(() => count.value + 1)

console.log(plusOne.value) // 2

plusOne.value++ // 错误!
 
 
 
 
 
 
 

想要修改这个值的话就需要使用对象形式的参数,注意{get() =>{}, set() => {}}get和set是搭配使用的,否则会抛出错误

// 读写模式操作
const count = ref(1)
const plusOne = computed({
  get: () => count.value + 1,
  set: (val) => {
    // val是=右边的值 plusOne.value = 1
    count.value = val - 1
  },
})

plusOne.value = 1
console.log(count.value) // 0
 
 
 
 
 
 
 
 
 
 
 
 

10. provide, inject

provide()和inject()用来实现多级嵌套组件之间的数据传递,父组件或祖先组件使用 provide()向下传递数据,子组件或子孙组件使用inject()来接收数据

// 父组件
<script>
import {provide} from 'vue'
export default {
    setup() {
        const obj = ref('johnYu')
        // 向子孙组件传递数据provide(名称,数据)
        provide('name', obj)
    }
}
</script>

// 孙组件
<script>
import {inject} from 'vue'
export default {
    setup() {	
        // 接收父组件传递过来的数据inject(名称)
        const name = inject('name') // johnYu
        return {name}
    }
}
</script>

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 




11. getCurrentInstance

getCurrentInstance方法用于获取当前组件实例,仅在setup和生命周期中起作用

<template>
	<p>{{ num }}</p>
</template>
<script>
import {ref, getCurrentInstance} from 'vue'
export default {
    setup() {	
        const num = ref(3)
        const instance = getCurrentInstance()
        console.log(instance)

        return {num}
    }
}
</script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

通过instance中的ctx属性可以获得当前上下文

12. $Refs

获得对模板中元素或组件实例的引用,可以同样使用ref并从setup()返回它

setup() {
    // 获取渲染上下文的引用
    // 创建一个DOM引用,名称必须与元素的ref属性名相同
    const myRef = ref(null);
    
    // 仅在初次渲染后才能获得目标元素
    onMounted(() => {
      console.log(myRef.value);
    });
    return {
      myRef
    };
}
 
 
 
 
 
 
 
 
 
 
 
 
 

多个ref

let myRef = '';
const setRef = el => {
   myRef = el;
}

nextTick(() => {
   console.log(myRef);
})
return {
    setRef
};
 
 
 
 
 
 
 
 
 
 
 
上次编辑于:
贡献者: zddbic