Vue components and Prop data flow

  1. Understanding of components and props A
    component is equivalent to defining a function. Using a component (such as a parent component) is equivalent to calling a function. At this time, if you need to pass a value, you must pass it from the parent component; and props is to pass the parent component down through props Passed to the child component; the child component sends messages to the parent component through events.
    It is necessary to ensure that each component can be written in a relatively isolated environment, which can improve the maintainability of the component. There are two ways for the parent component to pass data to the child component: dynamic and static;

  2. Component usage:

//子组件代码如下:
// const data = { text: 123 }
 const component = {
    
    
  template: `
    <div>
      <span>This is component {
     
     {text}}</span>
      <input type="text" v-model.number="text" >
    </div>
    `,
  // data:{ text: 123 } 直接写data 写法错误
  // data () {
    
    
  //   return data 这样写会导致使用组件的所有data都一样
  // }
  data () {
    
    
    return {
    
    
      text: 123
    }
  }
}
//父组件
// Vue.component('CompOne', component) 使用组件的另一种方式
new Vue({
    
    
  components: {
    
    
    CompOne: component
  },
  el: '#root',
  template: `
    <div>
      <comp-one></comp-one>
      <comp-one></comp-one>
    </div>  
  `
})
  1. The naming convention
    of props For the properties declared by props, in the template template of the parent component, the property name needs to be written in the middle line;
    when the props property of the child component is declared, either small hump or the middle line can be used; and the template of the child component When using the variable passed from the parent component, you need to use the corresponding little camel case. Vue can correctly identify variables with a mixture of small hump and underscore nomenclature.

  2. The scope of the static props component instance is isolated, which means that the data of the parent component cannot be directly referenced in the template of the child component. To let the child component use the data of the parent component, you need to pass the props option of the child component.
const component = {
    
    
  props: {
    
    
    propOne: String
  },
  template: `
    <div>
      <span>This is component {
     
     {text}}</span>
      <span>{
     
     {propOne}}</span>
    </div>
    `,
  data () {
    
    
    return {
    
    
      text: 123
    }
  }
}
new Vue({
    
    
  components: {
    
    
    CompOne: component
  },
  el: '#root',
  template: `
    <div>
      <comp-one prop-one="prop1"></comp-one>
      <comp-one prop-one="prop2"></comp-one>
    </div>  
  `
})

Insert picture description here

  1. Dynamic props

    In the template, you need to dynamically bind the data of the parent component to the props of the child component template, just like binding the Html tag feature, using v-bind binding;

const component = {
    
    
  props: {
    
    
    propOne: String,
    active: Boolean
  },
  template: `
    <div v-show="active">
      <span>This is component {
     
     {text}}</span>
      <span>{
     
     {propOne}}</span>
    </div>
    `,
  data () {
    
    
    return {
    
    
      text: 123
    }
  }
}
new Vue({
    
    
  components: {
    
    
    CompOne: component
  },
  el: '#root',
  template: `
    <div>
      <comp-one :prop-one="p1" :active="true"></comp-one>
      <comp-one :prop-one="p2" :active="false"></comp-one>
    </div>  
  `,
   data: {
    
    
    p1: "prop1",
    p2: "prop2"
  },
})

The data p1, p2, active of the parent component will be passed to the child component

  1. Props verification

Verify the data specification of the passed props parameter. If it does not meet the data specification, Vue will issue a warning.

Vue.component("example", {
    
    
 props: {
    
    
	 // 基础类型检测, null意味着任何类型都行
	 propA: Number,
	 // 多种类型
	 propB: [String, Number],
	 // 必传且是String
	 propC: {
    
    
	  type: String,
	  required: true
	 },
	 // 数字有默认值
	 propD: {
    
    
	  type: Number,
	  default: 101
	 },
	 // 数组、默认值是一个工厂函数返回对象
	 propE: {
    
    
	  type: Object,
	  default: function() {
    
    
	  console.log("propE default invoked.");
	  return {
    
     message: "I am from propE." };
	  }
	 },
	 // 自定义验证函数
	 propF: {
    
    
	  isValid: function(value) {
    
    
	  return value > 100;
	  }
	 }
	}
  })

