全局组件
如何定义全局组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
{{str}}
<zujian></zujian>
</div>
<template id="zujian">
<div>
{{str}}
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
Vue.component("zujian",{
template:"#zujian",
data() {
return {
str:"这是组件中的String"
}
},
})
let vm =new Vue({
data() {
return {
str:"这是实例中的String"
}
},
})
vm.$mount("#app")
</script>
</html>
组件的试图模板中只能有一个容器
实例和组件的数据互不相通
组件中的data必须是函数式返回一个对象
data函数式和data对象的区别(类似于深拷贝和浅拷贝):
data对象:如果在父组件中定义数据,子组件中使用该数据并修改,会影响父组件中原本的数据,以及其他使用该数据的子组件
data函数式:当子组件想要使用data中的数据时,父组件会单独返回一个数据给子组件,当子组件修改该数据时,对父组件原本的数据没有影响
可以有多个组件,每个组件可以多次使用
局部组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<child1></child1>
</div>
<template id="child1">
<div>
<div>{{str}}</div>
<div v-for="item in arr" :key="item">
<div>{{item}}</div>
</div>
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
let vm=new Vue({
data() {
return {
}
},
components:{
child1:{
template:"#child1",
data() {
return {
str:"this is child1",
arr:["111","222","333"],
}
},
}
}
})
vm.$mount("#app")
</script>
</html>
全局组件和局部组件的区别:
1.当全局组件在当前项目中的任何地方都可以使用,局部组件只能在当前注册的父组件中使用
2.全局组件适用于公共的组件,如导航栏、弹框、页脚等;局部组件适用于一些特定场景下使用的组件
父组件和子组件的例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 实例的视图模板 -->
<div id="app">
<parent></parent>
</div>
<!--父组件的视图模板 -->
<template id="parent">
<div>
<div>{{str}}</div>
<!-- 展示子组件 -->
<child></child>
</div>
</template>
<!-- 子组件的视图模板 -->
<template id="child">
<div>
<div>{{str}}</div>
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
// 父组件
Vue.component("parent",{
template:"#parent",
data() {
return {
str:"data from parent"
}
},
components:{
// 子组件
child:{
template:"#child",
data() {
return {
str:"data from child"
}
},
}
}
})
let vm=new Vue({
data() {
return {
}
},
})
vm.$mount("#app")
</script>
</html>
组件的生命周期
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<div id="app">
<parent></parent>
</div>
<template id="parent">
<div>
<div>{{str}}</div>
<child></child>
</div>
</template>
<template id="child">
<div>
<div>{{str}}</div>
<grandson></grandson>
</div>
</template>
<template id="grandson">
<div>
<div>{{str}}</div>
</div>
</template>
<body>
</body>
<script src="../vue.min.js"></script>
<script>
Vue.component("parent", {
template: "#parent",
data() {
return {
str:"data from parent"
}
},
beforeCreate() {
console.log("【父组件】创建前");
},
created() {
console.log("【父组件】创建后");
},
beforeMount() {
console.log("【父组件】挂载前");
},
mounted() {
console.log("【父组件】挂载后");
},
components: {
child: {
template: "#child",
data() {
return {
str:"data from child"
}
},
beforeCreate() {
console.log("【子组件】创建前");
},
created() {
console.log("【子组件】创建后");
},
beforeMount() {
console.log("【子组件】挂载前");
},
mounted() {
console.log("【子组件】挂载后");
},
components: {
grandson: {
template: "#grandson",
data() {
return {
str:"data from grandson"
}
},
beforeCreate() {
console.log("【孙组件】创建前");
},
created() {
console.log("【孙组件】创建后");
},
beforeMount() {
console.log("【孙组件】挂载前");
},
mounted() {
console.log("【孙组件】挂载后");
},
}
}
}
}
})
let vm = new Vue({
data() {
return {
}
},
beforeCreate() {
console.log("【实例】创建前");
},
created() {
console.log("【实例】创建后");
},
beforeMount() {
console.log("【实例】挂载前");
},
mounted() {
console.log("【实例】挂载后");
},
})
vm.$mount("#app")
</script>
</html>
根据上图我们可以发现:首先是实例创建前、实例创建后、挂载前、然后是父组件的创建前、创建后、挂载前,在然后是子组件的创建前、创建后、挂载前,其次是孙组件的创建前、创建后、挂载前,最后是,孙组件、子组件、父组件、实例的挂载后。
父子组件的生命周期钩子函数执行流程
父组件beforeCreate创建前===>父组件created创建后===>父组件beforeMout挂载前===>子组件beforeCreate创建前===>子组件created创建后===>子组件beforeMount挂载前===>子组件挂载后===>父组件mounted挂载后
也就是说,除实例以外,每一个组件都是在其父组件完成挂载之前创建的。
父组件和子组件的数据传递
1.正向传递数据(父传子):Vue中支持正向传递数据
父组件中通过自定义属性将数据传递给子组件,子组件通过props属性接受数据
2.逆向传递数据(子传父):Vue中不支持逆向传递数据
父传子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<zujian :zifuchuan="str" :tupian="path"></zujian>
</div>
<template id="zujian">
<div>
<div>{{zifuchuan}}</div>
<img :src="tupian" alt="">
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
let vm = new Vue({
data() {
return {
str: "data from 实例",
path: "../img/606b810a2b8961edf94e4d3d939f6ad3.png"
}
},
components: {
zujian: {
template: "#zujian",
data() {
return {
}
},
props: ["zifuchuan", "tupian"]
}
}
})
vm.$mount("#app")
</script>
</html>
在父组件的自定义标签中添加要传递的数据的名字和值,然后在子组件中使用props[]来接受([ ]中写父组件传递的数据的变量名)
循环遍历数组中的整个对象向下传递
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
img{
width: 100px;
height: 100px;
}
</style>
<body>
<div id="app">
<div>
<parent v-for="item in arr" :key="item" :obj="item"></parent>
</div>
</div>
<template id="parent">
<div>
<img :src="obj.imgPath" alt="" >
<child :biaoti="obj.title"></child>
</div>
</template>
<template id="child">
<div>
<h1>{{biaoti}}</h1>
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
Vue.component("parent",{
template:"#parent",
data() {
return {
}
},
props:["obj"],
components:{
child:{
template:"#child",
props:["biaoti"]
}
}
})
let vm=new Vue({
data() {
return {
arr:[
{imgPath:"../img/1.png",title:"图片1"},
{imgPath:"../img/2.png",title:"图片2"},
{imgPath:"../img/3.png",title:"图片3"},
{imgPath:"../img/4.png",title:"图片4"},
{imgPath:"../img/5.png",title:"图片5"},
]
}
},
})
vm.$mount("#app")
</script>
</html>
我们可以将要循环的数组,在实例中就将对象拆开一个一个向下传递,也可直接将每个对象向下传递
子传父
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>子组件传递来的数据{{ziStr}}</div>
<!-- 子组件通过自定义监听事件将数据传递给父组件 -->
<parent @event="fun"></parent>
</div>
<template id="parent">
<div>
<button @click="run">子组件给父组件传递数据</button>
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script>
Vue.component("parent",{
template:"#parent",
data() {
return {
str:"子组件的str",
}
},
methods:{
run(){
//向上传递数据:通过自定义监听事件传递
//#emit("事件名",要传递是真实数据)
this.$emit('event',this.str)
}
}
})
let vm=new Vue({
data() {
return {
ziStr:""
}
},
methods: {
fun(value){
console.log("value::",value);
this.ziStr=value
}
},
})
vm.$mount("#app")
</script>
</html>
点击按钮后====>
子组件使用run()方法中的$emit()来将数据传递
父组件定义一个监听器来接受数据
当我们在组件中,两个兄弟组件怎么传递数据?当a组件想传递数据给其兄弟组件b时,a组件先将数据传递给父组件,父组件再将数据传递给b组件,这样的话就完成了数据的传递
最后附上一个小案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
ul{
list-style: none;
}
ul{
width: 100%;
height: 100%;
background-color: aqua;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
ul>li{
width: 18%;
height: 100%;
text-align: center;
line-height: 50px;
}
.bg{
background-color: yellow;
}
</style>
<body>
<div id="app">
<ul id="list">
<li>
<router-link to="/tianmao">
天猫
</router-link>
</li>
<li>
<router-link to="/taobao">
淘宝
</router-link>
</li>
<li>
<router-link to="/jingdong">
京东
</router-link>
</li>
</ul>
<router-view></router-view>
</div>
<template id="tianmao">
<div>
<h1>this is tianmao</h1>
<h1>this is tianmao</h1>
<h1>this is tianmao</h1>
<h1>this is tianmao</h1>
<h1>this is tianmao</h1>
</div>
</template>
<template id="taobao">
<div>
<h1>this is taobao</h1>
<h1>this is taobao</h1>
<h1>this is taobao</h1>
<h1>this is taobao</h1>
<h1>this is taobao</h1>
</div>
</template>
<template id="jingdong">
<div>
<h1>this is jingdong</h1>
<h1>this is jingdong</h1>
<h1>this is jingdong</h1>
<h1>this is jingdong</h1>
<h1>this is jingdong</h1>
</div>
</template>
</body>
<script src="../vue.min.js"></script>
<script src="../vue-router.js"></script>
<script>
let vm=new Vue({
data() {
return {
}
},
router : new VueRouter({
routes: [
{
path:"/",
component:{
template:"#tianmao"
}
},
{
path:"/tianmao",
component:{
template:"#tianmao"
}
},
{
path:"/taobao",
component:{
template:"#taobao"
}
},
{
path:"/jingdong",
component:{
template:"#jingdong"
}
},
]
})
})
vm.$mount("#app")
</script>
</html>
使用Vue的组件的切换,使得点击导航栏中不同的标签显示不同的内容