组件
定义:一段封装了html css的代码
组件的两种注册方式
全局变量
Vue.component("组件名",{
template:"html代码",
data(){
},
methods:{
},
computed:{
},
watch:{
})
<div id="app">
<my-com></my-com>
</div>
<script>
Vue.component("myCom",{
template:`<div>
<h1>我是一个组件</h1>
<a>百度一下,你就知道</a>
</div>`
})
new Vue({
el:"#app"
})
</script>
局部注册
可以同时在局部注册多个组件,组件之间也可以调用,但是记得要注册
var head = {
template: `<div><h1 >{{msg}}</h1></div>`,
data: function () { return { msg: "我是头部" } },
}
new Vue({//根实例,是最大的组件
el: "#app",
data: {},
components: {
myhead:head,//组件名:组件配置项
}
})
<div id="app">
<my-com></my-com>
<my-com></my-com>//可以复用
</div>
<script>
const myCom={
template:`<div>
<h1>{{msg}}</h1>
<h2>{{gender}}</h2>
</div>`,
data(){
return{
sex:1,
msg:"我是局部注册的第一个组件"
}
},
computed:{
gender(){
return this.sex==1?"男":"女"
}
}
}
const myCom1={
template:`<div>
<h1>{{msg}}</h1>
<h2>{{gender}}</h2>
</div>`,
data(){
return{
sex:1,
msg:"我是局部注册的第二个组件"
}
},
computed:{
gender(){
return this.sex==1?"男":"女"
}
}
}
new Vue({
el: "#app",
data: {},
components: {
myCom
}
})
</script>
注意:
- 没有挂载点
- 多了一个template属性,是放html结构的
- 组件必须得有template
- 组件标签只能有一个根节点,最外层要由一个大的div包裹
- 组件名在js中是使用驼峰式,在html中改为以横线连接的小写字母
- 组件中的data必须是函数,并且必须要return一个对象,就是我们的数据对象
组件之间的传值
组件之间传值的三种情况:
1.父- 子 props
2.子 -父 自定义事件
3.同级:先子给父,再父给子
父-子传值:props(属性)
注意:子组件不允许直接修改父组件传入的属性,如果需要更新(更改)这个属性,只能让父组件重新传
用法:
1.子组件内部要接收属性并规定属性的使用场景
2.父组件中使用子组件要给属性传实际的数据
子父传值:
<div id="app">
<my-com :a="msg" :b="change" :c="arr"></my-com>
</div>
<script>
const myCom={
props:["a","b","c"],//子组件内部接收的属性
template:`<div>
//规定属性的使用场景
<h1 @click="b">我是组件:{{a}}</h1>
<ul>
<li v-for="item in c">{{item}}</li>
</ul>
</div>`,
}
new Vue({
el:"#app",
data:{
box:"welcome",
msg:"我是父组件的数据",
info:"哈哈",
arr:[1,2,3,4]
},
methods:{
change(){
console.log(this)
}
},
components:{
//组件名:组件配置项
myCom
}
})
子父孙传值:
<div id="app">
<my-com :a="msg"></my-com>
</div>
<script>
const child={
props:["b"],
template:`<h1>我是孙子组件:{{b}}</h1>`
}
const myCom={
props:["a"],
template:`<div>
<h1>我是子组件:{{a}}</h1>
<child :b="a"></child>
</div>`,
data(){
return{
info:"我是子组件的数据"
}
},
components:{
child
}
}
new Vue({
el:"#app",
data:{
msg:"我是父组件的数据"
},
components:{
myCom
},
})
</script>
子-父:自定义事件
子父传值:定义事件
<div id="app">
<h1 >我是父组件{{msg}}</h1>
<child @abc="fn"></child>
</div>
<script>
const child={
data(){
return{
info:"我是子组件的数据"
}
},
template:`<h1 @click="change">我是子组件</h1>`,
methods:{
change(){
//$emit用于主动触发绑定在本组件标签上的自定义事件
//$emit(自定义事件名,参与方法的参数)
this.$emit("abc",this.info)
}
}
}
new Vue({
el:"#app",
data:{
msg:""
},
components:{
child
},
methods:{
fn(m){
this.msg=m
}
}
})
</script>
插槽
插槽:其实就是给组件标签中的内容(可以是多个标签)预留的位置。如果组件模板中有多个插槽,那么组件标签的内容将会复制,插入到多个插槽中
普通插槽
<div id="app" >
<my-head>
<h1>hello</h1>
</my-head>
</div>
<script>
var head = {
template: `<div>
//插槽,可以把html里的h1标签渲染到页面上
<slot></slot>
<h1 >{{msg}}</h1>
</div>`,
data: function () { return { msg: "我是头部" } },
}
new Vue({
el:"#app",//挂载点
components:{
myHead:head
}
})
</script>
具名插槽(v-slot:可以缩写为#)
给插槽取名字
<body>
<div id="app" >
<my-head>
<template v-slot:before> <!--v-slot:可以缩写为#-->
<h1>hello</h1>
</template>
<template #after>
<h1 >world</h1>
</template>
</my-head>
</div>
<script>
var head = {
template: `<div>
<slot name="before"></slot>
<h1 >{{msg}}</h1>
<slot name="after"></slot>
</div>`,
data: function () { return { msg: "我是头部" } },
}
new Vue({
el:"#app",//挂载点
components:{
myHead:head
}
})
</script>
</body>
编译作用域
如果插槽模板中想使用该组件内部的数据,首先需要在模板的插槽中定义v-bind:属性=“数据”
组件调用的地方插槽通过 v-slot:属性=“prop” prop拿到的不是一个,代表所有属性的集合
<body>
<div id="app">
<mycom>
<template #before="{abc}">//解构赋值
<h1>{{abc}}</h1>
</template>
<template #after="props">
<p>{{props.efg}}</p>
</template>
<template #middle>
<h3>就是开心</h3>
</template>
</mycom>
</div>
<script>
const mycom = {
data(){
return{
msg:"我是子组件的数据1",
info:"我是子组件的数据2"
}
},
template: `
<div>
<h1>我是组件</h1>
<slot name="before" v-bind:abc="msg" ></slot>
<ul>
<slot name="middle"></slot>
<li>1</li>
<li>2</li>
</ul>
<slot name="after" v-bind:efg="info"></slot>
</div>
`
}
new Vue({
el: "#app",
components: {
mycom
},
data:{
msg:"我是父组件"
}
})
</script>
</body>
组件的声明周期
生命周期:组件从创建到销毁的完成过程
生命周期(钩子)函数:在特定的时间节点会自动触发的函数
beforeCreate(){
console.log("组件创建之前")
},
created(){
console.log("组件创建完毕")
},
beforeMount(){
console.log("组件渲染前/组件挂载前")
},
mounted(){
//这个阶段我们能看到组件渲染在页面上
console.log("组件挂载完毕")
},
beforeUpdate(){
//首次不触发,页面重新渲染的时候触发
//子组件用到的属性渲染到了视图中的时候触发(视图是否更新)
console.log("组件更新前")
},
updated(){
console.log("组件更新后")
},
beforeDestroy(){
console.log("组件销毁前")
},
destroyed(){
console.log("组件销毁后")
},
动态组件
<div id="app">
<component v-bind:is="title"></component>
<button @click="change(2)">按钮</button>
</div>
<script>
var coma1 = {
template: `<div><h1>我是第一个组件</h1></div>`,
}
var coma2 = {
template: `<div><h1>我是第二个组件</h1></div>`,
}
var coma3 = {
template: `<div><h1>我是第三个组件</h1></div>`,
}
new Vue({
el: "#app",
data: {
tab: "mycom",
title:"mycom"
},
components: {
coma1,
coma2,
coma3,
},
methods:{
change(n){
this.title="mycom"+n
}
}
})
</script>