🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 组件基础 ### 什么是组件? 组件是可复用的 Vue 实例,且带有一个名字。 ### 基本示例 ~~~ // 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' }) ~~~ ~~~ <div id="components-demo"> <button-counter></button-counter> </div> new Vue({ el: '#components-demo' }) ~~~ ### 全局注册和局部注册 ~~~ Vue.component('name', {...}) ~~~ ~~~ var ComponentA = { /* ... */ } var ComponentB = { /* ... */ } var ComponentC = { /* ... */ } new Vue({ el: '#app', components: { 'component-a': ComponentA, 'component-b': ComponentB } }) ~~~ ### 命名方式 ~~~ //kebab-case (短横线分隔命名) Vue.component('my-component-name', { /* ... */ }) //PascalCase (驼峰式命名) Vue.component('MyComponentName', { /* ... */ }) ~~~ ### 组件的复用 ~~~ <div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div> ~~~ ### data 必须是一个函数 ~~~ data: { count: 0 } ~~~ 取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝: ~~~ data: function () { return { count: 0 } } ~~~ ### 通过 Prop 向子组件传递数据 ~~~ Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }) ~~~ ~~~ new Vue({ el: '#blog-post-demo', data: { posts: [ { id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } }) ~~~ ~~~ <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:title="post.title" ></blog-post> ~~~ ### 单个根元素 每个组件必须只有一个根元素 否则会报错 every component must have a single root element (每个组件必须只有一个根元素) ~~~ <h3>{{ title }}</h3> <div v-html="content"></div> ~~~ ~~~ <div class="blog-post"> <h3>{{ title }}</h3> <div v-html="content"></div> </div> ~~~ ### 通过事件向父级组件发送消息 组件外 ~~~ <blog-post v-on:enlarge-text="onEnlargeText"></blog-post> methods: { onEnlargeText: function (enlargeAmount) { this.postFontSize += enlargeAmount } } ~~~ 组件内部 ~~~ <button v-on:click="$emit('enlarge-text', 0.1)"> Enlarge text </button> ~~~ ### 在组件上使用 v-model ~~~ <input v-model="searchText"> ~~~ ~~~ <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" > ~~~ ~~~ <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input> ~~~ 为了让它正常工作,这个组件内的 input 必须: 将其 value 特性绑定到一个名叫 value 的 prop 上 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出 ~~~ Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` }) ~~~ ### 通过插槽分发内容 ~~~ <alert-box> Something bad happened. </alert-box> ~~~ ~~~ Vue.component('alert-box', { template: ` <div class="demo-alert-box"> <strong>Error!</strong> <slot></slot> </div> ` }) ~~~ ### 动态组件 ~~~ <!-- 组件会在 `currentTabComponent` 改变时改变 --> <component v-bind:is="currentTabComponent"></component> ~~~ ### 课后习题 1.设计一个组件,实现一个通过传入的秒数进行倒计时的效果,并通过插槽的方式,为定时器显示的数字后面带上一段描述的话! ~~~ <cutdown timer="14">秒后开始抢购</cutdown> // 效果 <div>14秒后开始抢购<div> <div>13秒后开始抢购<div> . . . ~~~