Component value transfer, two-way data binding

1, Component value transfer

Value transfer mode between components

Parent child values: props, emit, $parent, $chidren, ref
Value transfer between brothers: event bus (on, emit), Vuex

Value transfer instance

(1) Parent component to child component (props)
A component can have any number of props by default, and any value can be passed to any props.

// Parent component
<template>
    <div>
        <ceshi @test="test"></ceshi>
    </div>
</template>
<script>
export default {
    data() {
        test: 'test'
    }
}
</script>

// Sub component receiving ceshi
<template>
    <div>
        {{test}}
    </div>
</template>
<script>
export default {
    props: {
        test: String
    }
    data() {
        
    }
}
</script>

(2) Pass child component to parent component (emit)
The child component triggers an event to the parent component through emit, and the parent component listens to data changes through on.

// Parent component
<template>
    <div>
        <ceshi :test="test" @change="change"></ceshi>
    </div>
</template>
<script>
export default {
    data() {
        test: 'test'
    },
    methods: {
       change(val){
           console.log(val)
       }
    }
}
</script>

// Sub component receiving ceshi
<template>
    <div>
        {{test}}
        <button @click="getTitle"></button>
    </div>
</template>
<script>
export default {
    `props: {
        test: String
    }`
    data() {
        title: 'Subcomponents'
    },
    methods: {
       getTitle(){
           this.$emit('change', this.title) // Bind the value to change and pass it to the past
       }
    }
}
</script>

2, prop

prop type

List as string:

props: ['title', 'likes', 'isPublished', 'commentIds', 'author']

Usually, we need each prop to have a specified value type, so we list and indicate the name, type and default value of the prop in the form of objects

props: {
   test: String,
   likes: {
       type: Number,
       default: () => []
   },
   isPublished: {
       type: Boolean,
       default: false
   }
}

Pass static or dynamic Prop

// Static value transmission
<blog-post title="My journey with Vue"></blog-post>

// Dynamically assign the value of a variable
<blog-post v-bind:title="post.title"></blog-post>

// Dynamically assign the value of a complex expression
<blog-post
  v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>

Unidirectional data flow

All props form a one-way downstream binding between their parent and child props: the updates of the parent props will flow down to the child components, but not vice versa. This will prevent the state of the parent component from being accidentally changed from the child component, which will make the data flow of your application difficult to understand.

Every time the parent component changes, all props in the child component will be refreshed to the latest value. This means that you should not change the prop inside a subcomponent. If you do, Vue will issue a warning in the browser's console.

When you need to change prop, you can

(1) In the subcomponent, you need to use prop as local data. You can use this prop as the initial value in data

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

(2) This prop is passed in as an original value and needs to be converted. In this case, it is best to use the value of this prop to define a calculation attribute:

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Note that in JavaScript, objects and arrays are passed in by reference, so for an array or object type prop, changing the object or array itself in the child component will affect the state of the parent component.

3, Custom event (v-model)

Bidirectional binding v-model

The v-model on a component will use prop named value and event named input by default, but input controls such as radio boxes and check boxes may use value attribute for different purposes. The model option can be used to avoid such conflicts:

// Subcomponents
<template>
    <div>
        <el-input v-model="price" @input="updateVal"></el-input>
    </div>
</template>
<script>
export default {
   // Model is used to change the properties of v-model binding and throw events (real-time listening)
    model: {
        prop: 'price',
        event: 'change'
   },
    props: {
        price: Number
    },
    methods: {
       updateVal(val){
           this.$emit('change', val) // Listen for the change of price value and pass it to the parent component
       }
    }
}
</script>

Use v-model in the parent component, and use this statement to realize the bidirectional binding of price variable and input value

<ceshi @change="change" v-model="price"></ceshi>


// Equivalent to
<ceshi @change="change" :value="price" @input="price=$event.target.value"></ceshi>

Execution process:
1. The child component receives the data price of the parent component through prop
2. When input is input, the input event is triggered
3. Submit the event through $emit and pass the value to the parent component
4. The input event of the parent component is triggered and the value of the variable price will be updated
5. The parent component passes the value to the child component through props

v-bind implements one-way binding
v-model to achieve two-way binding

. sync modifier

True two-way binding will bring maintenance problems, because child components can change the parent component, and there is no obvious source of change on both sides of the parent component and child component. Therefore, the mode of update:myPropName is recommended to trigger events

vue event name can be defined by updata:prop to handle the new value passed by prop
Within the component, an event will be triggered through $emit('update:dtitle', val) to modify the value of the title

// Subcomponents
<el-input v-model="title" @input="updateVal"></el-input>

props: ['title'],
updateVal(val) {
    this.$emit('update:dtitle', val)
}
// Parent component
<ceshi @update:dtitle="title = $event" :title.sync="title"></ceshi>

matters needing attention:
1, . The v-bind of the sync modifier cannot be used with an expression
2. The event name triggered by $emit is required inside the component. The format is update:prop

At the same time, when using sync, it is simplified to bind prop and update:prop events

4, Dynamic component & asynchronous component

5, Code example

Keywords: Front-end Vue.js html

Added by hacksurfin on Sun, 26 Dec 2021 02:46:55 +0200