“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

Writing in the front

More and more people are learning Vue, including some back end students. Since its release, Vue has successfully established itself in the front end. Vue is small and clean compared to the clunky Angular framework, and it’s easier to get started than React. The official definition is a set of progressive frameworks for building user interfaces.

My understanding of a progressive framework is very simple: use the features you want or can use, and don’t use the parts you don’t want. Vue doesn’t force you to accept and use all of its features at once.

It can be seen that Vue is indeed a framework that is easy to learn, but there are some advanced functions in Vue. The author summarizes some advanced features of Vue, aiming to help learners master these advanced skills of Vue and help readers stand out in interviews or jobs.

Vue advanced features:

  • The advanced features presented here are based on Vue2, and updates to Vue3 will be introduced in a later article

  • (1) Customize v-Model (2) $nextTick (3) slot

  • (4) Dynamic and asynchronous components (5) keep-alive (6) mixins

1. Customize the V-Model

That is, use the V-model command on the component. Usage scenarios: Use a color selector component, or encapsulate the Input of your own company’s project, requiring some project-specific number or text. Now you can’t use the simplest Input, you have to encapsulate a CustomInput yourself.

CustomVmodel component code:

<template>
  <div>
    <input type="text":value="text1"
    @input="$emit('change1',$event.target.value)">
    <! -- 1. The input above uses value instead of v-model 2. 3. Text1 attribute = text1 -->
  </div>
</template>
<script>
export default {
  model: {prop:'text1'.// This corresponds to the props attribute
    event:'change1'
  },
  props: {text1:String.default(){
      return ' '}}}</script>
Copy the code

Next, use this component:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <! -- custom v-model-->
    <CunstomVmodel v-model="name"/>
  </div>
