1. 组件
组件:component
举个例子:我们登录管理系统的后台,发现有左侧的菜单栏、头部的管理员信息、中间的数据信息、底部的友情链接等,我们可以把这些不同的页面布局看成一个个的组件,然后像拼积木一样把他们拼起来,这些组件就构成了一个完整的页面,如下图所示:
组件的作用:
- 减少 vue 实例中的代码量
- 组件可以重复使用:
"代码共享"
- 便于开发人员进行维护
2. 全局注册
全局注册完,任何 vue 实例都可以使用该组件。
2.1 全局注册语法:
Vue.component('login',{
template:'<div><span>这是登录组件</span></div>'
});
- 参数一:组件的名称
- 参数二:组件的配置,template 中用来写 html 代码
2.2 使用组件:
<login></login>
- 如果组件名是以驼峰形式命名,则在使用的时候组件名必须是“小写单词-小写单词”,例如:
<div id="app">
<!-- 2.组件使用 -->
<new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1.注册全局组件
Vue.component('newComponent', {
template: '<div> 这瓜保熟吗? </div>'
})
const app = new Vue({
el: '#app'
})
</script>
运行结果:
3. 局部注册
注册的组件只能在当前 vue 实例中使用。
-
- 先定义组件
-
- 必须在 vue 实例中注册组件
-
- 使用组件
3.1 第一种注册方式
<div id="app">
<!-- 3. 使用组件,注:组件可以重复使用 -->
<new-component></new-component>
<new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1. 定义局部组件
var newComponent = {
template: '<div>我是个局部组件,只能在当前vue实例中使用!</div>'
}
const app = new Vue({
el: "#app",
// 2. 在 vue 实例中注册组件,切记只有在这里注册过后才能使用
components: {
'newComponent': newComponent
}
})
</script>
运行结果:
3.2 第二种注册方式
将 template 中的 html 代码单独剥离出来放到 template 标签里面。
<div id="app">
<!-- 4. 使用组件,注:组件可以重复使用 -->
<new-component></new-component>
<new-component></new-component>
</div>
// 1. 声明局部组件模板
<template id="newTemplate">
<div>我是个局部组件,只能在当前vue实例中使用!</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 2. 定义变量保存模板对象
var newComponent = {
template: '#newTemplate'
}
// 3. 注册组件
const app = new Vue({
el: "#app",
components: {
'newComponent': newComponent
}
})
</script>
注:无论是全局组件还是局部组件,都可以重复使用。template中必须有且仅有一个 root 元素,这里一般指的是 div 标签。
4. 组件内部 data 中的数据
我们知道在 vue 实例中可以使用 data 中的数据,在组件内部中同样可以使用 data 中的数据。
- 组件中的 data 值必须是一个函数,这个函数必须要返回一个对象
- 以 {{}} 形式使用 data 中的数据
<div id="app">
<!-- 2.组件使用 -->
<new-component></new-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 1.注册全局组件
Vue.component('newComponent', {
// 组件中的 data 值必须是一个函数
data: function(){
//这个函数必须要返回一个对象
return {
price: 15,
msg: "保熟"
}
},
// {{}} 使用组件data中的数据
template: '<div><p> 刘华强:这瓜多少钱一斤?</p> <p> 卖瓜的:{{price}} 元一斤</p><p> 刘华强:卧槽这瓜保熟吗?</p><p> 卖瓜的:{{msg}} </p></div>'
})
const app = new Vue({
el: '#app'
})
</script>
运行结果:
5. 组件传值
5.1 父组件向子组件传值
- 父组件发送的属性值需要绑定到子组件的属性上面,下面例子中 :name 表示绑定子组件的属性是 name,:name="childName" 表示将父组件 childName 的值给了子组件的 name属性。
- 子组件用属性 props 接收,下例中 props:["name"] 表示子组件用 name 来接收父组件的传值。
- props 中的属性如果是驼峰形式,绑定的子组件的属性需要使用短横线的形式。例如 props:["childAge"] 则 :child-age="age"
<!-- 4. 父组件绑定子组件属性进行传值 -->
<div id="app">
<p>父亲:{{username}}</p>
<child :name="childName" :child-age="age"></child>
</div>
<!-- 1. 定义组件模板 -->
<template id="child">
<div>
<p> 儿子姓名:{{ name }}</p>
<p> 儿子年龄:{{ childAge }}</p>
</div>
</template>
<script>
// 2. 定义组件变量保存组件模板对象
const child = {
template: "#child",
// 里面的属性用来接父组件的值
props:["name","childAge"]
}
const app = new Vue({
el: "#app",
data: {
username: "张翠山",
childName:"张无忌",
age:23
},
// 3. 注册组件
components: {
child
},
methods: {
},
})
</script>
5.2 子组件向父组件传值
- 子组件用
$emit()
触发事件 $emit()
第一个参数是事件名称,第二个参数是需要传递的数据- 父组件用 v-on 监听子组件的事件
<div id="app">
<!-- 5. 通过事件绑定将参数传递给父组件的方法 -->
<child @tell="fromChild"> </child>
</div>
<!-- 1. 定义儿子组件模板 -->
<template id="child">
<div>
<h2>我是儿子组件,点击我向父亲传值</h2>
<button @click="change"> 点我</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 2. 定于组件变量保存组件模板对象
const child = {
template: "#child",
data() {
return {
name: "张无忌"
}
},
methods: {
change() {
// 4. 触发事件
this.$emit('tell', this.name);
}
},
}
const app = new Vue({
el: "#app",
data: {
username: "张翠山"
},
// 3. 注册组件
components: {
child
},
methods: {
fromChild(name) {
console.log("儿子:"+name);
}
},
})
</script>
运行结果:
上面例子讲解:
-
- 使用子组件时,通过 @tell 绑定了父组件的 fromChild 方法
-
- 点击子组件的按钮,通过
$emit()
触发 tell 事件,父组件通过 v-on 监听子组件的 tell 事件,其中 @tell 就是 v-on:tell 的缩写,父组件将监听到的数据传递给自己的 fromChild 方法。
- 点击子组件的按钮,通过
-
- 父组件的 fromChild 方法打印出数据
6. 组件访问
6.1 父组件访问子组件数据
- 使用子组件时用
$refs
给子组件定义一个别名 - 使用
this.$refs.子组件别名
可以获取子组件信息
<div id="app">
<!-- 4. 使用组件,通过 ref 给子组件起一个别名 -->
<new-component ref="firstChild"></new-component>
<hr>
<button @click="getFilmName">点我</button>
</div>
<!-- 1. 声明局部组件模板 -->
<template id="newTemplate">
<div>我是个局部组件,只能在当前vue实例中使用!</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 2. 定义变量保存模板对象
var newComponent = {
template: '#newTemplate',
data: function () {
//这个函数必须要返回一个对象
return {
film: "扫黑风暴"
}
},
}
// 3. 注册组件
const app = new Vue({
el: "#app",
data: {
msg: ""
},
components: {
'newComponent': newComponent
},
methods: {
getFilmName(){
// 5.this.$refs.firstChild.film 获取子组件的属性
console.log("最近热播剧:"+this.$refs.firstChild.film);
}
},
})
</script>
运行结果:
6.2 子组件访问父组件数据
- 使用
this.$parent
访问父组件
<div id="app">
<!-- 4. 使用组件 -->
<new-component></new-component>
</div>
<!-- 1. 声明局部组件模板 -->
<template id="newTemplate">
<div>
<h2>这是子组件!</h2>
<hr>
<button @click="getFilmName">点我</button>
</div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// 2. 定义变量保存模板对象
var newComponent = {
template: '#newTemplate',
methods: {
getFilmName(){
console.log("最近热播剧:"+this.$parent.film);
}
},
}
// 3. 注册组件
const app = new Vue({
el: "#app",
data: {
film: "扫黑风暴"
},
components: {
'newComponent': newComponent
},
methods: {
},
})
</script>
运行结果:
7. 组件插槽
-
- 新建组件,使用
<slot>默认内容</slot>
展示默认内容
- 新建组件,使用
-
- 使用组件时,组件标签中间的内容覆盖 slot 标签里面的内容
-
- 使用组件插槽可以增加代码复用性
7.1 匿名插槽
设置默认值,组件标签有值就覆盖默认值,没有就显示默认值。
<div id="app">
<!-- 2. 所有组件标签中嵌套的内容会替换掉slot,如果不传值则使用 slot 中的默认值 -->
<final></final>
<final>贺芸是大boss!/final>
<final>高明远是大boss!</final>
<final>王政是大boss!</final>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
// 1、定义全局组件,slot 插槽中设置默认值
Vue.component('final', {
template: `
<div>
<span>扫黑风暴大结局:</span>
<slot>谁是大boss?</slot>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
}
});
</script>
运行结果:
7.2 具名插槽
就是给插槽设置个
名字
,使用组件的时候可以给特定名字
的插槽设置值。
<div id="app">
<!-- 2. 所有组件标签中嵌套的内容会替换掉slot,如果不传值则使用 slot 中的默认值 -->
<final></final>
<final>贺芸是大boss!</final>
<final>高明远是大boss!</final>
<final><span slot="boss" style="color:red">打死都不剧透!!</span> </final>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript">
// 1、定义全局组件,slot 插槽中设置默认值
Vue.component('final', {
template: `
<div>
<span>扫黑风暴大结局:</span>
<slot name="boss">谁是大boss?</slot>
</div>
`
});
const app = new Vue({
el: '#app',
data: {
}
});
</script>
运行结果: