第四章Vue.js 的组件
1.基本概念
1.1组件是一个可复用的Vue实例,需要挂载到Vue的实例
1.2组件除了el选项外,同样包括有data、computed、watch、methods 以及生命周期钩子等。
2定义组件
<div id="app">
<button-counter></button-counter>
</div>
<script>
var compoent1 = {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">点击了{{ count }} 次.</button>'
}
Vue.component("button-counter", compoent1);
var vm = new Vue({
el: "#app"
});
</script>
2.1组件的data和Vue实例有区别
2.1.1组件通过一个函数返回一个对象
2.1.2Vue实例是对象
2.2el的区别
2.2.1组件没有el选项
2.2.2Vue实例有el选项
2.3html元素
2.3.1组件的html元素定义在template属性上
2.3.2Vue实例通过el指定挂载的位置
3注册组件到Vue实例
3.1全局注册
<div id="app">
<button-counter></button-counter>
</div>
<script>
var compoent1 = {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">点击了{{ count }} 次.</button>'
}
Vue.component("button-counter", compoent1);
var vm = new Vue({
el: "#app"
});
</script>
3.1.1.1通过组件名称应用组件 <button-counter></button-counter>
3.1.1.2每个组件都是独立的,互不影响。这样组件都可以重用了,维护起来会非常方便。
3.2组件名要求
3.2.1kebab-case 短横线隔开
例如:my-component-name
使用的时候 <my-component-name></my-component-name>
3.2.2PascalCase 帕斯卡命名|大驼峰|
例如:MyComponentName
使用 <my-component-name>(推荐)
使用 <MyComponentName>(错误)
总结:组件名称最好全部采用小写,因为html标签始终都是小写的。只有html的名称与组件一致才匹配。另外一种方式组件名采用大驼峰命名,表签名每个单词用短横杠分隔。推荐组名名小写,因为html的标签名始终都是小写方式渲染的,这样就可以避免不必要的麻烦
3.3局部注册 定义在components上
<script>
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
</script>
3.3.1属性名就是自定义元素的名字,属性值就是这个组件的选项对象。
3.3.2注意:局部注册的组件在其子组件中不可用。
3.3.3在子组件中注册其它的组件
<script>
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
</script>
4.props-父组件先子组件传递数据
4.1props 数组。
<div id="app">
<course-item coursename="善良的死神"></course-item>
</div>
<script>
var courseListComponent = {
props: ['coursename'],
template: '<p>{{ coursename }}</p>'
}
var vm = new Vue({
el: "#app",
components: {
'course-item': courseListComponent
}
});
</script>
注意:coursename="善良的死神" 和 coursename="1" 传递的是字符串类型,而不是数字。如果非要传递数字采用绑定的方式传递,例如::coursename="1" ,因为v-bind的表达式是js表达式,所以1会当作数字看待
4.2props 对象。
<div>
<compoent :number="18"></compoent>
</div>
<script>
// 对象语法,提供校验
Vue.component('props-demo-advanced', {
props: {
// 检测类型
height: Number,
// 检测类型 + 其他验证
age: {
type: Number,//数据类型
default: 0,//默认值
required: true,//required是否必须
validator: function (value) {//validator 校验器
return value >= 18
}
}
}
})
</script>
4.3注意命名
4.3.1全部小写 节点上的名称与属性的名一致
<div id="app">
<course-item coursename="善良的死神"></course-item>
</div>
<script>
var courseListComponent = {
props: ['coursename'],
template: '<p>{{ coursename }}</p>'
}
var vm = new Vue({
el: "#app",
components: {
'course-item': courseListComponent
}
});
</script>
4.3.2小驼峰命名 节点上要使用短横线隔开
<div id="app">
<course-item course-name="善良的死神"></course-item>
</div>
<script>
var courseListComponent = {
props: ['courseName'], // course-name大小写没有关系或者course-Name也可以
template: '<p>{{ courseName }}</p>'
}
var vm = new Vue({
el: "#app",
components: {
'course-item': courseListComponent
}
});
</script>
5.通过自定义事件向父级组件发送消息
5.1在vue.js中,可以使用$emit自定义事件
语法 $emit("事件名","事件传递的数据")
<div id="app">
<stu-content @left-length="leftNumber=$event"></stu-content>//在事件处理上,使用$event获取返回来的值
<p>剩余字数{{leftNumber}}</p>
</div>
<script>
var component1 = {
data: function () {
return {
content: '',
maxLength: 50,
}
},
template: '<textarea v-model="content" ></textarea>',//是父组件上使用v-model绑定事件
watch: {
content: function (newValue, oldValue) {
var len = newValue.length;
var leftLength = this.maxLength - len;
this.$emit("left-length", leftLength);
}
}
}
var vm = new Vue({
el: "#app",
data: {
leftNumber: 50,
},
components: {
'stu-content': component1
}
});
//事件名称自定义,最好采用短横线,例如:left-input
</script>
5.2使用v-model
<div id="app">
<stu-content v-model="leftNumber"></stu-content>//使用v-model接收事件处理的结果。
<p>剩余字数{{leftNumber}}</p>
</div>
<script>
var component1 = {
data: function () {
return {
content: '',
maxLength: 50,
}
},
template: '<textarea v-model="content" ></textarea>',
watch: {
content: function (newValue, oldValue) {
var len = newValue.length;
var leftLength = this.maxLength - len;
this.$emit("input", leftLength);//修改事件名称为input
}
}
}
var vm = new Vue({
el: "#app",
data: {
leftNumber: 50,
},
components: {
'stu-content': component1
}
});
</script>
v-model实际上是 @input="value=$event" 操作的语法糖。由此可见只需要在子组件的事件名定义为input即可
6.通过插槽分发内容
6.1期望组件之间的内容传入到组件里,如何做?
<div id="app">
<stu-content v-model="leftNumber">500</stu-content>//使用<slot>获取组件之间的内容
<p>剩余字数{{leftNumber}}</p>
</div>
<script>
var component1 = {
data: function () {
return {
content: '',
maxLength: 50,
}
},
template: '<div><textarea v-model="content" ></textarea><p>限输入<slot></slot>字</P></div>',
watch: {
content: function (newValue, oldValue) {
var len = newValue.length;
var leftLength = this.maxLength - len;
this.$emit("input", leftLength);
}
}
}
var vm = new Vue({
el: "#app",
data: {
leftNumber: 50,
},
components: {
'stu-content': component1
}
});
</script>
6.2具名插槽
<div id="app">
<slot-commponent>hello vue.js</slot-commponent>
</div>
<script>
var component1 = {
template: '<div><p>默认插槽的内容来自,标签之间的内容</P><slot></slot></div>'
}
var vm = new Vue({
el: "#app",
components: {
'slot-commponent': component,
}
});
</script>