第二节、组件构建方法(主要是针对公用组件)

讲组件的构建之前我们现在看下组件之间的数据传递,我们先来看一下组件组合的关系。

组件最常见的就是父子组件(例如在A组件中使用了B组件)。先看一张图


这张图反映了父子组件传递数据的关系,简单来说有两个方面:

  • 父组件向子组件下发数据,子组件向父组件传递事件
  • 上面一句话是重点,也是我们组件之间传递数据的核心,父组件通过prop向下传递数据给子组件,子组件通过事件向上给父组件发送消息
看到上面,有些人可能会有疑问,组件之间的数据传递来回互相直接传递引用不就行了吗。但实际上并非如此,这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。子组件要想传递数据给父组件,只能通过事件来发送消息给父组件,父组件在接收到数据后再把数据赋到父组件的数据对象中。


父组件向子组件传递数据

1、使用 Prop 传递数据

组件实例的作用域时孤立的。这意味着不能再子组件内直接引用父组件的数据,父组件的数据需要通过 prop 才能下发到子组件中。

子组件要显式地用 props 选项声明它预期的数据:

Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 就像 data 一样,prop 也可以在模板中使用
  template: '<span>{{ message }}</span>'
})

然后我们在其他组件中使用该组件时,传入参数的方法,就是定义该组件标签 <child> 的属性。

<child message="hello!"></child>

HTML 特性是不区分大小写的。所以,当使用的不是字符串模板时,camelCase (驼峰式命名) 的 prop 需要转换为相对应的 kebab-case (短横线分隔式命名):

Vue.component('child', {
  // 在 JavaScript 中使用 camelCase
  props: ['myMessage'],
  template: '<span>{{ myMessage }}</span>'
})
<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child>

如果你使用字符串模板,则没有这些限制。

2、动态 Prop 

与绑定到任何普通的 HTML 特性相类似,我们可以用 v-bind 来动态地将 prop 绑定到父组件的数据。每当父组件的数据变化时,该变化也会传导给子组件

<div id="prop-example-2">
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>
new Vue({
  el: '#prop-example-2',
  data: {
    parentMsg: 'Message from parent'
  }
})

你也可以使用 v-bind 的缩写语法:

<child :my-message="parentMsg"></child>

如果你想把一个对象的所有属性作为 prop 进行传递,可以使用不带任何参数的 v-bind (即用 v-bind 而不是 v-bind:prop-name)。例如,已知一个 todo 对象:

todo: {
  text: 'Learn Vue',
  isComplete: false
}

然后:

<todo-item v-bind="todo"></todo-item>


子组件向父组件传递数据

这种方法是基于父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName, optionalPayload) 触发事件

下面是一个例子:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
  template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    incrementCounter: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})

new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

相信看到上面的代码,有人已经发现了,在子组件中为了触发父组件的监听事件,会使用 $emit (' 父组件监听的事件名 ' , ' 需要传递的参数 ') 来触发父组件的监听。

这就是构建公用组件的核心内容,也是最基础的用法,更高级的用法可以 访问官网


如果你使用字符串模板,则没有这些限制。 如果你使用字符串模板,则没有这些限制


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值