父组件向子组件传值

  • 通过子组件的 props 选项接受父组件的传值
  • props内的数据可以在模板内直接使用
  • 注意:props不要与data 存在同名属性,会产生覆盖问题

子组件设置方式
Vue.component(‘my-com’,{ props:[‘title’], // 父类中要绑定的属性 template:’{{ title }}‘ })
父组件设置方式

  • 给自定义组件设置属性

    // 静态属性设置,无法操作修改 // 动态属性设置:表达式(一般不通过动态属性绑定静态值,无法操作修改) // 动态属性设置:数据(父组件数据更新会使子组件同步更新)
    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:’

    {{ myTitle }}

    ‘, data(){ return { myTitle:this.initialTitle // 把属性存下来,处理后放入插值中 } } })
    var vm = new Vue({ data:{ value:’北京欢迎你’, }, }).$mount(“#app”)
  • 组件也是vue实例,无论实例内的 属性怎么修改, myTitle 数据怎么变,都不会对父的数据产生影响
  • 处理 props 数据方式, this.myTitle = “其他内容”
  • 直接修改 props 数据会产生警告 this.initialTitle = “其他内容” ,建议用 data 或者 computed 代替直接修改 (我没出现)
  • 注意,如果 prop 为数组或对象时,子组件操作将会影响到父组件的状态。(引用)
  • 解决办法

    • 存起来,拷贝到一个对象操作,obj_:Object.assign({},this.obj)
    • 对象不整体传入

      {{ obj.name }}

      // 会受到影响
      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”)

购物车

总数为{{ totalCount }}


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++; } } })父组件

    总数为{{ totalCount }}

    Vue.component(‘product-item’,{ … methods:{ countIns(){ this.$emit(‘count-change’,1) // 传参 this.count++; }, countIns5(){ this.$emit(‘count-change’,5) this.count+=5; } } })

    自定义事件传值

  • 父组件在监听事件时需要接收子组件传递的数据。

    总数为{{ totalCount }}

    或者@count-change=”onCountChange” new Vue({ … methods:{ onCountChange(productCount){ // 在方法中接收参数 this.totalCount += productCount } } })

    非父子组件传值

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

内容概述

  • 兄弟组件传值
  • EventBus
  • 其他传值方式

    兄弟组件传值

  • 兄弟组件可以通过父组件进行数据中转

  • 例如a,b子组件传值,可以通过a子组件传给父组件,再由父组件传给b子组件new Vue({ data:{ value:”” // 用来数据中转的根实例数据 } })

    // 子a向父传递数据 // 父向子b传数据
    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 注册对应事件。 // 引入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,箭头函数 }) } } })