Composition API usage in Vue3

1. Composite API

Combination API is to collect the code of the same logical concern together, so as to avoid the complicated and difficult to sort out the logical content of components. In order to use the composite API, we first need a place where we can actually use it. In the vue component, we call this location setup.

Basic usage and ref of composite API:

<template>
  <div>
   <button @click="changeA">change</button>
   <button @click="changeCounter">changeCounter</button>
   <h2>{
   
   { a }}--{
   
   { counter }}</h2>

  </div>
</template>
<script>

import {ref} from "vue"
export default {
  // 注意:setup是在组件创建前执行,也就是在beforeCreate和created生命函数之前执行,相当于包含了这两个生命周期,所以在组合式API中没有这俩个生命周期函数。
 setup(){
  let a="hello"
  // 在setup中无法使用this,因为找不到组件实例
  console.log(a); //hello
  function changeA(){
  a="hi"
  console.log(a);//点击按钮数据没有改变,因为数据不是响应式的
  }
  function changeCounter(){
    counter.value++
  }
  // 通过ref定义响应式变量
  const counter=ref(0) //ref()返回的是带有value属性的对象
  // 将变量暴露出去
  return{a,changeA,counter,changeCounter}
 }
}
</script>

2. reactive and toRefs in combined API:

<template>
  <div>
   <button @click="changeObj">changeObj</button>
   <h2>{
   
   { obj.name }}</h2>
   <p>{
   
   { name }}---{
   
   { children.name }}</p>
  </div>
</template>
<script>
// ref定义Number和String,reactive定义引用数据类型,toRefs让解构后的数据重新变成响应式
// import {ref,reactive} from "vue"
import {reactive,toRefs} from "vue"
export default {

 setup(){
  const obj=reactive({
    name:"张三",
    age:18,
    children:{
      name:"小张"
    }
  })
  function changeObj(){
    obj.name="李四",
    obj.children.name="小李"
  }
  // let {name,children}=toRefs(obj)
  // 通过ES6扩展运算符进行解构使得对象中的属性不是响应式的,...obj,此时{
   
   {}}内不在需要obj开头
  return{obj,changeObj,...toRefs(obj)}
 }
}
</script>

3. Use watch in setup:

The composition API can perform the same operation using the watch function imported from Vue, which accepts three parameters:

①A reactive reference or getter function that you want to listen to

② a callback

③Optional configuration options

<template>
  <div>
   <button @click="changeNum">changeNum</button>
   <h2>{
   
   {num }}</h2>
   <button @click="changeObj">changeName</button>
   <p>{
   
   { obj.name }}</p>
  </div>
</template>
<script>
import {reactive,ref,watch,watchEffect} from "vue"
export default {

 setup(){
  let num=ref(0)
  const obj=reactive({
    name:"张三",
    age:18,
  
  })
  watch(num,(newVal,oldVal)=>{
console.log(newVal,oldVal);
  })
  watch(obj,(newVal,oldVal)=>{
    console.log(newVal,oldVal);//Proxy {name: '李四', age: 18} Proxy {name: '李四', age: 18}
  })
  //watchEffect(回调函数)注意:不需要指定监听的属性,组件初始化的时候会执行一次回调函数,自动收集依赖
  watchEffect(()=>{
    console.log(obj.name);
  })
  // watch和watchEffect的区别
  //1.watchEffect不需要指定监听的属性,自动收集依赖,只要在回调中引用到了响应式的属性,只要这些属性发生改变,回调就会执行。watch只能监听指定的属性,做出回调函数的执行,可以侦听多个在vue3里
  //2.watch可以获取新旧值,watchEffect拿不到
 // 3.watchEffect在组件初始化的时候就会自动执行一次,用来收集依赖,watch不需要,一开始就指定了。
  function changeNum(){
   num.value++
  }
  function changeObj(){
   obj.name="李四"
  }
 
  return{obj,changeObj,num,changeNum}
 }
}
</script>

4. Use computed in setup:

<script>
import {ref,computed} from "vue"
export default {

 setup(){
  const msg=ref("helloworld")
  //返回一个带有value属性的对象
  const reverseMsg=computed(()=>{
    return msg.value.split("").reverse().join("")
  })
  console.log(reverseMsg.value);
  return{msg,reverseMsg}
 }
}
</script>

5. The use of lifecycle hooks in setup

A component's lifecycle hooks are accessed by prefixing the lifecycle hook with "on".

<script>
import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated} from "vue"
export default {

 setup(){
  // 生命周期钩子函数是一个回调函数,在setup中生命周期钩子函数可以多次使用
  onBeforeMount(()=>{
    console.log("onBeforeMount");
  })
  onBeforeMount(()=>{
    console.log("onBeforeMount");
  })
  onMounted(()=>{
    console.log("onMounted");
  })
  return{}
 }
}
</script>

