This is the fifth day of my participation in the August Wen Challenge.More challenges in August

The use of the ref

It is common to use a ref to retrieve a DOM element, although Vue does not recommend manipulating the DOM, except in complex cases. The following example: child component reuse, by clicking the child component to modify the value in the parent component, the knowledge point used includes the child component to transmit value to the parent component, and obtain the data of the child component.

  <div id="app">
    <couter @change="handleChange" ref="one"></couter>
    <couter @change="handleChange" ref="two"></couter>
    <div>{{total}}</div>
  </div>
Copy the code
Vue.component('couter', {
      template: '<div @click="handleClick">{{number}}</div>'.data() {
        return {
          number: 0}},methods: {
        handleClick() {
        // this.number++ controls child component data
          this.number++;
          // When the data changes, the 'change' event is triggered, and the parent component detects the event and executes the corresponding method
          this.$emit('change')}}})var vm = new Vue({
      el: '#app'.data: {
        total: 0
      },
      methods: {
        handleChange() {
        // Since the child executes this function by firing the change event, the parent recalculates total every time the child clicks
          this.total = this.$refs.one.number + this.$refs.two.number
          This.$refs.one is the Vue instance component}}})Copy the code

The child component wants to change the value passed by the parent component

If the parent component sends a value, the child component cannot modify it. If the parent component sends a value, the child component cannot modify it.

<div id="app">
    <couter number="0"></couter>
