Custom v – model

//index.vue<! -- Custom v-model --><p>{{name}}</p>
    <CustomVModel v-model="name"/>
Copy the code
<template>
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
    <! -- 1. Input uses :value instead of v-model 2. Change1 and model.event1 correspond to each other. Text1 correspond to each other -->
</template>

<script>
export default {
    model: {
        prop: 'text1'.// Corresponding to props text1
        event: 'change1'
    },
    props: {
        text1: {type:String.default() {
            return ' '}}}}</script>
Copy the code

The official documentation

$nextTick & refs

$nextTick

  • Vue is asynchronous rendering
  • DOM does not render immediately after data changes
  • The $nextTick is triggered after DOM rendering to get the latest DOM node

Render asynchronously, $nextTick calls back after DOM rendering. Data modifications will be integrated during page rendering, and multiple data modifications will only be rendered once

<template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">To add a</button>
  </div>
</template>

<script>
export default {
  name: 'app'.data() {
      return {
        list: ['a'.'b'.'c']}},methods: {
    addItem() {
        this.list.push(`The ${Date.now()}`)
        this.list.push(`The ${Date.now()}`)
        this.list.push(`The ${Date.now()}`)

        // 1. Render asynchronously, $nextTick will wait for DOM to render and then call back
        // 3. Data modifications will be integrated during page rendering. Multiple data modifications will only be rendered once
        this.$nextTick(() = > {
          // Get the DOM element
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          console.log( ulElem.childNodes.length )
        })
    }
  }
}
</script>
Copy the code

slot

  • Basic use:
//index
<SlotDemo :url="website.url">
      {{website.title}} // Slot contents
</SlotDemo>
Copy the code
//SlotDemo.vue
<template>
    <a :href="url">
        <slot>Default content, that is, if the parent component does not set content, the // slot default value is displayed here</slot>
    </a>
</template>

<script>
export default {
    props: ['url'].data() {
        return{}}}</script>
Copy the code
  • Scope slot:
//index.vue
<ScopedSlotDemo :url="website.url"> 
            <template v-slot="slotProps">{{slotProps. Slotdata.title}} // define a parameter to receive the value passed in</template>
        </ScopedSlotDemo>
Copy the code
//ScopedSlotDemo.vue
<template>
    <a :href="url">
        <slot :slotData="website">// Define a value to pass to the parent component {{website. SubTitle}}<! -- Default shows subTitle when the parent component does not pass content -->
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'].data() {
        return {
            website: {
                url: 'http://wangEditor.com/'.title: 'wangEditor'.subTitle: 'Lightweight Rich Text Editor'}}}}</script>
Copy the code
  • A named slot
index.vue
<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>
Copy the code
// Components with named slots //<div class="container">
  <header>
    <slot name="header"></slot>
  </header>// It can be written either way<p>A paragraph for the main content.</p>
  <p>And another one.</p>/ / method 2<template v-slot:default>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </template>
  
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
Copy the code

Like v-on and v-bind, v-slot has an abbreviation that replaces everything before the argument (v-slot:) with the character #. For example, v-slot:header can be rewritten as #header:

Dynamic components

  • usage:is="compontent-name"
<component :is="NextTickName"/>
...
export default {
    components: {
         NextTick
    },
    data() {
        return {
             NextTickName: "NextTick".// Define a variable with the same value as the component name used}}}Copy the code
// An example
<div v-for="(val,key) in newsData" :key="key">
    <component :is="val.type"/>
</div>
...

data() {
    return {
         newsData: {1: {type: 'text'
             },
             2: {type: 'text'
             }
             3: {type: 'image'}}}}Copy the code

Asynchronous components (one of the Vue performance optimizations)

  • The import () function
  • Load on demand, load large components asynchronously
<! -- Asynchronous components --><FormDemo v-if="showFormDemo"/> // Define asynchronous components
   <button @click="showFormDemo = true">show form demo</button> // Set the button, click the event trigger showFormDemo to true

<script>
//import FormDemo from '.. /BaseUse/FormDemo' // Sets the synchronization component
export default {
    components: {
       FormDemo: () = > import('.. /BaseUse/FormDemo'),// Set the asynchronous component}},</script>
Copy the code

Keep-alive (One of Vue performance optimizations)

  • Cache components
  • Frequent switching, no need to repeat the rendering
  • Vue common performance optimizations

Grammar: < keep alive – >…

// Use cases combining components and dynamic components
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
Copy the code

mixin

  • Multiple components have the same logic, pull out
  • Mixins are not perfect solutions, and there are problems
  • Vue3’s Composition API aims to address these issues
//index.vue
<template>
    <div>
        <MixinDemo/>
    </div>
</template>
<script>

import MixinDemo from './MixinDemo'

export default {
    components: {
        MixinDemo
    },
}
</script>
Copy the code
// MixinDemo.vue
<template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">Display name</button>
    </div>
</template>

<script>
import myMixin from './mixin'
export default {
    mixins: [myMixin], // Multiple can be added and will be merged automatically
    data() {
        return {
            name: The more 'double'.major: 'the web front end'}},methods: {},mounted() {
        // eslint-disable-next-line
        console.log('component mounted'.this.name)
    }
}
</script>
Copy the code
// mixin.js
export default {
    data() {
        return {
            city: 'Beijing'}},methods: {
        showName() {
            // eslint-disable-next-line
            console.log(this.name)
        }
    },
    mounted() {
        // eslint-disable-next-line
        console.log('mixin mounted'.this.name)
    }
}
Copy the code

The problem of a mixin

  • Variable sources are not clear, which is not conducive to reading
  • Multiple mixins can cause naming conflicts
  • Minins and components may have a many-to-many relationship, which is highly complex