组件(Component)是前端在单页面应用(SPA)上最好的一种实现方式,把全部功能模块拆解成单独的组件,每一个组件都有独立的做用域,且还能够相互通讯javascript
在传统的页面之间跳转,是经过刷新,从新渲染一个页面而实现,在渲染的过程当中势必要加载外部资源文件,页面在服务器中渲染出来是经过一系列的生命周期,在这个过程当中会由于网速等硬件问题直接影响页面的加载速度,为解决这一问题,前端在新的设计模式上引入了组件的概念,页面之间的跳转变成了组件之间的切换,不须要从新加载整个页面,也不用考虑页面的生命周期,换成组件的生命周期,在性能上大大的提高了。html
<div id="app"> <!--组件的使用--> <global-component></global-component> </div>
//组件的定义 Vue.component(组件名称, {template}) Vue.component('global-component', { template: '<h1>全局组件</h1>' }) var vm = new Vue({ el: '#app' })
最终渲染的效果前端
<div id="app"> <h1>全局组件</h1> </div>
<div id="app"> <!--组件的使用--> <private-component></private-component> </div>
//组件的定义 Vue.component(组件名称, {template}) var vm = new Vue({ el: '#app', components:{ 'private-component': { template: '<h1>局部组件</h1>' } } })
最终渲染的效果vue
<div id="app"> <h1>局部组件</h1> </div>
每一个组件都有单独的做用域java
<div id="app"> <p>{{count}}</p> <component1/> </div>
var vm = new Vue({ el: '#app', data: { count: 10 }, methods: { increment: function(){ this.count += 1; } }, components:{ 'component1': { template: '<button v-on:click="increment">{{ count }}</button>', data: function(){ //在组件里面 data 必定是 function 并返回一个对象 return { count: 0 } }, methods: { increment: function(){ this.count += 1; } } } } })
渲染结果为git
<div id="app"> <p>10</p> <!-- 此按钮每次点击都会自增 1,而 p 标签永远都是为 10 缘由为组件的做用域是单独的 --> <button>0</button> </div>
效果预览github
好比在下拉列表(select)元素里面,子元素必须为 option,则在使用组件的时候用 is设计模式
<div id="app"> <select> <option is="privateOption"></option> </select> </div>
var vm = new Vue({ el: '#app', components: { 'privateOption': { template: '<option value=1>1</otpion>' } } })
渲染结果服务器
<div id="app"> <select> <option value="1">1</option> </select> </div>
<div id="app" style="display: none;"> <input type="button" value="changeLight" @click="changeLight" /> <br/> <p :is="show"></p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { show: 'red', }, methods:{ changeLight: function(){ this.show = this.show == 'red' ? 'green' : 'red'; } }, components: { red: { template: '<h1>Red</h1>' }, green: { template: '<h1>Green</h1>' } } }) </script>
组件的属性要先声明后使用,props: ['属性名'...]app
<div id="app"> <!--组件的使用--> <private-component title="组件属性" :text="mess"></private-component> </div>
//组件的定义 Vue.component(组件名称, {template}) var vm = new Vue({ el: '#app', data: { mess: '-动态属性' } components:{ 'private-component': { template: '<h1>{{title + text}}</h1>', props: ['title', 'text'] } } })
最终渲染的效果
<div id="app"> <h1>组件属性-动态属性</h1> </div>
和组件属性不同的在于 <组件名 v-bind:属性名="">,属性名要在组件中先声明再使用:props: ['属性名']
自定义事件:<组件名 v-on:自定义事件名="">,自定义事件名不须要声明,直接用 $emit() 触发
<div id="app"> <p>{{total}}</p> <increment-total v-on:count="incrementTotal"></increment-total> </div>
var vm = new Vue({ el: '#app', data: { total: 0 }, methods: { incrementTotal: function(){ this.total += 1; } }, components: { 'incrementTotal': { template: '<input type="button" @click="incrementTotal" value="Total" />', data: function(){ return { total: 0 } }, methods: { incrementTotal: function(){ this.total += 1; this.$emit('count') } } } } })
Vue 组件默认是覆盖渲染,为了解决这一问题,Vue 提出了 slot 分发内容
<div id="app"> <component1> <h1>Sam</h1> <h1>Lucy</h1> </component1> </div>
Vue.component('component1', { template: ` <div> <h1>Tom</h1> <slot></slot> </div> ` })
最终渲染的效果
<div id="app"> <component1> <h1>Tom</h1> <!-- 若是在组件定义的 template 当中没有 <slot></slot>,那么下面两个 h1 标签将不会存在 换句话说就是 <slot></slot> = <h1>Sam</h1><h1>Lucy</h1> <slot></slot>能够放到 <h1>Tom</h1> 上面进行位置调换 --> <h1>Sam</h1> <h1>Lucy</h1> </component1> </div>
若是要将组件里面不一样的子元素放到不一样的地方,那就为子元素加上一个属性 slot="名称",而后在组件定义的时候用名称对应位置 <slot name="名称"></slot>,其它没有 slot 属性的子元素将统一分发到 <slot></slot> 里面
<div id="app"> <component1> <h1>Sam</h1> <h1 slot="lucy">Lucy</h1> </component1> </div>
Vue.component('component1', { template: ` <div> <slot name="lucy"></slot> <h1>Tom</h1> <slot></slot> </div> ` })
最终渲染的效果
<div id="app"> <component1> <!--<slot name="lucy"></slot> = <h1 slot="lucy">Lucy</h1>--> <h1>Lucy</h1> <h1>Tom</h1> <!--其它没有 slot 属性的子元素将所有分发到 <slot></slot> 标签--> <h1>Sam</h1> </component1> </div>
<template id="component1"> <div> <input type="text" v-model="name"/> <p>{{name}}</p> </div> </template> <div id="app"> <component1/> </div>
var vm = new Vue({ el: '#app', components: { 'component1': { template: '#component1', data: function(){ return {name: 'Tom'}; } } } })