You can also add a custom verification function to the data defined by props. When the function returns false, a warning
is output . All types (that is, type values) that can be judged are: String, Number, Boolean, Function, Object, Array, Symbol

  1. The data flow of
    props -one-way props are one-way binding: when the property of the parent component changes, it will be passed to the child component, but not the other way around. This is to prevent the child component from incorrectly modifying the state of the parent component.
    So you should not modify the value of props in the subcomponent, Vue will report a warning.
 let childNode = {
    
    
 template: `
   <div class="child">
   <div>
    <span>子组件数据</span>
    <input v-model="forChildMsg"/>
   </div>
   <p>{
     
     {forChildMsg}}</p>
   </div>`,
  props: {
    
    
   "for-child-msg": String
 }
};
let parentNode = {
    
    
 template: `
   <div class="parent">
   <div>
    <span>父组件数据</span>
    <input v-model="msg"/>
   </div>
   <p>{
     
     {msg}}</p>
   <child :for-child-msg="msg"></child>
   </div>
  `,
 components: {
    
    
  child: childNode
 },
 data() {
    
    
   return {
    
    
     msg: "default string."
   };
 }
};

Here we have an input box for the parent component and the child component, and display the data of the parent component and the child component. When we enter new data in the input box of the parent component, the synchronized child component data is also modified; this is the transfer of props to the child component. When we modify the input box of the child component, the browser console reports an error warning
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: “forChildMsg”
8.
There are usually two reasons for modifying the data of props :

After prop is passed in as the initial value, the child component wants to
treat it as local data. After the prop is passed in as the initial value, the child component will process it into other data output

The answer is

Define a local variable and initialize it with the value of prop.
But because the defined ownChildMsg can only accept the initial value of forChildMsg, when the value to be passed by the parent component changes, ownChildMsg cannot receive the update.

let childNode = {
    
    
 template: `
   <div class="child">
   <div>
    <span>子组件数据</span>
    <input v-model="forChildMsg"/>
   </div>
   <p>{
     
     {forChildMsg}}</p>
   <p>ownChildMsg : {
     
     {ownChildMsg}}</p>
   </div>`,
 props: {
    
    
   "for-child-msg": String
 },
 data() {
    
    
   return {
    
     ownChildMsg: this.forChildMsg };
 }
};

Here we add a p tag to check whether the data of ownChildMsg has changed, and it turns out that only the default value is passed to ownChildMsg, and the parent component change will only change to forChildMsg, and will not modify ownChildMsg.

Define a calculated property, process the value of prop and return it.
Because it is a calculated property, it can only display the value, not set the value. What we set here is that once the forChildMsg data is modified from the parent component, we will add a string "—ownChildMsg" to forChildMsg and display it on the screen. At this time, it is possible to update ownChildMsg data whenever the parent component modifies new data.

let childNode = {
    
    
 template: `
   <div class="child">
   <div>
    <span>子组件数据</span>
    <input v-model="forChildMsg"/>
   </div>
   <p>{
     
     {forChildMsg}}</p>
   <p>ownChildMsg : {
     
     {ownChildMsg}}</p>
   </div>`,
 props: {
    
    
   "for-child-msg": String
 },
 computed: {
    
    
   ownChildMsg() {
    
    
     return this.forChildMsg + "---ownChildMsg";
 }
 }
};

A more appropriate way is to use variables to store the initial value of prop, and use watch to observe changes in prop value. When a change occurs, the value of the variable is updated.

let childNode = {
    
    
 template: `
   <div class="child">
   <div>
    <span>子组件数据</span>
    <input v-model="forChildMsg"/>
   </div>
   <p>{
     
     {forChildMsg}}</p>
   <p>ownChildMsg : {
     
     {ownChildMsg}}</p>
   </div>`,
 props: {
    
    
   "for-child-msg": String
 },
 data() {
    
    
   return {
    
    
     ownChildMsg: this.forChildMsg
   };
 },
 watch: {
    
    
   forChildMsg() {
    
    
     this.ownChildMsg = this.forChildMsg;
   }
 }
};

Guess you like

Origin blog.csdn.net/weixin_39854011/article/details/106209421