Vue3 new feature experience -- in (Composition API)

Posted by popsiclesph on Sat, 30 Oct 2021 06:55:37 +0200

The Composition API in Vue3 is mainly used to facilitate the integration of codes, centralize the codes that realize the same functions, and facilitate maintenance and management. The entry of the new features of the Composition API - the setup() function, which is a new attribute provided for components. Make a simple example and feel it.

The example code of this chapter is modified on the basis of the previous chapter:

Vue3 new feature experience -- upper (with simple examples, which can be used directly)_ Front end dish Xiaobai leo's blog - CSDN blog

Now, we implement a small function in component A and click the button to change the display content.

In vue2:

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Modify name</button>
  </div>
</template>

<script>
export default {
  name: 'A',
  data() {  //The data inside is responsive and hijacks getter s and setter s through Object.defineProperty()
    return {
      name: 'leo'
    }
  },
  methods: {
    changeName() {
      this.name = 'lion'
    }
  }
}
</script>

In vue3:

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Modify name</button>
  </div>
</template>

<script>
//Import ref function
import {ref} from 'vue'
export default {
  name: 'A',
  setup(){
    //Declare the responsive data name, with the initial value of 'leo'
    let name = ref('leo')

    //Create method changeName
    function changeName(){
      name.value = 'lion'
    }

    //Expose variables and methods so that they can be accessed by the outside world
    return {
      name,
      changeName
    }
  }
}
</script>

Page display:

In vue2, name and its method changeName are separated, distributed in the data attribute and methods attribute respectively. When a function is implemented, the code is separated. Imagine that if this component needs to implement many functions, there may be a lot of data in data, and many methods will be constructed in methods. The code is scattered, so it will be difficult to find. This situation does exist at work. Sometimes it takes time to find a variable, especially when there are many variables and functions. Compared with vue3, it combines the logic of the same function together. For example, in this example, the declaration of name and the method of modifying it can see the relevant implementation code of a function at a glance, which is convenient for the maintenance and management of the function code.

setup

setup is an entry function in the Composition API. It is executed only once during initialization and before the beforeCreate life cycle. Verify:

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Modify name</button>
  </div>
</template>

<script>
import {ref} from 'vue'
export default {
  name: 'A',
  beforeCreate(){
    console.log('beforeCreate implement')
  },
  setup(){
    console.log('setup implement')
    let name = ref('leo')
    function changeName(){
      name.value = 'lion'
    }
    return {
      name,
      changeName
    }
  }
}
</script>

The contents of setup() are printed on the console, indicating that it is executed before beforeCreate() and only once. This also means that when setup is executed, the component object has not been created, and the component instance object this is not available. The contents of data, calculated and methods cannot be accessed through this. Therefore, mixed use is not recommended.

There are two parameters props and context in setup.

Props: props is an object through which the child component gets the properties passed down by the parent component.

Context: context object, which has three attributes attrs, slots and emit. Attrs: get all objects on the current component template label that do not have properties received through props. Slots: an object that contains the contents of all incoming slots. Emit: a function used to distribute custom events. It can communicate between parent and child components. (the content is not expanded, but can be consulted and studied by yourself)

ref

ref defines a responsive data in vue3, which can be either a basic data type or an object. It is similar to the responsive variable in data in vue2.

let name = ref('leo')

What is returned is an object. The real value is placed in its value attribute. You might as well print it out.

let name = ref('leo')
console.log(name,'ref')  //Print on the console and view the returned data structure

  Note: when changing the value of name (ref type object), you cannot directly "name =" but need "name.value =".

reactive

You can define multiple responsive data, receive an object, return the responsive Proxy object of the object, and Proxy all the attributes in the object. No matter how deep the object is, all attributes are responsive. In contrast to vue2, the way to make an object corresponding is to traverse all the properties in the object and hijack the getter and setter of the property through defineProperty(). When there are multiple objects and the object level is very deep, traversing all attributes to make them responsive is a time-consuming and resource-consuming process. vue3 improves the process and efficiency by means of agent.

