一、什么是组件
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。
二、组件类型
1、全局组件
<div id="app"> <runoob></runoob> </div> <script> // 注册 Vue.component('runoob', { template: '<h1>自定义组件!</h1>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
2、局部组件(这样组件只能在这个实例中使用)
<div id="app"> <runoob></runoob> </div> <script> var Child = { template: '<h1>自定义组件!</h1>' } // 创建根实例 new Vue({ el: '#app', components: { // <runoob> 将只在父模板可用 'runoob': Child } }) </script>
组件也可以放在 component 文件夹下,然后进行引入
import component-a from './components/component-a' new Vue({ el: '#app', components: {component-a} })
三、父子组件间的数据传输
1、prop
prop 是父组件用来传递数据的一个自定义属性。父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop"。prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
<div id="app"> <child message="hello!"></child> </div> <script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件。
<div id="app"> <div> <input v-model="parentMsg"> <br> <child v-bind:message="parentMsg"></child> </div> </div> <script> // 注册 Vue.component('child', { // 声明 props props: ['message'], template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app', data: { parentMsg: '父组件内容' } }) </script>
(以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中)
<div id="app"> <ol> <todo-item v-for="item in sites" v-bind:todo="item"></todo-item> </ol> </div> <script> Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) new Vue({ el: '#app', data: { sites: [ { text: 'Runoob' }, { text: 'Google' }, { text: 'Taobao' } ] } }) </script>
2、自定义事件
子组件要把数据传递回去,就需要使用自定义事件。我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
- 使用 $on(eventName) 监听事件
- 使用 $emit(eventName) 触发事件
<div id="app"> <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> </div> <script> Vue.component('button-counter', { template: '<button v-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>