6. The props of the two parameters in the setup function

The first parameter in the setup function is props, which is responsive. When a new prop is passed in, it will be updated, and props are responsive and cannot be deconstructed using ES6. It will eliminate the responsiveness of props. If destructuring is required, this can be done using the toRefs function.

//父组件
<template>
  <div>
 
  <Children :message="message" />
  </div>
</template>
<script>
import Children from "./components/Children.vue";
export default {
data(){
return{
  message:"hello"
}
}, 
components:{
  Children
 },
 setup(){
  
  return{}
 },

}
</script>

//子组件
<template>
  <div>
    123
  </div>
</template>
<script>
export default{
  props:{
    message:{
      type:String,
      default:"你好"
    }
  },
  setup(props){
    console.log(props.message);
  }
}
</script>

7. The context of the two parameters in the setup function

The second parameter passed to the setup function is context, which is an ordinary js object that exposes other values ​​that may be useful in setup. It is not responsive and can be deconstructed normally.

root component

<template>
  <div>
  <!-- <Children :message="message" class="box" @sendCounter="getParent"/> -->
  <Children  class="box" id="content" ref="content" @sendCounter="getParent"/>
  </div>
</template>
<script>
import Children from "./components/children.vue";
export default {
data(){
return{
  message:"hello",
  msg:""
}
}, 
methods:{
  getParent(value){
  console.log(value);
  }
},
mounted(){
// 此处调用的是expose暴露出来的方法
this.$refs.content.senParent()
},
components:{
  Children
 },
 setup(){
  
  return{}
 },

}
</script>

Subassembly

<template>
  <div>
   
    <button @click="senParent">向父组件发送数据</button>
  </div>
</template>
<script>
import { ref,h} from "vue"
export default{
  props:{
    message:{
      type:String,
      default:"你好"
    }
  },
  setup(props,context){
    // console.log(props.message);
    // console.log(context);
    // 可以拿到父组件定义的选择器,如class,id等。(非响应式对象,等同于$attrs)
    console.log(context.attrs);
    //插槽(非响应式对象,等同于$slots)
    console.log(context.slots);

    //context.emit触发事件(方法,等同于$emit)
    const counter=ref(20)
    function senParent(){
      context.emit("sendCounter",counter.value)

      //context.expose暴露公共property(函数)
    }
    // return{senParent}
    context.expose({
      senParent,counter 
    })
    return ()=>h("div",counter.value)
  }
}
</script>

8.provide and inject in setup

When using provide and inject in setup, we first import the provide and inject methods from vue, which enables us to call provide to define each property, and after inject is imported, we can call it to define the way the components are exposed to us.

The provide function allows you to define a property with two parameters:

①name (String type)

②value

The inject function has two parameters:

①The name of the property to be injected

② Default value (optional)

parent component:

<template>
  <div>
  <Children  class="box" id="content" ref="content" />
  <button @click="changeName">改变</button>
  </div>
</template>
<script>
import Children from "./components/children.vue";
import { provide,ref } from "vue";
export default {
data(){
return{
  message:"hello",
  msg:""
}
}, 

components:{
  Children
 },
 setup(){
  // 非·响应式的
  // provide("name","张三")
 
  // 响应式的
  const nm=ref("张三")
  provide("name",nm)
  function changeName(){
    nm.value="李四"
  }
  return{changeName}
 },

}
</script>

Subassembly:

<template>
  <div>
   {
   
   { value }}
  </div>
</template>
<script>
import { inject} from "vue"
export default{
 
  setup(){
  const value=inject("name")
    return {value}
  }
}
</script>

9. Use combined API syntactic sugar in single-file component SFC (script tag directly uses setup)

<template>
  
  <Children  class="box" id="content"  />
  <!-- 此处下的红色下划线报错,是插件不识别vue3语法导致,不影响vue3正常运行 -->
  <Children  class="box" id="content"  />
  <h2>{
   
   { a }}</h2>
  <h2>{
   
   { b}}</h2>
  <button @click="changeAdd">add</button>
</template>

<script setup>
//在script标签中使用setup语法糖
//1.引入组件不需要注册
//2.定义变量不在需要return暴露,直接使用
//3.定义响应式变量,还需引入
import { ref } from "vue";
import Children from "./components/children.vue";
const a=20
console.log(a);
let b=ref(10)
function  changeAdd(){
  b.value++
}
</script>

Guess you like

Origin blog.csdn.net/qq_72760247/article/details/128650570