For example, create a like object and make it responsive.

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Change content</button>
    <div>
      <p>Favorite movies:{{like.movie}}</p>
      <p>Favorite music:{{like.music}}</p>
    </div>
  </div>
</template>

<script>
import {reactive, ref} from 'vue'
export default {
  name: 'A',
  setup(){
    let name = ref('leo')
    let like = reactive({     //Object is responsive
      movie:'Changjin Lake',
      music:'I love you China'
    })
    console.log(like,'like')
    function changeName(){
      name.value = 'lion'
      like.movie = 'Warwolf 2'
    }
    return {
      name,
      like,
      changeName
    }
  }
}
</script>

Observe the console print result. Unlike ref, the real value is not in value, but in the original corresponding attribute of the object. Therefore, it is not necessary to add ". Value" when modifying the value.

Initial page

  Click the button to verify its relevance

computed

The calculation properties are basically consistent with those in vue2, for example:

If only one callback function is passed in the function for calculating properties, it indicates a get process

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Change content</button>
    <div>
      <p>{{content}}</p>
    </div>
  </div>
</template>

<script>
import {computed, reactive, ref} from 'vue'
export default {
  name: 'A',
  beforeCreate(){
    // console.log('beforeCreate execution ')
  },
  setup(){
    let name = ref('leo')
    let like = reactive({
      movie:'Changjin Lake',
      music:'I love you China'
    })
    console.log(like,'like')
    function changeName(){
      name.value = 'lion'
      like.movie = 'Warwolf 2'
    }
    let content = computed(()=>{
      return 'I like watching:' + like.movie + ';Like to listen to:' + like.music
    })
    console.log(content,'content')  //Console printing, returned data structure
    return {
      name,
      like,
      content,
      changeName
    }
  }
}
</script>

Print it out on the console. It is found that the data structure is the same as that of ref type, indicating that computed returns ref type data.

Note: the. value of ref type returned by computed is a read-only attribute and cannot be modified.

function changeName(){
  name.value = 'lion'
  like.movie = 'Warwolf 2'
  content.value = 'Attention!!!' + content.value
}

  Of course, calculation properties can also be passed into an object, where there can be read and write methods, print and observation.

let content = computed({
  get(){
    return 'I like watching:' + like.movie + ';Like to listen to:' + like.music
  },
  set(newVal){
    like.movie = newVal
  }
})
console.log(content,'content')

watch

watch is consistent with the configuration in vue2. All include the data to be monitored, callback function and monitoring configuration.

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Change content</button>
    <div>
      <p>{{content}}</p>
      <span>{{newContent}}</span>
    </div>
  </div>
</template>

<script>
import {computed, reactive, ref, watch} from 'vue'
export default {
  name: 'A',
  beforeCreate(){
    // console.log('beforeCreate execution ')
  },
  setup(){
    let name = ref('leo')
    let like = reactive({
      movie:'Changjin Lake',
      music:'I love you China'
    })
    let newContent = ref('')
    console.log(like,'like')
    function changeName(){
      name.value = 'lion'
      like.movie = 'Warwolf 2'
    }
    watch(    //Listen to the like object and execute callback when movie and music change
      like,
      ({movie,music})=>{
        newContent.value = 'I prefer to watch:' + movie + ';Prefer to listen to:' + music
      }
    )
    let content = computed({
      get(){
        return 'I like watching:' + like.movie + ';Like to listen to:' + like.music
      },
      set(newVal){
        like.movie = newVal
      }
    })
    console.log(content,'content')
    return {
      name,
      like,
      content,
      newContent,
      changeName
    }
  }
}
</script>

Initial page

After the watch page is loaded, it will not be executed by default. You want to execute it immediately. Modify the following configuration (deep:true, deep listening)

watch(
  like,
  ({movie,music})=>{
    newContent.value = 'I prefer to watch:' + movie + ';Prefer to listen to:' + music
  },
  {immediate:true,deep: true}   //immediate:true execute immediately
)

View the page, and the movie in the new content is the initial value  

