关于vue.js:Vue-组件通信方式

父组件向子组件传值

  • 通过子组件的 props 选项承受父组件的传值
  • props内的数据能够在模板内间接应用
  • 留神:props不要与data 存在同名属性,会产生笼罩问题

子组件设置形式

Vue.component('my-com',{
  props:['title'],  // 父类中要绑定的属性
  template:'<h>{{ title }}</h>'
})

父组件设置形式

  • 给自定义组件设置属性

    <div id="app">
    <my-com title="实例内容1" ></my-com>  // 动态属性设置,无奈操作批改
    <my-com :title="'实力内容2'"></my-com>  // 动静属性设置:表达式(个别不通过动静属性绑定动态值,无奈操作批改)
    <my-com :title="item.title"></my-com> // 动静属性设置:数据(父组件数据更新会使子组件同步更新)
    </div>
    new Vue({
    ...
    data:{
      item:{title:"实力内容3"}
    },
    components:{
      "my-com":{
        props:["title"],
        template:`
          <div>
            <h3>{{ title }}</h3>
          </div>
        `
      }
    }
    })

    Props命名规定

  • 倡议prop命名应用camelCase,父组件绑定时应用kebab-case。
    为什么?
  • 子组件中,props内如果用kebab-case,如果prop作为属性应用不能加”-“,如果prop为”my-title”这种状况,应用时在插值内须要改成”{{ myTitle }}”解决
  • 父组件中,属性是在html中书写的,html的属性是不辨别大小写,因而camelCase会被辨认成camelcase,可能并不是咱们想要的camel-case 后果

子组件

Vue.component("my-com",{
  props:["myTitle"], // {myTitle:String} 写法也可
  template:`
    <div>
      <h3>{{ myTitle }}</h3> 
      <a :href="myTitle"></a> // 除了应用在插槽中,在绑定动静属性中也能够
    </div>
  `
})

父组件

<div id="app">
  <my-com my-title="实例内容1" ></my-com>
  <my-com :my-title="'实力内容2'"></my-com>
  <my-com :my-title="item.title"></my-com>
</div>

父传子的单向数据流

父子组件间的所有prop都是单向上行绑定的。意味着只能父向子传,不能反向影响(子影响父)

解释:

  • 父组件的数据批改会主动绑定到子组件中,并更新子组件,子组件的操作无奈反向影响父组件
  • 如果子组件要解决prop数据,该当存储在 data 或 computed 中后操作

    Vue.component("my-com",{
    props:['initialTitle'],
    template:'<h3> {{ myTitle }} </h3>',
    data(){
      return {
        myTitle:this.initialTitle // 把属性存下来,解决后放入插值中
      }
    }
    })
    <div id="app">
    <my-com :initial-title= "value"></my-com>
    </div>
    
    var vm = new Vue({
    data:{
      value:'北京欢送你',
    },
    }).$mount("#app")
  • 组件也是vue实例,无论实例内的 属性怎么批改, myTitle 数据怎么变,都不会对父的数据产生影响
  • 解决 props 数据形式, this.myTitle = "其余内容"
  • 间接批改 props 数据会产生正告 this.initialTitle = "其余内容" ,倡议用 data 或者 computed 代替间接批改 (我没呈现)

  • 留神,如果 prop 为数组或对象时,子组件操作将会影响到父组件的状态。(援用)
  • 解决办法

    • 存起来,拷贝到一个对象操作,

      obj_:Object.assign({},this.obj)
    • 对象不整体传入

      <div id="app">
      <p>{{ obj.name }}</p>  // 会受到影响
      <my-com :initial-obj= "obj"></my-com>
      </div>
      
      var vm = new Vue({
      data:{
      obj:{
        name:'mcgee', // 会受到影响 1
        age:18
      }
      },
      }).$mount("#app")
      Vue.component("my-com",{
      props:['initialObj'],
      template:`
      <div>
        <h3> {{ myObj.name }}:{{ myObj.age }}岁 </h3>
        <button @click="fn">按钮</button>
      </div>
      `,
      data(){
      return {
        myObj:this.initialObj
      }
      },
      methods:{
      fn(){
        this.initialObj.name = "Jack"  // 对象批改会影响父类 1 处的值
      }
      }
      })

子组件向父组件传值

  • 子向父传值须要通过自定义事件实现
  • 无奈通过 props 解决,通过自定义事件
  • 父传子,子操作后想要传回父会有个问题。子组件什么时候处理完毕,什么时候批改了数据,什么时候将数据传给父组件无奈确定,因而通过事件触发

