Use of Vue3 and setup

1. The use of setup

1.1. Introduction

The setup option is a function that accepts props and context, that is to say, its basic writing method should be like this:

export default {
    
    
  name: 'test',
  setup(props, context){
    
    
    return {
    
    } // 这里返回的任何内容都可以用于组件的其余部分
  }
}

Takes a props and context function and exposes the contents of the setup to the rest of the component via return.

1.2. Notes on setup

Since the created lifecycle method has not been executed when the setup function is executed, the variables and methods of data and methods cannot be used in the setup function.
Since we cannot use data and methods in the setup function, Vue directly modifies this in the setup function to undefined in order to avoid our wrong use.

1.3. Define responsive data

refreactive

  • ref is used to define basic data types as responsive data , which is essentially implemented by redefining properties based on Object.defineProperty() (ref is more suitable for defining basic data types)
  • reactive is used to define the reference type as responsive data , and its essence is to implement object proxy based on Proxy.
  • Basic data type (single type) : except Object. String, Number, boolean, null, undefined.
  • Reference data type : object. The function, Array, and Date contained in it.
  • definition:
<script>
import {
    
     ref, reactive } from "vue";
export default {
    
    
  name: "test",
  setup(){
    
    
    // 基本类型
    const nub = ref(0)
    const str = ref('inline')
    const boo = ref(false)
    // 引用类型
    const obj = reactive({
    
    
      name: 'inline',
      age: '18'
    })
    const arr = reactive(['0', '1', '2'])
    
    return {
    
    
      nub,
      str,
      boo,
      obj,
      arr
    }
  }
}
</script>
  • use:
<template>
  <div>
    <h1>基本类型</h1>
    <p>nub:{
    
    {
    
     nub }}</p>
    <p>str:{
    
    {
    
     str }}</p>
    <p>boo:{
    
    {
    
     boo }}</p>
    <h1>引用类型</h1>
    <p>obj:{
    
    {
    
     obj.name }}</p>
    <p>arr:{
    
    {
    
     arr[1] }}</p>
  </div>
</template>
  • result:
    insert image description here

1.4、toRefs

If we define responsive variables in the form of reactive

setup(){
    
    
  const obj = reactive({
    
    
    name: 'inline',
    gender: '男',
    age: '18'
  })
  return {
    
    
    obj
  }
}

use:

<div>
  <p>姓名:{
    
    {
    
     obj.name }}</p>
  <p>性别:{
    
    {
    
     obj.gender }}</p>
  <p>年龄:{
    
    {
    
     obj.age }}</p>
</div>

In this way, do we find it troublesome to use parameters in the template, then we want to directly use { { name }} to access it, the answer is no .
Here we use es6's spread operator.

setup(){
    
    
  const obj = reactive({
    
    
    name: 'inline',
    gender: '男‘,
    age: '18',
  })
  return {
    
    
    ...obj
  }
}

use:

<div>
  <p>姓名:{
    
    {
    
     name }}</p>
  <p>性别:{
    
    {
    
     gender }}</p>
  <p>年龄:{
    
    {
    
     age }}</p>
  <button @click="name = 'lgg'">改变姓名</button>
  <button @click="gender = '未知'">改变性别</button>
  <button @click="age = '18'">改变年龄</button>
</div>

Result:
Here we see that the parameters are displayed on the page normally , but when we change the parameters, we find that the view is not updated , why?
We write the spread operator as its equivalent

setup(){
    
    
  const obj = reactive({
    
    
    name: 'inline',
    gender: '男‘,
    age: '18',
  })
  return {
    
    
    ...obj ==> name:obj.name
  }
}

When the mouse floats up, it prompts that the name is just a string?
insert image description here
Then let's take a look at what we prompt when we use ref to define the value.
insert image description here
At this time, we see that name is a Ref, which is a responsive string.
At this time, we know why the view is not updated. When we use the ... extension operator, what we get is just a normal type of value, not a responsive data .
Asked to solve this problem, vue3 provides us with the **toRefs function, let us see how it works:

setup(){
    
    
  const obj = reactive({
    
    
    name: 'inline',
    gender: '男'age: '18'
  })
  return {
    
    
    ...toRefs(obj)
  }
}
<div>
  <p>姓名:{
    
    {
    
     name }}</p>
  <p>性别:{
    
    {
    
     gender }}</p>
  <p>年龄:{
    
    {
    
     age }}</p>
  <button @click="name = 'lgg'">改变姓名</button>
  <button @click="gender = '未知'">改变性别</button>
  <button @click="age = '18'">改变年龄</button>
</div>

The parameters can be changed normally, and the facelift is successful.

toRefs summary:
toRefs will transform a responsive object into a common object , and then turn each attribute in the common object into a responsive data .

1.5. Execution method in setup

1.5.1. Method 1:

Define methods in the way reactive defines responsive data:

<script>
  import {
    
     ref, reactive, toRefs } from 'vue';
  export default {
    
    
    name: 'test',
    setup(){
    
    
      const str = ref('inline')
      const fun = reactive({
    
    
        fun1(data) {
    
    
          console.log(str.value)
          this.fun2(data)
        },
        fun2(data) {
    
    
          console.log(data)
          console.log('我是fun2')
        }
      })
      return {
    
    
        ...toRefs(fun)
      }
    }
  }
</script>

The value is passed to fun1 through the click event, and fun1 receives it and then passes it to fun2.
Here we use the method of this.fun2() to call fun2, why it can be executed normally without reporting undefind, because this here is not this,This in Vue2 is an instance, and this here is an object

<button @click="fun1('你还')">点我</button>

result :insert image description here

1.5.2. Method 2:

Note that the method of calling fun2 here is different from method 1, it can be called directly without this call.

export default {
    
    
  name: 'test',
  setup(){
    
    
    const fun1 = (data) => {
    
    
      fun2(data)
    }
    const fun2 = (data) => {
    
    
      console.log(data)
    }
    return {
    
    
      fun1
    }
  }
}

call :

<button @click="fun1('你好 inline')">点我1</button>

result :
insert image description here

1.5.3. Method 3:

This method avoids the problem of stacking functional logic in the setup. We can write independent functions as separate functions. Here I wrote two functional functions, fun() and login(), outside the setup, and call them separately in the setup. .

import {
    
     ref, reactive, toRefs } from 'vue';
export default {
    
    
  name: 'test',
  setup(){
    
    
    const test1 = fun() // 如果函数返回的参数过多,可以赋值给变量并用扩展运算符暴露给组件的其余部分。
    const {
    
     test } = login() // 也可单个接受
    return {
    
    
      ...toRefs(test1),
      test
    }
  }
}
// 功能1
function fun() {
    
    
  let str = ref('我是功能1')
  function fun1(data) {
    
    
    console.log(str.value)
    fun2(data)
  }
  function fun2(data) {
    
    
    console.log(data)
  }
  return{
    
    
    fun1,
    fun2
  }
}
// 功能2
function login() {
    
    
  const obj = reactive({
    
    
    msg: '我是功能2'
  })
  function test() {
    
    
    console.log(obj.msg)
  }
  return{
    
    
    test
  }
}

call :

<button @click="fun1(你好 inline)">点击1</button>
<button @click="test">点击2</button>

1.5.4. Method 4:

Same as the third method, except that we extract the two functional functions and put them in a separate .js file:
insert image description here
then introduce the component and call it in the setup

<template>
  <div>
    <button @click="fun1('你好 inline')">点击1</button>
    <button @click="test">点击2</button>
  </div>
</tempalte>
<script>
import {
    
     ref, reactive, toRefs } from 'vue';
import {
    
     fun, login } from './test.js'
export default {
    
    
  name: "test",
  setup(){
    
    
    const test1 = fun()
    const {
    
     test } = login()
  }
  return{
    
    
    ...toRefs(test1),
    test
  }
}
</script>

1.5.5. Method 5:

We can also write like this, here I define a reactive response object and assign it to the login variable. This response object contains the parameters, verification and methods we need for login. Here we put them all in the login response object and then use toRefs and its spread operator are exposed.

<script>
import {
    
     ref, reactive, toRefs } from "vue";
