Vue FAQ collection

Are you tired of working? Tired ah. But I can’t cry, because it’s not safe to wipe tears while riding an electric bike. Good morning, worker!!

Transfer values between VUE components

1. Father passes son

This method is relatively simple. The child component only needs to use props to receive the data passed by the parent component

// Parent component code<p> Parent component <p><input type="text" v-model="parentData">
<Children :parentData="parentData"></Children>-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- child component code -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- props: {parentData: {type: String, required: true}}Copy the code

Son to father

Sending a value from the child to the parent requires submitting (this.$emit) a custom method that the parent listens for to get the value from the child.

//----------- child component code ----------
<p><input type="text" v-model="childrenData"></p>
<p><button @click="handelChildren">Click Pass value to parent component</button></p>
export default{
    name:'Children'.data(){
        return{
            childrenData:' '}},methods: {handelChildren(){
            this.$emit('onSetData'.this.childrenData)
        }
    }
}
//---------------- parent component code -----------------
<Children @onSetData="handelSetData"></Children>
export default{
    name:'Parent'.data(){
        return{
            number:' '}},methods: {handelSetData(val){
            this.number = val
        }
    }
}
Copy the code

, $3 refs

The parent gets the child’s data and methods via $refs: write a ref=” XXX “when calling the child, and this.$refs.xxx in the parent. The this.$refs.xxx. Method is used to pass values from parent components to children

//---------------- parent component code -----------------
<template>
    <div>
        <children-comp ref="child"></children-comp>
        <button @click="getChildProp()">Gets the property value of the child component</button>
        <button @click="getChildMethod()">Methods to get child components</button>
    </div>
</template>
<script>
import ChildrenComp from './ChildrenComp.vue'
export default{
    components:{
        ChildrenComp
    },
    data(){
        return{}},methods: {getChildProp(){
            alert(this.$refs.child.msg);
        },
        getChildMethod(){
            this.$refs.child.run(); }}}</script>

//---------------- child component code -----------------
<script>
    export default{
        data(){
            return: {msg:'I'm the value of the child component.'}},methods: {run(){
                alert("I am a child component method"+this.msg); }}}</script>
Copy the code

4, $parent

The child gets the parent’s data and methods from $parent: use this.$parent. XXX directly in the child without doing anything extra.

// Examples of sub-component code
<script>
    export default{
        methods: {getFatherProp(){
                let fatherMsg = this.$parent.fatherMsg;
            },
            getFatherMethod(){
                this.$parent.fatherRun();
            }
        }       
    }
</script>
Copy the code

5. Sibling components pass values

// Operation procedure
1Create a new Vue instance so that all siblings share the same event mechanism. (Key point: Using the Bus event Bus, create a relay station to transfer values)2$emit --> Trigger $emit via an event ('Method name'.'Data passed')
3Mounted () -> Raises $on('Method name',callback(received data)) in the callback functionthisChanges have been made to use the arrow functionCopy the code
  • This is declared first in main.js
Vue.prototype.$bus = new Vue();
Copy the code
  • The parent component has two children that are siblings
<template>
    <div>
        <child1></child1>
        <child2></child2>
    </div>
</template>

<script>
import child1 from './userChild/child1'
import child2 from './userChild/child2'
export default {
    components:{
        child1,
        child2
    },
    data(){
        return {
            value:' ',}}}</script>
Copy the code
  • Child components pass values
//---------------- subcomponent 1----------------
<template>
    <div class="child1">The child component 1<div>
            <el-input v-model="value"></el-input>
            <el-button @click="submit">submit</el-button>
        </div>
    </div>
</template>
<script>
export default {
    data(){
        return{
            value:' '}},methods: {submit(){
            this.$bus.$emit('onName'.this.value)
        }
    }
}
</script>
//---------------- subcomponent 2----------------
<template>
    <div class="child2">The child component 2<div>{{MSG}} submitted the application</div>
    </div>
</template>
<script>
export default {
    data(){
        return{
            msg:' '}},mounted(){
        this.$bus.$on('onName'.(value) = >{
            this.msg = value; }}})</script>
Copy the code

Dependency injection Provide&inject

Provide /inject needs to be used together to allow an ancestor to inject a dependency to all of its descendants, one-way, parent-only –> descendants, regardless of component level, and remain in effect as long as the upstream/downstream relationship is established.

Provide is equivalent to an enhanced parent prop that can span intermediate components; Inject is equivalent to props for a reinforced child component

//----------- in the parent component ------------
<template>
	<div id="app">
         {{count}}
      <child-component @update:xxx="changeCount"></child-component>
    </div>
