本节内容:
一、组件[component]
1.1局部组件
1.2 默认组件(全局组件)
组件传值
2.1 父组件往子组件传值
2.2 子组件父组件传值
2. 3 平行组件传值
一、组件[component]
组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能
而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个
功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。
所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。
这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。
我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,
根据网页上的功能区域我们又可以细分成其他组件,或称为子组件
注意: 在组建中template ,写组件中的html标签时,外层一定要套一个标签
1.1局部组件
三步:声子、用子、挂子
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<div class="vheader">
这是头部{{msg}}
</div>
<App/> <!--3 使用子组件-->
</div>
</body>
<script>
//子组件的名称尽量不要叫做Header或者vHeader等,以防和最新的H5中的标签名称冲突,导致组件无法使用
// 1 声明子组件
let App = {
data(){
return { //组件中必须写成函数形式的
'appmsg':'hello app!'
}
},
// 写组件的html标签的地方
template:`
<div class="content">
内容部分{{appmsg}}
</div>
`
};
let vm = new Vue({
el:'#app',
data(){
return {
'msg':'hello'
}
},
components:{
//App:App //键的名臣和组件名称相同时,可以简写
App, // 2 挂载子组件
}
})
</script>
</html>
View Code
1.2 默认组件(全局组件)
直接看代码,局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,
局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的
时候,在哪里可能都会用到的时候。
<div id="app">
<addnum></addnum>
</div>
<script>
Vue.component("addnum",{
template:'<div><input type="text" v-model="num"><button @click="num+=1">点击</button></div>',
data: function(){
// 写在这里的数据只有当前组件可以使用
return {
num:1,
}
}
});
var vm = new Vue({
el:"#app",
data:{
}
})
</script>
View Code
二、组件传值
2.1 父组件往子组件传值
两步:
1.在子组件中使用props属性声明,然后可以直接在子组件中任意使用
2.父组件要定义自定义的属性
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<div class="vheader">
这是头部{{msg}}
</div>
<App :xx="msg"/>
</div>
</body>
<script>
let App = {
data(){
return {
'appmsg':'hello app!'
}
},
template:`
<div class="content">
内容部分{{appmsg}}--{{xx}}
</div>
`,
props:['xx',]
};
let vm = new Vue({
el:'#app',
data(){
return {
'msg':'hello'
}
},
components:{
App,
}
})
</script>
</html>
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<h1>{{ganmao}}</h1>
<!-- 用子: 使用子组件 -->
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>
// 局部组件
//1 声子: 声明子组件
let Vheader = {
data(){
return {
msg:'我是子组件1号'
}
},
// 写组件的html标签的地方
template:
`
<div class="c1">
<h3 style="color:#ff0000">{{msg}}</h3>
<h2 style="color:blue;">{{son}}</h2>
</div>
`
,
props:['son', ], //第二步: 写父组件中使用子组件时的自定义标签属性名称,那么他就可以拿到标签属性对应的值,并且可以作为当前子标签的一个数据属性来使用
};
let App = {
data(){
return {
app_num:80,
}
},
components: {
Vheader,
},
// 注意: 写组件中的html标签时,外层一定要套一个标签
// 第一步: 使用子组件的地方写自定义属性
// 静态传值: <Vheader son="20"></Vheader>
// 动态传值: <Vheader :son="app_num"></Vheader>
template:
`
<div class="app">
<h2>我是app组件</h2>
<Vheader :son="app_num"></Vheader>
</div>
`
}
let vm = new Vue({
el:'#app',
// data:{}
data(){
return {
ganmao:'xxx',
}
},
components:{
App,
}
})
</script>
</html>
View Code
使用父组件传递数据给子组件时, 注意一下几点:
1. 传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
2. 父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"
2.2 子组件父组件传值
两步:
a.子组件中使用this.$emit('fatherHandler',val);fatherHandler是父组件中使用子组件的地方添加的绑定自定义事件,
注意,如果fatherHandler报错了,那么可能是你的vue版本不支持自定义键名称fatherHandler中有大写字母,
所以我们改成father-handler或者直接就全部小写就可以了
b.父组件中的methods中写一个自定义的事件函数:appFatherHandler(val){},在函数里面使用这个val,
这个val就是上面子组件传过来的数据
第一步:在父组件使用子组件的地方写自定义事件
<Vheader @fatherHandler="xx"></Vheader>
第二步: 在子组件中this.$emit('fatherHandler', 200);
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<div class="vheader">
这是头部{{msg}} -- {{sondata}}
</div>
<App @son="sonDataHandler"/>
</div>
</body>
<script>
let App = {
data(){
return {
'appmsg':'hello app!'
}
},
template:`
<div class="content">
内容部分{{appmsg}}
<button @click="xH"></button>
</div>
`,
methods:{
xH(){
this.$emit('son',this.appmsg)
}
}
};
let vm = new Vue({
el:'#app',
data(){
return {
'msg':'hello',
'sondata':'xxx',
}
},
components:{
App,
},
methods:{
sonDataHandler(val){
console.log(val);
this.sondata = val;
}
}
})
</script>
</html>
View Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<h1>{{ganmao}}</h1>
<!-- 用子: 使用子组件 -->
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>
// 局部组件
//1 声子: 声明子组件
let Vheader = {
data(){
return {
msg:'我是子组件1号',
header_num:99,
}
},
// 写组件的html标签的地方
template:
`
<div class="c1">
<h3 style="color:#ff0000">{{msg}}</h3>
<button @click="zouni">zouni</button>
</div>
`
,
methods: {
zouni(){
console.log(this);
// this -- 组件对象
this.$emit('fatherHandler', this.header_num);
}
}
};
let App = {
data(){
return {
app_num:80,
// 声明数据属性,承接子组件传递来的值
son_data:0,
}
},
components: {
Vheader,
},
// 第一步:在父组件使用子组件的地方写自定义事件
// <Vheader @fatherHandler="xx"></Vheader>
// 第二步: 在子组件中this.$emit('fatherHandler', 200);
template:
`
<div class="app">
<h2>我是app组件</h2>
<Vheader @fatherHandler="xx"></Vheader>
<h3 style="color:yellow;">{{son_data}}</h3>
</div>
`
,
methods:{
xx(val){
this.son_data = val;
console.log(this);
// console.log('>>>>>', val);
},
}
}
let vm = new Vue({
el:'#app',
// data:{}
data(){
return {
ganmao:'xxx',
}
},
components:{
App,
},
})
console.log(vm);
</script>
</html>
View Code
2. 3 平行组件传值
什么是平行组件,看图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<h1>{{ganmao}}</h1>
<!-- 用子: 使用子组件 -->
<App></App>
</div>
</body>
<script src="../vue.js"></script>
<script src="../axios.js"></script>
<script>
// 第一步:声明公交车
let bus = new Vue();
let Vheader2 = {
data(){
return {
msg:'我是子组件2号',
header2_num:88,
vheader_data:'',
}
},
// 写组件的html标签的地方
template:
`
<div class="c1">
<h3 style="color:#ff0000">{{msg}}</h3>
<h3>{{vheader_data}}</h3>
</div>
`,
created(){
// 第三步:在公交车上获取值
bus.$on('xxx',(val) => {
console.log('???', val); // ??? 99
this.vheader_data = val;
});
}
}
// 局部组件
//1 声子: 声明子组件
let Vheader = {
data(){
return {
msg:'我是子组件1号',
header_num:99,
}
},
// 写组件的html标签的地方
template:
`
<div class="c1">
<h3 style="color:#ff0000">{{msg}}</h3>
<button @click="zouni">zouni</button>
</div>
`
,
methods: {
zouni(){
// 第二步:往公交车上添加值
bus.$emit('xxx', this.header_num)
}
}
};
let App = {
data(){
return {
app_num:80,
// 声明数据属性,承接子组件传递来的值
son_data:0,
}
},
components: {
Vheader,
Vheader2,
},
// 第一步:在父组件使用子组件的地方写自定义事件
// <Vheader @fatherHandler="xx"></Vheader>
// 第二步: 在子组件中this.$emit('fatherHandler', 200);
template:
`
<div class="app">
<h2>我是app组件</h2>
<Vheader></Vheader>
<Vheader2></Vheader2>
</div>
`
,
methods:{
xx(val){
this.son_data = val;
console.log(this);
// console.log('>>>>>', val);
},
}
}
let vm = new Vue({
el:'#app',
// data:{}
data(){
return {
ganmao:'xxx',
}
},
components:{
App,
},
})
console.log(vm);
</script>
</html>
例子1
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<div class="vheader">
这是头部{{msg}} -- {{sondata}}
</div>
<!--<App :xx="msg"/>-->
<App @sonHa="sonDataHandler"/>
</div>
</body>
<script>
let bus = new Vue();
Vue.component('T1',{
data(){
return {
't1num':100,
}
},
template:`
<div class="t1">
{{t1num}}
<button @click="f1">走你</button>
</div>
`,
methods:{
f1(){
// console.log(this.t1num);
bus.$emit('TestData',this.t1num)
}
}
});
Vue.component('T2',{
data(){
return {
't2num':200,
't1n':0,
}
},
template:`
<div class="t2">
<h1>{{t2num}}</h1>
<h2 style="color:red;">{{t1n}}</h2>
</div>
`,
created(){
// console.log(this.t1n);
bus.$on('TestData',(val)=>{
console.log(val);
this.t1n = val;
})
}
});
let App = {
data(){
return {
'appmsg':'hello app!'
}
},
template:`
<div class="content">
内容部分{{appmsg}}
<button @click="xH">点击</button>
<T1></T1>
<T2></T2>
</div>
`,
methods:{
xH(){
this.$emit('sonHa',this.appmsg)
}
// console.log(this);
}
// props:['xx',]
};
let vm = new Vue({
el:'#app',
data(){
return {
'msg':'hello',
'sondata':'xxx',
}
},
components:{
App,
},
methods:{
sonDataHandler(val){
console.log(val);
this.sondata = val;
}
}
})
</script>
</html>
例子2