组件组合

2 篇文章 0 订阅

构造Vue实例时传入的各种选项大多数都可以在组件里使用。只有一个例外:data必须是函数。实际上如果你这么做:

Vue.component('my-component', {
  template: '<span>{{ message }}</span>',
  data: {
    message: 'hello'
  }
})

那么vue会停止运行,并在控制台发出警告,告诉你在组件实例中data必须是一个函数,

data: function () {
  return {
    counter: 0
  }
}

<div id="example-2">
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
  <simple-counter></simple-counter>
</div>
var data = { counter: 0 }

Vue.component('simple-counter', {
  template: '<button v-on:click="counter += 1">{{ counter }}</button>',
  // 技术上 data 的确是一个函数了,因此 Vue 不会警告,
  // 但是我们却给每个组件实例返回了同一个对象的引用
  data: function () {
    return data
  }
})

new Vue({
  el: '#example-2'
})

由于这三个组件实例共享了同一个 data 对象,因此递增一个 counter 会影响所有组件!这就错了。我们可以通过为每个组件返回全新的数据对象来修复这个问题:

现在每个counter都有自己内部的状态了。

#组件组合

组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。然而,通过一个良好定义的接口来尽可能将父子组件解耦也是很重要的。这保证了每个组件的代码可以在相对隔离的环境中书写和理解,从而提高了其可维护性和复用性。

在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的。

prop

#使用Prop传递数据

组件实例的作用域是孤立的。这意味着不能(也不应该)在子组件的模板里引用父组件的数据,父组件的数据需要通过prop才能下发到子组件中。

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

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

然后我们可以这样向它传入一个普通字符串:

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

#camelCase vs.kebab-case

Html的特性是不区分大小写的,如果使用的不是字符串模板,需要把prop里的camelCase(驼峰式命名)转换为(kebab-case)短杠形式。

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

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

#动态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>
将等价于:

<todo-item
  v-bind:text="todo.text"
  v-bind:is-complete="todo.isComplete"
></todo-item>

#字面量语法vs动态语法

初学者常范的错误是字面量语法传递数值

<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp>

因为它是一个字面量 prop,它的值是字符串 "1" 而不是一个数值。如果想传递一个真正的 JavaScript 数值,则需要使用 v-bind,从而让它的值被当作 JavaScript 表达式计算:

<!-- 传递真正的数值 -->
<comp v-bind:some-prop="1"></comp>




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值