案例

商品为子组件,购物车为父组件,父组件须要统计商品个数,就须要在子组件个数变动时传值给父组件。

var vm = new Vue({
  data:{
    products:[
      {id:1,title:"茄子"},
      {id:2,title:"辣椒"},
      {id:3,title:"西红柿"}
    ],
    totalCount:0
  },
}).$mount("#app")
<div id="app">
  <h3>购物车</h3>
  <product-item 
    v-for='item in products'
    :key="item.id"
    :title='item.title'
  ></product-item>

  <p>总数为{{ totalCount }}</p>
</div>
Vue.component('product-item',{
  props:['title'],
  template:`
    <div>
      <span>名称{{ title }},数量{{ count }}</span>
      <button @click="addCount">+1</button>
    </div>
  `,
  data(){
    return { count:0 }
  },
  methods:{
    countIns(){
      this.count++;
    }
  }
})
  • 子组件数据变动时,通过$emit()触发自定义事件。(实例的办法)
  • 自定义事件名称倡议应用 kebab-case, 在父组件中用@绑定驼峰或者帕斯卡,无奈辨认

    Vue.component('product-item',{
    ...
    methods:{
      countIns(){
        this.$emit('count-change') // 触发,在父组件中监听
        this.count++;
      }
    }
    })

    父组件

    <div id="app">
    <product-item 
      ...
      @count-change="totalCount++" // 事件监听,操作的时父的数据
    ></product-item>
    
    <p>总数为{{ totalCount }}</p>
    </div>

    自定义事件传值

    Vue.component('product-item',{
    ...
    methods:{
      countIns(){
        this.$emit('count-change',1) // 传参
        this.count++;
      },
      countIns5(){
        this.$emit('count-change',5)
        this.count+=5;
      }
    }
    })
  • 父组件在监听事件时须要接管子组件传递的数据。

    <div id="app">
    <product-item 
      ...
      @count-change="totalCount += $event"  // 在标签中接管参数
    ></product-item>
    
    <p>总数为{{ totalCount }}</p>
    </div>

    或者

    @count-change="onCountChange"
    
    new Vue({
    ...
    methods:{
      onCountChange(productCount){ // 在办法中接管参数
        this.totalCount += productCount
      } 
    }
    })

非父子组件传值

  • 非父子组件指的是兄弟组件或齐全无关的两个组件

内容概述

  • 兄弟组件传值
  • EventBus
  • 其余传值形式

兄弟组件传值

  • 兄弟组件能够通过父组件进行数据直达
  • 例如a,b子组件传值,能够通过a子组件传给父组件,再由父组件传给b子组件

    new Vue({
    data:{
      value:"" // 用来数据直达的根实例数据
    }
    })
    <div id="app">
    <com-a @value-change="value = $event" ></com-a> // 子a向父传递数据
    
    <com-b :value="value"></com-b> // 父向子b传数据
    </div>

    A组件

    Vue.components('ComA',{
    template:`
      组件A内容{{ value }}
      <button 
        @click="$emit('value-change',value)"
      >发送</button>
    `,
    data(){
      return { value: '实力内容' }
    }
    })

    B组件

    Vue.components('ComB',{
    props:['value']
    template:`
      组件B内容{{ value }}
    `
    })

    EventBus

    问题

  • 当组件嵌套关系简单时,依据组件关系传值会较为繁琐。
  • 组件为了数据直达,data中会存在许多与以后组件性能无关的数据。

解决

  • EventBus(事件总线)是一个独立的事件核心,用于治理不同组件间的传值操作。(邮递员,直达解决)
  • EventBus通过一个新的Vue实例来治理组件传值操作,组件通过给实例注册事件、调用事件来实现数据传递。

    // EventBus.js
    
    var bus = new Vue() // 不须要配置,只做事件传值操作
  • 发送数据的组件触发bus事件,接管的组件给bus 注册对应事件。

    <script src="EventBus.js"></script> // 引入js
    
    Vue.component('product-item',{
    ...
    methods:{
      countIns(){
        bus.$emit('count-change',1) // 用bus实例 代替 组件product-item实例
        this.count++;
      }
    }
    })
  • 给bus注册对应事件通过$on()操作。

    Vue.component('product-total',{
    template:`
      <p>{{ totalCount }}</p>
    `,
    data(){
      return { totalCount:0 }
    },
    created(){ // 实例创立实现后触发
      countIns(){
        bus.$on('countChange',(productCount)=>{
          this.totalCount+=productCount    // 留神下这里this,箭头函数
        })
      }
    }
    })

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理