</div>
Copy the code
var couter = {
      template: '<div @click = "handleClick">{{couterNumber}}</div>'.props: ['number'].data() {
        return {
          couterNumber: this.number
        }
      },
      methods: {
        handleClick() {
          this.couterNumber++
          // Instead of directly modifying the value passed by the parent component, you should assign a copy of the value, and operate on the copy}}}var vm = new Vue({
      el: "#app".components: {
        couter
      }
    })
Copy the code

Bind native events to components

Writing a click event on a child component of a parent component does not work.

<div id="app">// Binding click events to child component tags does not work.<couter @click.native="handleClick"></couter>
</div>
Copy the code

Value transfer across components: publish and subscribe

Sibling components want to control each other, which is equivalent to communicating with each other. Set up a public bus that contains methods for all vUE instances because $emit is involved to fire events and the $ON method to listen for events.

<div id="app">
        <Child content="hello"></Child>
        <Child content="world"></Child>
</div>
Copy the code
        Vue.prototype.bus = new Vue()
      // Every Vue instance has this bus property, which is equivalent to every component (including its children)
        Vue.component('Child', {
            template: '<div @click="handleClickChild">{{myContent}}</div>'.props: ['content'].data() {
                return {
                    myContent: this.content
                }
            },
            mounted() {
                // This points to the current component
                var _this = this
                // Use $on to monitor the change event, which is executed whenever triggered
                this.bus.$on('change'.function (val) {
                // Also note that this refers to changing the value of the current component, so you can store this value in advance.
                    _this.myContent = val
                })
            },
            methods: {
                handleClickChild() {
                // Since each component has a bus attribute, which in turn is an instance of Vue, there is a $emit method that fires the change event and passes the value
                // Note that bus is public.
                    this.bus.$emit('change'.this.myContent)
                }
            },
        })
        var vm = new Vue({
            el: "#app",})Copy the code

In the created() function, the function called is not undefined. For example, if a function is created(), the function called is not undefined.

Detail points in components

  1. When rendering with subcomponents in tags, be aware of some unknown bugs, such as the IS attribute
  2. Data in a child component must be a function, not an object. This is so that each sub-component has an independent data store, so that multiple sub-components do not interfere with each other.
  3. through$refs.refTo get a DOM node, or to bind a ref to a child component to get a reference to that child component, where the data can be written directlythis.$refs.ref.number(Number is the data in data in the component)
  4. Event names are usually in the form of verbiage, constants that appear in the program can be written separately in front of the file, in uppercase.
  5. Props parameter verification, which properties can be configured :(note the custom validator)

Use of slots

The usage scenarios of slots are as follows: A parent component passes DOM labels to its child components through its child components, and the child components receive DOM labels through its child components.

The named slot, which contains a template tag around it, uses v-slot to name the slot. Note V-slot can only be added to the<template>(with one exception),

 <div id="app">
    <Child>
      <template v-slot:"header">
        <p slot="header">
          <span>return</span>
        </p>
      </template>
      <template v-slot:"footer">
        <p slot="footer">The tail</p>
      </template>
    </Child>
  </div>
Copy the code
Vue.component('Child', {
      template: '
      
Default value Header

Hello world

Default footer
'
.methods: {// Note that slot cannot be bound methods can place a div outside the slot tag and bind events to the div handleClick(){ console.log('return')}}})// Default values can be set in slot tags. When no label is sent, the slot will be occupied by the default display. When DOM elements are sent, they will be replaced directly, regardless of what is inside var vm = new Vue({ el:'#app' }) Copy the code

Dynamic components

< Component :is=type>, where type is the corresponding component name, can be obtained by js. Two components can be realized switching display

        <button @click="change('Child')">I'm gonna go to Child</button>
        <button @click="change('myfooter')">Click to switch myFooter</button>
        <component :is="componentId"></component>
Copy the code
import Child from './childOne' 
import myfooter from './childTwo'

methods: {change(val){
           this.componentId = val
           // componentId writes the corresponding component name}}Copy the code

Component refresh

<div @click="refresh">Click Refresh component</div> 
<myfooter v-if="isShow"></myfooter >
Copy the code
import myfooter from './myfooter'
export default {
	data(){
		isShow: true
	},
	methods: {refresh(){
			this.isShow = false;
			this.$nextTick(() = > {  
                            // After DOM updates, reload the component
       			this.isShow = true})}},componets:{
		myfooter
	},
}
Copy the code

V – once the instructions

A better way to display static content is to display some static content once, put it in memory, and fetch it in memory when rendering again. Can improve performance very well.

The computed and watch

Instead of writing logical code in an HTML template, write in computed, and in computed, you can write get() and set() methods to get attributes, or set attributes. The Watch listener listens for properties in data and executes them as soon as they change. Such as:

watch:{
    letter () {
        console.log(this.letter) // This letter is the current value in the current data}}Copy the code
  • computed

    1. Caches are supported, recalculation occurs only when dependent data changes, and computed properties can be used to quickly compute properties displayed in the View. These calculations will be cached and updated only as needed. Computations are attributes; It dynamically displays new results based on the data it depends on, and the results are cached. Computed values are cached after getter execution. If the dependent data changes, the getter is re-invoked to calculate the latest result.
    2. Asynchronism is not supported. It does not work when there is asynchronous operation in computed, and data changes cannot be monitored
    3. If a property is computed by something else, that property depends on something else, it’s a many-to-one or one-to-one, usually computed
    4. If the computed attribute value is a function, the default is to use the GET method; The return value of the function is the property value of the property; In computed, attributes have a GET and a set method, which are called when data changes.
    5. Computed and Methods: Computed attributes are cached based on their responsive dependencies. They are reevaluated only when the associated reactive dependencies change. Reactive dependencies: data in data and props?
       computed: {
               fullName: { 
                   // getter
                   get: function () { 
                       return this.firstName + ' ' + this.lastName 
                   }, 
                   // setter
                   set: function (newValue) {
                       var names = newValue.split(' ') 
                       this.firstName = names[0] 
                       this.lastName = names[names.length - 1]}}}Copy the code

    Gets the property, calling the get method by default.

  • watch

    This approach is most useful when asynchronous or expensive operations need to be performed when data changes.

    In most cases, when the input box is bound to the V-Model, the value inside is monitored, and the newVal and oldVal arguments are passed in the callback. For example, you can send asynchronous requests in watch, but not computed.

        <div>
            <van-field 
                @focus="Focus (' num_s' 800350, 'up')" 
                @blur="blur('up')" 
                placeholder="Cash value" 
                v-model="begin_cash"
                maxlength="Seven" 
                type="number" 
                input-align="center" 
            />
        </div>
    Copy the code
    watch: {
            begin_cash(newVal, oldVal) {
                    if (newVal < 0) {
                        this.$toast('Input amount cannot be negative! ');
                        this.begin_cash = ' ';
                    }
                    if (newVal.toString().indexOf('. ') = = =0) {
                        this.begin_cash = ' ';
                    }
                    if (newVal === ' ' && oldVal.toString().indexOf('. ') > 0) {
                        this.begin_cash = oldVal;
                        return;
                    }
                    if (newVal) {
                        newVal = newVal.toString();
                        var pointIndex = newVal.indexOf('. ');
                        if (pointIndex > 0 && (newVal.length - pointIndex) > 3) {
                            this.begin_cash = oldVal;
                            return; }}}Copy the code

    Author: Late summer _ The sun still shines link: juejin.cn/post/699992… The copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.

Note when updating arrays in VUE

For example, if you want to change data in data, if the data is in array format, the data itself may have been updated, but the view will not be updated.

  <div id="app">
    <p v-for="item in arr">{{item}}</p>
    <! -- Still print 1, 2, 3 -->
  </div>
Copy the code
let vm = new Vue({
      el: '#app'.data: {
        arr: [1.2.3]},created() {
        setTimeout(() = > {
          this.arr[0] = 100
          console.log(this.arr) // [100,2,3], but the view is not updated
        }, 2000)}})Copy the code

Vue hook function

  • BeforeCreate (before instance creation)

    The instance component has just been created, and the element DOM and data have not been initialized

    Application scenario: You can add a loading event; Common logic can be mixed in, vue.mixin ()

  • Created data is initialized and methods are available, but the DOM is not rendered. During this cycle, requests can be made to change data and render it. Because the DOM is not mounted, too many requests or too much time will result in blank pages.

    Application scenario: Loading ends here and some initialization is performed to implement self-execution of the function

  • BeforeMoute DOM is not mounted, data initialization is complete, but bidirectional binding of data is still {{}} because vue uses virtual DOM technology.

  • The Render function creates the virtual DOM and mounts it.

  • Mouted (after the element is mounted) the data and DOM are mounted, and the data that was occupied in the previous cycle is rendered into the value. This is where the request is normally placed, because the request changes the data just enough to render.

  • BeforeUpdate this is triggered whenever the page data changes, the page data is the same before the data is updated, this cycle is executed when you request an assignment, not if there is no data change.

  • Updated (after an instance is updated) The first time the data is loaded, it is triggered whenever the page data is changed. BeforeUpdated, the page data is updated. Manipulating data here has a significant impact on performance and endless loops. Note: beforeUpdate and updated are not used much and can be monitored with watch.

  • BeforeDestory Called before instance destruction, at this step, the instance is still fully available. Application scenario: You can unbind custom events, unbind DOM events, and clear timers.

  • Destory is called after the vUE instance is destroyed. After this call, everything indicated by the vue instance is unbound, all event listeners are removed, and all subinstances are destroyed. Note: Switching routes, the component automatically executes beforeDestory and deStory hook functions.

    can be used for caching if switching is frequent.

The order in which parent and child components are executed

Synchronous and asynchronous components, parent and child components execute different hook functions in different order.

  • Import Page from ‘@/components/ Page ‘

    Lifecycle hook function execution order: BeforeCreate, created, beforeMount, beforeCreate for all child components, created, beforeMount, Mounted for all child components, mounted for the parent component

  • Asynchronous components:

    1. const Page = () => import('@/components/page')

    2. const Page = resolve => require(['@/components/page'], page)

    The lifecycle hook functions are executed in the following order: beforeCreate, created, beforeMount, Mounted for the parent, beforeCreate, created, beforeMount, mounted for the child

Vue.mixin()

Mixed logic: it is to form each hook function or data into an array and execute it in sequence. Public methods and write plug-ins [beforeCreate beforeCreate], Vue. Mixin () function can increase some hook.

Vue.mixin({
    beforeCreate(){
        console.log('1111111111') // Execute first}})Copy the code

Bug: Data source is unknown, Vue3 uses compositionApi to solve this problem.

<transition>Animation: Toggle show and hide effects

The
tag wraps the element to be switched

    <transition name="fade">
      <! Transition wraps around the element you want to animate -->
      <div 
        style="width:100px; height:100px" 
        class="box" 
        v-show="isShow"
        >
      </div>
    </transition>
    <button 
      style="width:100px; height:40px"
      @click="change"
      >Let me switch</button>
Copy the code
.box{
  backgroundRed} // At the beginning of the animation, such as the emergence of the moment.fade-enter{
  backgroundGreen} // The duration is2seconds.fade-enter-active{
  transition all 2s} // The final color is blue.fade-enter-to{
  background// The overall effect is: green => blue(continue2s// After the animation is over, all styles will be removed.fade-leave{// do not see the effect}.fade-leave-active{
  transition all 2s linear
}
.fade-leave-to{
  backgroundPink} // // total effect is: red => pink(continue2s), finally hide // After the end of direct hideCopy the code

Note: The V – instruction may be renamed if the animation is very large, so the name can be given.

Componentized development

  • Why componentize development?

    1. Implementing component reuse
    2. Easy to maintain code
    3. Only component level updates are given to each componentwatcherInstead of looking at all the components, find the component where the problem occurs.
    4. If you can pull out, pull out as soon as possible to reduce updates.
  • Component instantiation process

    Creates a Vue instance of the currently passed object. Put together the HTML, CSS, and JS of the current component.

    Vue.component('Child', {
            template: '<div @click="handleClickChild">{{myContent}}</div>'.data() {
                return {
                    myContent: this.content
                }
            },
    Copy the code

    Passing an object in Vue.component will call vue.extend () by default.

    Vue.extend(
        {
            template: '<div @click="handleClickChild">{{myContent}}</div>'.data() {
                return {
                    myContent: this.content
                }
            }
    )
    Copy the code

    Why is data a function? Functions can return an object, with different values in each component, to avoid data collisions in data.

Parent and child components pass values

  • Capitalization of Props

    Pass as a dash in the parent component

    <! -- kebab-case in HTML --> 
    <blog-post post-title="hello!"></blog-post>
    Copy the code

    Receive with hump nomenclature in child components

    Vue.component('blog-post', { 
    // In JavaScript it is camelCase
        props: ['postTitle'].template: '<h3>{{ postTitle }}</h3>' 
    })
    Copy the code

    Note: Any class of new data can be passed to Prop

  • Want to pass the entire object to Prop

    post: { 
        id: 1.title: 'My Journey with Vue' 
    }
    <blog-post v-bind="post"></blog-post>
    / / equivalent to
    <blog-post 
        v-bind:id="post.id" 
        v-bind:title="post.title">
    </blog-post>
    Copy the code

    If passed to prop is an object or an array, then a reference (address) is passed. Changing data in a child (not recommended) affects the parent.