</template>
<script>
import CunstomVmodel from './ComponentVmodel.vue'// Import components
export default {
  components:{
    CunstomVmodel// Register the component
  },
  data(){
    return{
      name:'Orange's front end amusement park'}}}</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

Code demo:

Bernays! So we have successfully used the V-Model directive on our custom component 😄.

2. $nextTick

First of all, let’s be clear that Vue is rendered asynchronously, as is React. Asynchronous rendering means that the DOM will not render immediately after the data changes. If we want to get the “correct DOM node” immediately after the data changes, we need to call $nextTick, which will be triggered after the DOM is rendered to get the latest DOM node.

With the following Demo you will have a clearer idea of $nextTick

NextTick Component code:

<template>
  <div>
    <ul ref="ul1">
      <li v-for="(item,index) in fruits" :key="index">{{item}}</li>
    </ul>
    <button @click="addItem">add</button>
  </div>
</template>
<script>
export default {
  data(){
    return{
      fruits: ['orange'.'pomelo'.'pineapple']}},methods: {addItem(){
      this.fruits.push(`The ${Date.now()}`)
      this.fruits.push(`The ${Date.now()}`)
      this.fruits.push(`The ${Date.now()}`)
      const ulElem = this.$refs.ul1
      console.log(ulElem.childNodes.length); }}}</script>
Copy the code

To explain this code: Click the Add button to get the ul node and print the length of the child nodes of ul (that is, the number of Li)

We found that after the first addition of data, the length of the print node should be 6, but the console printed the result as 3. This is why Vue rendered asynchronously, and DOM does not render immediately after the data was changed. If we want to get the “correct DOM” immediately after the data changes, we need to call $nextTick

<template>
  <div>
    <ul ref="ul1">
      <li v-for="(item,index) in fruits" :key="index">{{item}}</li>
    </ul>
    <button @click="addItem">add</button>
  </div>
</template>
<script>
export default {
  data(){
    return{
      fruits: ['orange'.'pomelo'.'pineapple']}},methods: {addItem(){
      this.fruits.push(`The ${Date.now()}`)
      this.fruits.push(`The ${Date.now()}`)
      this.fruits.push(`The ${Date.now()}`)
      // 1. Render asynchronously, $nextTick will call back when the DOM is rendered
      // 2. Data changes will be integrated during page rendering. Multiple data changes will only be rendered once
    this.$nextTick(() = >{
      const ulElem = this.$refs.ul1
      console.log(ulElem.childNodes.length); })}}}</script>
Copy the code

Code demo:

Bernays! With $nextTick, we implemented the function of obtaining the DOM node immediately after changing the data 😋.

3. slot

There are many slot knowledge points, including basic usage (basic knowledge points), scope slots and named slots.

The basic use

Child component code:

<template>
  <div>
<a :href="url">
      <slot>Here's the default</slot>
</a>
  </div>
</template>
<script>
export default {
  props: ['url'].data(){
    return{}}}</script>
Copy the code

{{webiste.title}} () {{webiste.title}} () {{webiste.title}} () {{webiste.title}} ();

Root component code:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <SlotDemo :url="webiste.url">
      {{website.title}}
    </SlotDemo>
  </div>
</template>
<script>
import SlotDemo from './Slot.vue'
export default {
  components:{
    SlotDemo
  },
  data(){
    return{
      name:'Orange's front end amusement park'.website: {url:'www.baidu.com'.title:'Google it'}}}}</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

Look! We have successfully inserted the data 🙃 into the slot.

Scope slot

The primary purpose of scope slots is for children to throw values from data for the parent to get. The scope slots are a little confusing, so let’s go straight to the code.

ScopedSlot subcomponent code:

<template>
  <div>
    <a href="url">
      <slot :slotData='website'>// The slotData is arbitrary and can be received by the parent component</slot>
    </a>
  </div>
</template>
<script>
export default {
  props: ['url'].data(){
    return{
      website: {url:'https://www.jd.com/'.title:'JD Shopping'}}}}</script>
Copy the code

Root component code:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <ScopedSlot :url="website.url">
    <! -- Here the template is mandatory, and slotprops is arbitrary -->
      <template v-slot="slotprops">
        {{slotprops.slotData.title}}
      </template>
    </ScopedSlot>
  </div>
</template>
<script>
import ScopedSlot from './ScopedSlot.vue'
export default {
  components:{
    ScopedSlot
  },
  data(){
    return{
      name:'Orange's front end amusement park'.website: {url:'www.baidu.com'.title:'Google it'}}}}</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

Code demo:

Look! We get the data of the child component in the heel component and insert it into the slot of the child component. That’s what scope slots are for 😝!

A named slot

There are multiple Solts that give each slot a name, so let’s look at the code.

NamedSlot Component code:

<template>
  <div>
  <h1><slot name='slot1'></slot></h1>
  <h2><slot></slot></h2>
  <h3><slot name='slot2'></slot></h3>
  </div>
</template>
<script>
export default{}</script>
Copy the code

Root component code:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <NamedSlot>
      <template v-slot:slot1>I'm H1 and I'm going to insert into SloT1</template>
      <template v-slot:slot2>I'm h2 and I'm going to plug in slot2</template>
      <p>I am P and will be inserted into an unnamed slot</p>
    </NamedSlot>
  </div>
</template>
<script>
import NamedSlot from './NamedSlot.vue'
export default {
  components:{
    NamedSlot
  },
  data(){
    return{}}}</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

Code demo:

See, we insert the data into the slot we want to insert, that’s what named slot is for 😊.

4. Dynamic and asynchronous components

:is = “component-name”; Scenarios that need to be rendered dynamically based on data, i.e. the component type is uncertain

Dynamic components

For example, if you want to develop a news detail page, you only know the data, not the order in which the components are rendered

Let’s implement this function now:

Root component code:

<template>
<div>
    <div v-for="(val,key) in comname" :key='key'>
    <component :is="val.type"></component>
  </div>
</div>
</template>
<script>
import MyText from './Text.vue'
import MyImage from './Image.vue'
export default {
    components:{
    MyText,
    MyImage
  },
  data(){
    return{
      comname: {1: {type:'MyText'
        },
        2: {type:'MyText'
        },
        3: {type:'MyImage'},}}}}</script>
Copy the code

Child component code:

<template>
  <div>
    <p>I'm the Text component</p>
  </div>
</template>
<script>
export default {
  data(){
    return{}}}</script>
Copy the code
<template>
  <div>
    <p>I'm the Image component</p>
  </div>
</template>
<script>
export default{}</script>
Copy the code

Code demo:

Asynchronous components

Asynchronous components exist to be loaded on demand. Large components, such as Echart ICONS or code editors, can have a significant impact on performance when loaded in the first place. Components are imported when they are registered using the import() function

Root component code:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <AsyncComp v-if="isShow"/>
    <button @click="showComp">show AsyncComp</button>
  </div>
</template>
<script>
export default {
  components: {AsyncComp:() = >import('./AsynComponent.vue')},data(){
    return{
      name:'Orange's front end amusement park'.website: {url:'www.baidu.com'.title:'Google it'
      },
      isShow:false}},methods: {showComp(){
      this.isShow=!this.isShow
    }
  }
}
</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

AsynComponent code

<template>
  <div>
     <p>Input box:</p>
    <input type="text" v-model.trim="name">
    <! -- <input type="text" v-model.lazy="name"> <input type="text" v-model.number="age"> -->
    <p>Multiline text</p>
    <textarea  cols="30" rows="10" v-model="text"></textarea>
    <p>Check box</p>
    <input id="Orange" type="checkbox" v-model="checked1">
    <label for="Orange">The oranges</label>
    <input id="Grapefruit" type="checkbox" v-model="checked2">
    <label for="Grapefruit">grapefruit</label>
    <input id="Pineapple" type="checkbox" v-model="checked3">
    <label for="Pineapple">pineapple</label>
    <p>Radio buttons</p>
    <input type="radio" id="male" value="male" v-model="gender">
    <label for="male">male</label>
    <input type="radio" id="female" value="female" v-model="gender">
    <label for="female">female</label>
    <p>Drop-down list selection (radio selection)</p>
    <select name="" id="" v-model="selected">
      <option disabled value="">Please select a</option>
      <option value="">A</option>
      <option value="">B</option>
      <option value="">C</option>
      <option value="">D</option>
    </select>
    <p>Drop-down list selection (multiple selection)</p>
    <select name="" id="" v-model="selectedList" multiple>
      <option disabled value="">Please select a</option>
      <option value="A">A</option>
      <option value="B">B</option>
      <option value="C">C</option>
      <option value="D">D</option>
    </select>
  </div>
</template>
<script>
export default {
    data(){
    return {
      name:'orange'.age:18.text:'1314520'.checked1:true.checked2:false.checked3:true.6
      gender:'male'.selected:' '.selectedList: []}}}</script>
Copy the code

Code demo:

We will find that the component will be introduced and rendered only when the button is clicked to display it, greatly improving performance. This is where the asynchronous component comes in — load 👍 on demand.

5. keep-alive

Cache component; Suitable for frequently switching scenes that do not require repeated rendering, such as Tab bar switching. Let’s see how it works through a code demonstration.

Root component code:

<template>
  <div>
    <p>Advanced features</p>
    <p>{{name}}</p>
    <KeepAlive/>
  </div>
</template>
<script>
import KeepAlive from './KeepAlive.vue'
export default {
  components:{
    KeepAlive
  },
  data(){
    return{
      name:'Orange's front end amusement park',}}}</script>
<style>
body{
  background-color: rgb(176.138.226);
}
  p:nth-child(2) {color: lightgreen;
  }
</style>
Copy the code

KeepAlive component code:

<template>
  <div>
    <button @click="changeState('A')">A</button>
    <button @click="changeState('B')">B</button>
    <button @click="changeState('C')">C</button>
      <KeepAliveA v-if="state==='A'"/>
      <KeepAliveB v-if="state==='B'"/>
      <KeepAliveC v-if="state==='C'"/>
  </div>
</template>
<script>
import KeepAliveA from './KeepAliveStateA.vue'
import KeepAliveB from './KeepAliveStateB.vue'
import KeepAliveC from './KeepAliveStateC.vue'
export default {
  components:{
    KeepAliveA,
    KeepAliveB,
    KeepAliveC
  },
  data(){
    return{
      state:'A'}},methods: {changeState(state){
      this.state=state
    }
  }
}
</script>
Copy the code

KeepAliveA (B, C) code:

<template>
  <div>This is A component.</div>
</template>
<script>
export default {
  mounted() {
    console.log('A is mounted')},destroyed(){
    console.log('A is destroyed')}}</script>
Copy the code

Code demo:

We found that when we switched components, the components were destroyed, which was very performance consuming, and we needed to cache the components.

We have keepalive wrapping up all these components, so let’s see what happens

Look! We have successfully cached the components with the Keepalive tag, which improves performance. 😀!

6. Mixin

Multiple components have the same logic, pulled out; Mixins are not perfect solutions there are solutions, and in Vue3.0, the proposed Composition API addresses these issues. Let’s take a look at the code to see what a Mixin is

Mixin component code:

<template>
  <div>
    <p>My name is {{name}}</p>
    <p>{{age}}</p>
    <p @click="showPicture">This is my picture</p>
  </div>
</template>
<script>
  import myMixin from './Mixin'
export default {
  mixins:[myMixin],// You can add multiple
  data(){
    return{
        name:'orange'}},mounted(){
    console.log('Name is Mounted'); }}</script>
Copy the code

Code demo:

We have 18 extra pages and a few unfamiliar pieces of code on the console. Where did this come from? The answer is mixn. We defined the mixin.js file

export default {
  data() {
    return {
      age: 18,}},methods: {
    showPicture() {
      console.log("picture is here")}},mounted() {
    console.log("Mixin is mounted")}},Copy the code

Mixins take this common logic out and introduce it through mixns, avoiding duplication of definitions.

Some problems with Mixn:

  1. The source of variables is not clear, which is not conducive to reading
  2. Multiple mixins can cause naming conflicts.
  3. Mixins may have a many-to-many relationship with components, resulting in high complexity.

The last

This article summarizes the advanced features of Vue, although you can not use in your work, but is the so-called skill is no burden, master these skills may be work, we make clear the application scenario of various features, believe that by learning accumulation, readers will be able to play the Vue ~ if this article helpful to you, Please click on the GitHub blog at github.com/skyblue309. I have other columns, welcome to read ~ Vue from give up to easy to play with the beauty of CSS JavaScript