vue.js入门之第四篇(自定义组件)
2018-08-17 本文已影响0人
平安喜乐698
目录
除了可以使用普通html元素外,Vue还允许自定义组件(可以使用指令)
组件是可复用的 Vue 实例,每用一次组件就会有一个它的新实例被创建。
只能有一个跟元素
复用则data必须是个函数
data: function () {
return {
count: 0
}
}
1、自定义全局组件
<div id="app">
<!--2、使用全局组件-->
<hello-world></hello-world>
</div>
<script>
// 1、注册全局组件,可在本页中使用
// 第一参数:组件名
// 第一种命名方式:全小写 加 连字符-(建议),使用<hello-world>
// 第二种命名方式:HelloWorld,使用<hello-world>或<HelloWorld>
Vue.component('hello-world', {
template: '<h1>自定义组件!</h1>'
})
// 创建根实例
new Vue({
el: '#app'
})
</script>
2、自定义局部组件
<div id="app">
<!--2、使用局部组件-->
<hello></hello >
</div>
<script>
var Child = {
template: '<h1>自定义组件!</h1>'
}
// 创建根实例
new Vue({
el: '#app',
// 1、注册局部组件(仅在id为app中使用)
components: {
'hello': Child
}
})
</script>
- 传递数据 [属性]
<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>
- 传递数据(绑定属性)
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<child v-bind:message="parentMsg"></child>
</div>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容'
}
})
</script>
- 传递数据(循环)
<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>
- is
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部。
这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:
<table>
<customRow></customRow>
</table>
这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。
注意:三种情况不存在这个限制:字符串、单文件组件.vue、<script type="text/x-template">
解决
<table>
<tr is="customRow"></tr>
</table>
- v-model
<input v-model="searchText">
等价于:
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
<custom-input v-model="searchText"></custom-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>
'
})
属性
1、html大小写不敏感,Vue中的驼峰属性名在html中要使用连字符-。{{}}不受限制
<blog-post post-title="hello!"></blog-post>
Vue.component('blog-post', {
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
2、属性类型type可以是:String、Number、Boolean、Function、Object、Array、Date、Symbol、一个自定义的构造函数
当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告
prop 会在一个组件实例创建之前进行验证,所以实例的属性 (如 data、computed 等) 在 default 或 validator 函数中是不可用的
Vue.component('example', {
props: {
// 基础类型检测 (`null` 意思是任何类型都可以)
propA: Number,
// 多种类型
propB: [String, Number],
// 必传且是字符串
propC: {
type: String,
required: true
},
// 数字,有默认值
propD: {
type: Number,
default: 100
},
// 数组/对象的默认值应当由一个工厂函数返回
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
}
}
})
3、传值(静态、动态)
<blog-post title="My journey with Vue"></blog-post>
<!-- 动态赋予一个变量的值 -->
<!-- 或者告诉Vue这不是个字符串而是表达式,如传递数值、Boolean、数组、对象-->
<blog-post v-bind:title="post"></blog-post>
<!-- 传入post对象的所有属性 -->
<blog-post v-bind="post"></blog-post>
4、组件可以接受任意特性
因为组件并不总能预见组件会被用于怎样的场景。
这些特性会被添加到这个组件的根元素上。
<blog-post title="My journey with Vue"></blog-post>
title会被加在根元素上
5、对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值,即覆盖。class 和 style 则会合并。
6、禁用根元素的继承继承特性
注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。
Vue.component('my-component', {
inheritAttrs: false,
props: ['label', 'value'],
// ...
})
label、value不再从<my-component value=''>中获取
$attrs 属性包含了传递给一个组件的特性名和特性值
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
方法(自定义事件)
事件名不存在任何自动化的大小写转换,
v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。推荐使用全小写加连字符-
使用 $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 () { // data 必须是一个函数
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
// this.$emit('increment',1) 带参数 ,在function (count)可获取 或 html 元素中 $event可获取
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
</script>