1 组件
-
使用组件
(1) 注册
注册一个全局组件,可使用
Vue.component(tagName, options)
Vue.component("my-component", { //options })
(2) 创建实例
new Vue({ el:'#example' })
(3) 使用
<div id="example"> <my-component></my-component> </div>
-
局部注册
不在全局注册组件,使组件仅在一个实例/组件的作用域中可用
var Child = { template:'<div>A custom component!</div>' } new Vue({ el: '#test', //组件仅在id为test的元素内可用 components: { 'my-component': Child } })
-
DOM模板解析说明
(1) 使用DOM模板,如将
el
挂载到已存在的元素上,将受到HTML的限制:<ul>
,<ol>
,<table>
,<select>
限制了能被它包裹的元素,<option>
只能出现在其它元素内部<table> <my-row>...</my-row> </table>
<table>
元素不接受<my-row>
,故其被认为是无效内容(2) 解决方法,使用
is
属性<table> <tr is="my-row">...</tr> </table>
(3) 使用字符串模板,将不受此限制,如
.vue
组件 -
Vue组件中,
data
必须是函数若data为数据对象,则多个组件共享同一个
data
-
构成组件
(1) 良好定义的接口中,应尽可能将父子组件解耦,保证每个组件在相对隔离的环境中书写和理解
(2) props down, event up. 父组件通过props向子组件传递数据,子组件通过events给父组件发送消息
-
props
(1) 使用props传递数据
-
组件实例的作用域是孤立的,不能在子组件的模板内直接引用父组件的数据,可使用props把数据传给子组件
-
子组件需要显式地使用
props
声明prop
<child message="hello"></child> <script> Vue.component('child',{ props:['message'], template:'<span>{{message}}</span>' }) </script>
(2) camelCase与kebab-case
使用非字符串模板时,prop的名字形式,在模板定义中应使用camelCase,在html应用时应使用kebab-case
<child my-message="hello!"></child> <script> Vue.component('child', { props: ['myMessage'], template: '<span>{{myMessage}}</span>' }) </script>
(3) 动态Props
<input v-model="parentMsg"> <child :my-message="parentMsg"></child> <script> Vue.component('child',{ props: ['parentMsg'], templates:'<span>{{parentMsg}}</span>' }) </script>
(4) 字面量语法与动态语法
<comp some-prop="1"></comp> <!--字面量语法,传递字符串"1"--> <comp :some-prop="1"></comp> <!--动态语法,传递数字-->
-
-
props验证
(1) 组件可以为props指定验证要求,即在数据后加上
:type
Vue.component('example', { props: { propA: Number, propB: [String, Number], propC: { type: String, required: true }, propD: { type: Object, default: function() { return {message: 'hello'} } } } })
type
可以为String、Number、Boolean、Function、Object、Array(2) prop验证失败,Vue将拒绝在子组件上设置值
-
自定义事件
(1) 子组件通过自定义事件向父组件传递数据
(2) 使用
v-on
绑定自定义事件<button-counter @increment="incrementTotal"></button-counter> <script> Vue.component('button-counter',{ methods: { increment: function() { this.counter += 1 this.$emit('increment') } } }) new Vue({ methods: { incrementTotal: function () { this.total += 1 } } }) </script>
(3) 在组件上监听原生事件,加上
.native
修饰符<my-component @click.native="doTheThing"></my-component>
-
使用Slots分发内容
(1)
app-layout
子组件模板<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>
(2) 父组件模板
<app-layout> <h1 slot="header">Here might be a page title</h1> <p>A paragraph for the main content.</p> <p>And another one.</p> <p slot="footer">Here's some contact info</p> </app-layout>
(3) 渲染结果
<div class="container"> <header> <h1>Here might be a page title</h1> </header> <main> <p>A paragraph for the main content.</p> <p>And another one.</p> </main> <footer> <p>Here's some contact info</p> </footer> </div>
-
动态组件
多个组件使用同一个挂载点,使用保留的
<component>
元素,绑定至其is
特性<component :is="currentView"> </component> <script> var vm = new Vue({ //... data: { currentVies: 'home' }, component: { home: {}, posts: {}, archive: {} } }) </script>
-
编写可复用组件规范
(1) Props允许外部环境传递数据给组件
(2) Events允许组件触发外部环境的副作用
(3) Slots允许外部环境将额外的内容组合在组合中
(4) 使用
v-bind
和v-on
的简写形式
2 单文件组件
-
使用
Vue.component
定义全局组件的弊端(1) 全局定义(Global definitions)强制要求每个component中的命名不得重复
(2) 不支持CSS
(3) 字符串模板缺乏语法高亮
-
单文件组件
扩展名为
.vue
的单文件组件(single-file components)解决了以上问题