export default {
    
    
  name: "test",
  setup(){
    
    
    const login = reactive({
    
    
      param: {
    
    
        username: '123',
        password: '123456',
      },
      rules: {
    
    
        username: [{
    
    
          required: true,
          message: '请输入用户名',
          trigger: 'blur'
        }],
        password: [{
    
    
          required: true,
          message: '请输入密码',
          trigger: 'blur'
        }]
      },
      login(){
    
    
        this.param.username = 'inline'
        this.param.password = '123456'
        console.log('登录成功!‘)
      }
    })
    return{
    
    
      ...toRefs
    }
  }
}
</script>

use :

<input type="text" v-model="param.username">
<input type="password" v-model="param.password">
<button @click="login">登录</button>

Result :
insert image description here
Normal execution, so we can also write all methods and related parameters of a function in a reactive object .

1.6、script setup:

The script setup has been officially released on the vue3.2 version
Usage :

<script setup></script>
  • Variable methods do not need to return
  • When using <script setup", the template is compiled into a render function that is inlined within the scope of the setup function . This means that any top-level bindings declared inside <script setup> can be used directly in the template .
<script setup>
  const msg = 'hello!'
</script>
<template>
  <div>{
    
    {
    
     msg }}</div>
</template>

Variables and methods defined in script setup do not need to be returned and can be used directly .

  • Component introduction:
    Imported components do not need to be registered and can be used directly .
<script setup>
// 导入的组件也可以直接在模版中使用
import Foo from './Foo.vue'
import {
    
     ref } from 'vue' 
// 编写合成API代码,就像在正常设置中一样
// 不需要手动返回所有内容
const count = ref(0)
const inc = () => {
    
    
  count.value++
}
</script>
<template>
  <Foo :count="count" @click="inc">
</template>
  • Publish Props and Emits
<script setup>
  const props = defineProps({
    
     foo: String })
  const emit = defineEmits(['update', 'delete'])
</script>
  • Ordinary script and script setup :
    script setup can coexist with script
<script>
  export const name = 1
</script>
<script setup>
import {
    
     ref } from 'vue'
const count = ref(0)
</script>
  • Additional options for script setup :
    script setup provides most of the capabilities equivalent to options api;
    that is to say, script setup can do most of what options api can do.
    So what else can't be done by script setup?
  1. name
  2. inheritAttrs

  3. What about customization options required by plugins or libraries ? Separately write:
<script>
export default {
    
    
  name: 'CustomName', // 自定义名称
  inheritAttrs: false, // 继承属性
  customOptions: {
    
    } // 自定义选项
}
</script>
<script setup></script>

1.7、defineExpose:

The variables defined by script setup defaultWon'tExposed , because the variable is now included in the closure of the setup. At this point we can use defineExpose({}) to expose the internal properties of the component to the parent component :

<script setup>
const a = 1
const b = ref(2)
defineExpose({
    
    
  a, 
  b
})
</script>

When the parent component obtains the instance of this component through the template reference, the retrieved instance will be like this { a: number, b: number } (the reference will be automatically expanded as on the normal instance)

2. The role and difference of ref, reactive, toRef, toRefs

2.1、reactive

reactiveUsed to add reactive state to objects .
Accepts a js object as a parameter and returns a copy with reactive state .

  • Get it directly when getting the data value, no need to add .value .
  • Parameters can only be passed in object types.
import {
    
     reactive } from 'vue'

// 响应式状态
const state = reactive({
    
    
  count: 0
})
// 打印count的值
console.log(state.count)

2.2、ref

refUsed to add reactive state to data .
Since reactive can only pass in parameters of object type, and for basic data types to add responsive state, only ref can be used, and a copy with responsive state is also returned .

  • When the setup gets the data value, you need to add .value, and the template will automatically bring in .value . (For basic types, ref is its own implementation and its performance is better than reactive, while for object types, ref can be understood as implemented through reactive packaging)
  • Parameters can pass any data type, it can also maintain deep responsiveness when passing object types, so it has wider applicability.
  • When defining data in vue3.0 setup, ref is preferred to facilitate logical splitting and business decoupling .
import {
    
     ref } from 'vue'

// 为基本数据类型添加响应式状态
const name = ref('lgg')

// 为复杂数据类型添加响应式状态
const state = ref({
    
    
  count: 0
})

// 打印name的值
console.log(name.value)
// 打印count的值
console.log(state.value.count)

2.3、toRef

toRef is used for **source reactive objectsAttributes** Creates a new ref, thus maintaining a reactive connection to its source object properties.
It accepts two parameters : 1. The source response object; 2. The attribute name. Returns a ref data.
For example : when using the props data passed by the parent component, when you want to refer to the props data, it is useful when you want to refer to a certain attribute of the props and you want to maintain a responsive connection .

  • You need to add .value when getting the data value.
  • If the ref data after toRef is complex type data , it is not a copy of the original data, but a reference , and changing the value of the result data will also change the original data at the same time.
import {
    
     defineComponent, toRef } from 'vue'
export default defineComponent({
    
    
  props: [title],

  setup(props) {
    
    
    // 创建变量myTitle
    const myTitle = toRef(props, 'title')

    console.log(myTitle.value)
  }
})

2.4、toRefs

toRefs is used to convert a reactive object into a result object , where each property of the result object is a ref pointing to a property of the original object response.
It is often used in the destructuring assignment operation of es6 , because when a responsive object is directly destructured, the destructured data will no longer be responsive , and using toRefs can easily solve this problem.

  • You need to add .value when getting the data value.
  • If the ref data after toRefs is complex type data , it is not a copy of the original data, but a reference . Changing the value of the result data will also change the original data at the same time .
  • The function is actually similar to toRef, except that toRef manually assigns values ​​to each attribute, while toRefs automatically deconstructs and assigns values.
import {
    
     defineComponent, toRefs} from 'vue'
export default defineComponent({
    
    
  props: [title],
  setup(props) {
    
    
    // 使用了解构赋值语法创建了变量myTitle
    const {
    
     myTitle } = toRefs(props)
    
    console.log(myTitle.value)
  }
})

Tip: Try not to mix them together, choose one of reactive and ref, and one of toRef and toRefs, otherwise the code will be messy. (ref and toRefs are recommended)

Guess you like

Origin blog.csdn.net/weixin_44767973/article/details/125146023