Click the button, the movie changes, watch listens to the change, and the value of newContent changes accordingly

Extension: watch listens to multiple data and uses an array

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Change content</button>
    <div>
      <p>{{content}}</p>
      <span>{{newContent}}</span>
    </div>
  </div>
</template>

<script>
import {computed, reactive, ref, watch} from 'vue'
export default {
  name: 'A',
  beforeCreate(){
    // console.log('beforeCreate execution ')
  },
  setup(){
    let name = ref('leo')
    let like = reactive({
      movie:'Changjin Lake',
      music:'I love you China'
    })
    let newContent = ref('')
    console.log(like,'like')
    function changeName(){
      name.value = 'lion'
      like.movie = 'Warwolf 2'
    }
    watch(
      [name,()=>like.movie,()=>like.music],
      ([newName,newMovie,newMusic])=>{
        newContent.value = newName + 'Prefer to watch:' + newMovie + ';Prefer to listen to:' + newMusic
      },
      {immediate:true,deep:true}
    )
    let content = computed({
      get(){
        return 'I like watching:' + like.movie + ';Like to listen to:' + like.music
      },
      set(newVal){
        like.movie = newVal
      }
    })
    console.log(content,'content')
    return {
      name,
      like,
      content,
      newContent,
      changeName
    }
  }
}
</script>

Initial page

  Click the button to enable watch to monitor multiple data

 watchEffect

Unlike watch, it does not directly specify the data to be monitored. Instead, it executes it once initially to judge which responsive data is used in the callback function, so as to collect the data to be monitored.

The code in watch:

watch(
  [name,()=>like.movie,()=>like.music],
  ([newName,newMovie,newMusic])=>{
    newContent.value = newName + 'Prefer to watch:' + newMovie + ';Prefer to listen to:' + newMusic
  },
  {immediate:true,deep:true}
)

Change to watchEffect form:

watchEffect(
  ()=>{
    newContent.value = name.value + 'Prefer to watch:' + like.movie + ';Prefer to listen to:' + like.music
  }
)

Verify that the display effect of the page is consistent.

toRefs

In this example, when we use the attribute of the like object in the template, we use it in the form of "like." if the page uses this attribute a lot, it will be troublesome. If we deconstruct it through es6, it will lose its responsiveness. toRefs supports converting all the original attributes of a reactive object into responsive ref attributes. Ref directly uses the object when using the template, such as name and newContent in the instance.

Using toRefs, the console prints the changes of like objects before and after use.

<template>
  <div class="a-style">
    <p>I am A assembly</p>
    <p>My name:{{name}}</p>
    <button @click="changeName">Change content</button>
    <div>
      <span>{{newContent}}</span>
      <!-- <p>Not used toRefs: {{like.movie}},{{like.music}}</p> -->
      <p>use toRefs: {{movie}},{{music}}</p>
    </div>
  </div>
</template>

<script>
import {reactive, ref, toRefs, watchEffect} from 'vue'
export default {
  name: 'A',
  setup(){
    let name = ref('leo')
    let like = reactive({
      movie:'Changjin Lake',
      music:'I love you China'
    })
    console.log(like,'like')
    let newContent = ref('')
    function changeName(){
      name.value = 'lion'
      like.movie = 'Warwolf 2'
    }
    watchEffect(
      ()=>{
        newContent.value = name.value + 'Prefer to watch:' + like.movie + ';Prefer to listen to:' + like.music
      }
    )
    let newLike = toRefs(like)   //Use toRefs to convert a proxy object into a ref object
    console.log(newLike,'newLike')
    return {
      name,
      //like, / / don't use toRefs
      ...newLike,  //The extension operator returns the ref object corresponding to the attribute in each proxy object
      newContent,
      changeName
    }
  }
}
</script>

The page displays normally, and the effect is the same as that when toRefs is not used.  

The life cycle comparison of vue2 and vue3 is attached (picture from: Learn to use Vue3_hugo233 blog CSDN blog)

Summary: mainly experience vue3's new feature Composition API through simple examples.

Topics: Javascript Front-end Vue Vue.js