</template>
<script>
export default {
    data: {
        count: 2000.text: 'hello world! '
    },
    provide: function () {
        return {
            infos:this.text, // Here is the data defined in data
            fun:this.fun // Here are the methods defined in methods}}},</script>
//----------- in the descendant component ------------
<script>
export default {
    inject:['infos'.'fun'].// Use this as the normal component
    data: {
        count: 2000.text: 'hello world! '}}</script>
Copy the code

Vuex data sharing to transfer values to each other to change state

Vue dynamically binds classes

The first is the form of an object

  • The simplest binding (active can be rendered with or without single quotes)
//isActive is a Boolean in data, active is a class style class
The style class active only takes effect when isActive is true
<div :class='{active:isActive}'>123</div>
Copy the code
  • Determines whether to bind an active
<div :class='{active:isActive == index}'>123</div>
Copy the code
  • Bind and judge multiple
1<div;class='{active:isActive, sort:isSort}'>123</div>
2<div style = "box-sizing: border-box! Important;class='classObject'>123</div>
export default{
    data(){
        return{
            classObject: {active:true.sort:false}}}};3Third (using computed attributes) <div:class='classObject'>123</div>
export default{
    data(){
        return{
            isActive:true.isSort:false}},computed: {classObject:function(){
            return{
                active:this.isActive,
                sort:this.isSort
            }
        }
    }
};
Copy the code

Second: array form

  • Pure array
<div :class='[isActive,isSort]'>123</div>
export default{
    data(){
        return{
            isActive:true.isSort:false}}};Copy the code
  • Arrays are combined with ternary operators to determine which class to select
<div :class="[ isActive ? 'active':'' ]">123</div>
/ / or
<div :class="[ isActive==index ? 'active':'otherActive' ]">123</div>
Copy the code
  • Array associative object dynamic determination
// Active can be unquoted in the object, sort can be quoted in the object
<div :class="[{active:isActive}, 'sort']">123</div>
/ / or
<div :class="[{active:isActive==index}, 'sort']">123</div>
Copy the code

Vue dynamically adds style

Vue adds style dynamically:

1All style names with - should be camel weight, such as font weight should be written as fontWeight2In addition to the binding value, the values of other attribute names should be quoted, such as width:'75px'And don't forget the quotes3For dynamic binding, the property value and property name are enclosed in bracesCopy the code
1, object form :style="{ width:activeWidth,fontSize:fontSize + 'px' }"
2, array form :style="[{height:(warnData.length>0 ? '100px':'200px')},{color:'#fff'}]"
3, bind the form of data object :style="activeStyle"
export default{
    data(){
        return{
            activeStyle: {color:'#fff'.fontSize:'16px'}}}}Copy the code

Vue dynamic components

Scenario: Dynamic component loading is involved when tabbing

// Dynamic composition can be achieved by using the reserved < Component > element to dynamically bind to its IS feature
<component :is="currentTabComponent"></component>
// However, each time the component is reloaded, it consumes a lot of performance, so the cache component is used instead
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>
// There is no animation for this toggle effect, this is not a rush, can use the built-in animation effect
<transition>
    <keep-alive>
        <component v-bind:is="currentTabComponent"></component>
    </keep-alive>
</transition>
Copy the code

Reference: ① VUE dynamic component details

Bidirectional binding of VUE components

The communication between parent and child components in VUE is one-way. Directly modifying the value passed by prop in the child component will give a warning, so the following solution is needed

Method 1: Model option (The num attribute bound by the v-Model instruction of the parent component is passed to the data attribute of the child component through the model option, and the child component changes the NUM attribute of the parent component through a custom event)

//----------------- Parent component ----------------
<template>
    <div>
        <child v-model="num">{{num}}</child>
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123}}}</script>
//----------------- child component ----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    model: {prop:'data'.// Specify which property of the child the parent is bidirectionally bound to
        event:'on-change' // Specifies the name of the event that triggers the bidirectional binding
    },
    props: {data:Number
    },
    methods: {change(event){
            this.$emit('on-change'.Number(event.target.value)); }}}</script>
Copy the code

Method two: Through prop and custom properties

//----------------- Parent component ----------------
<template>
    <div>
        <child :data="num" @on-change="num=$event">{{num}}</child>
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123}}}</script>
//----------------- child component ----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    props: {data:Number
    },
    methods: {change(event){
            this.$emit('on-change'.Number(event.target.value)); }}}</script>
Copy the code

Method three: sync modifier

//----------------- Parent component ----------------
<template>
    <div>
        <child :data.sync="num">{{num}}</child> 
    </div>
</template>
<script>
import child from './child'
export default{
    components:{
        child
    },
    data(){
        return{
            num:123}}}</script>
//----------------- child component ----------------
<template>
    <div>
        <input type="text" :value="data" @input="change" ></input>
    </div>
</template>
<script>
import child from './child'
export default{
    props: {data:Number
    },
    methods: {change(event){
            this.$emit('update:data'.Number(event.target.value)); }}}</script>
Copy the code

Vue.observable

2.6.0 New Usage: Make an object responsive. It is used internally by Vue to process objects returned by the data function; The returned object can be used directly in rendering functions and computed properties, and will trigger an update when changes occur; It can also serve as a minimal cross-component state store for simple scenarios. The communication principle is to implement a simple VUex by vuue. Observable

// File path - /store/store.js
import Vue from 'vue'

export const store = Vue.observable({ count: 0 })
export const mutations = {
  setCount (count) {
    store.count = count
  }
}

/ / use
<template>
    <div>
        <label for="bookNum">quantity</label>
            <button @click="setCount(count+1)">+</button>
            <span>{{count}}</span>
            <button @click="setCount(count-1)">-</button>
    </div>
</template>

<script>
import { store, mutations } from '.. /store/store' Vue2.6 added API Observable

export default {
  name: 'Add'.computed: {
    count () {
      return store.count
    }
  },
  methods: {
    setCount: mutations.setCount
  }
}
</script>
Copy the code