Vue知识点总结三
组件化开发
步骤
- 创建组件构造器对象
- 注册组件
- 使用组件
下面用一个例子演示开发一个自定义组件的过程:
<body>
<!-- 3.使用组件 -->
<div id="app">
<mycpn></mycpn>
</div>
<script src="../js/vue.js"></script>
<script>
//1.创建组件构造器对象
const cpnCreater = Vue.extend({
template: `
<div>
<h2>标题</h2>
<p>段落1</p>
<p>段落2</p>
</div>`
})
//2.注册组件
Vue.component('mycpn', cpnCreater)
const app = new Vue({
el: '#app',
data: {
message: 'hello, vuejs'
}
})
</script>
</body>
全局组件和局部组件
通过Vue.component('mycpn', cpnCreater)
注册的组件是全局组件,可以在多个Vue实例下使用
还有一种注册方式是在Vue实例中注册:
const app = new Vue({
el: '#app',
data: {
message: 'hello, vuejs'
},
components: {
//局部注册法
cpn: cpnCreater
}
})
这种注册方法使得cpn只可以在挂载了"app"的标签下使用。
父子组件
组件构造器对象中可以通过components
属性注册另一个组件构造器对象使之成为自己的 子组件,例子如下:
// 子组件
const cpnCter1 = Vue.extend({
template: `
<div>
<h2>输入</h2>
<input type="text" />
</div>
`
})
// 父组件
const cpnCter2 = Vue.extend({
template: `
<div>
<h2>标题</h2>
<p>内容</p>
<cpn1></cpn1>
</div>
`,
components: {
//在一个组件中注册另一个组件
cpn1: cpnCter1
}
})
组件注册的语法糖
可以用Vue.extend({})
中的对象来代替组件构造器对象放到注册组件的地方使得创建和注册写在一起。
Vue.component('cpn1', {
template: `
<div>
<h2>输入</h2>
<input type="text" />
</div>
`
})
const app = new Vue({
el: '#app',
data: {
message: 'hello, plmm'
},
components: {
cpn2: {
template: `
<div>
<h2>标题</h2>
<p>内容</p>
<cpn1></cpn1>
</div>
`
}
}
})
组件的模板抽离写法
当template
中的代码过多时写在注册器中不利于代码的阅读与维护,于是引出了模板抽离的写法——将template
的内容拿出来。
两种写法:
- 使用
<script type="text/x-template"></script>
标签
在标签通过id来标识属于哪个组件,使用Vue.component()
注册时只需要在template
中填写id中的标识即可,与Vue实例挂载同理。在注册组件的时候也可以像Vue实例中一样定义数据成员、函数等内容。
<script type="text/x-template" id="cpn1">
<div>
<h2>{{title}}</h2>
<p>{{content}}</p>
</div>
</script>
<script>
Vue.component('cpn1', {
template: "#cpn1",
data() {
return {
title: '我挥动翅膀',
content: '天空中孤单的飞鸟,墙壁上昏暗的夕阳,让我柔软的心,掠过一丝暗影,你站在朝西的阳台,任寂寞随黑夜袭来,那曾经闪亮的心啊,为等待已慢慢变淡'
}
}
})
</script>
- 使用
<template></template>
标签
使用<template></template>
标签与上面只有标签的差异,其它的基本一致。
<template id="cpn2">
<div>
<h2>{{label}}</h2>
<input type="text" />
</div>
</template>
<script>
Vue.component('cpn2', {
template: '#cpn2',
data() {
return {
label: '用户名'
}
}
})
</script>
组件通信
父组件数据传给子组件
在子组件通过props
属性定义属性对象,属性对象中有type
、default
等属性用来约束此对象。在父组件中调用子组件时可以使用v-bind语法将子组件定义的属性和父组件中的变量绑定,实现父组件数据注入子组件。
<body>
<div id="app">
<!-- 父传子 -->
<cpn :cat_movies="movies"
:cat_message="message">
</cpn>
</div>
<template id="cpn">
<div>
{{notice}}
<ul v-for="movie in cat_movies">
<li>{{movie}}</li>
</ul>
<h2>{{cat_message}}</h2>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'hello, vuejs',
movies: ['盗梦空间', '假如爱有天意', '初恋这件小事', '致命魔术']
},
components: {
cpn: {
template: '#cpn',
props: {
//cat_movies: Array,
cat_movies: {
type: Array,
default() {
return []
}
},
cat_message: {
type: String,
default: 'no message'
}
}
}
}
})
</script>
</body>
子组件传给父组件
子组件向父组件传递消息通过事件派发实现,子组件派发事件,父组件监听事件并从参数列表中获得子组件传递的消息。
<body>
<div id="app">
<cpn @itemclick="cpnClick"/>
</div>
<template id="cpn">
<!-- click事件演示子传父通信,通过发射事件,接收事件实现通信 -->
<button v-for="item in categories"
@click="itemClick(item)">
{{item.name}}
</button>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
components: {
cpn: {
template: '#cpn',
data() {
return {
notice: '电影',
categories: [
{id: 'a', name: '热门推荐'},
{id: 'b', name: '手机数码'},
{id: 'c', name: '家用电器'},
{id: 'd', name: '电脑办公'}
]
}
},
methods: {
itemClick(item) {
//发射一个事件给父组件,将点击的id传给父组件
this.$emit('itemclick', item.id)
}
}
}
},
methods: {
cpnClick(id) {
console.log(id)
}
}
})
</script>
</body>
上面这个例子子组件将电影名字的id传递给父组件,并在父组件中通过控制台打印。
父组件获取子组件的两种方式
$children
父组件对象调用this.$children
即可获得子组件数组,通过下标可以访问到任意一个子组件。$refs
可以为子组件添加refs属性如<cpn ref="a2"></cpn>
使得在父组件对象中直接通过`this.$resfs.a2的形式获取子组件。
插槽
- 基本使用
在子组件使用<slot></slot/>
标签当作一个预留位置,然后在父组件中使用子组件时可以在子组件标签中插入想要添加的其它标签。 - 具名插槽
子组件中使用<slot></slot>
组件时可以给一个name属性值,然后在父组件中使用子组件并插入标签时可以通过slot=""
""中填写name属性值指定替换哪个插槽。 - 作用域插槽
参考这里