组件介绍
组件 挂载点el: 可以理解为被组件 template 模块进行替换的占位符
总结:根组件,可以不明确template,template默认采用挂载点页面结构;如果设置的template,挂载点内部的内容无效,因为会被替换
概念:html、css与js的集合体,为该集合体命名,用该名字复用html、css与js组成的集合体 => 复用性
组件分类:
根组件:new Vue() 生成的组件
局部组件:组件名 = {},{}内部采用的是vue语法
全局组件:Vue.component('组件名', {}),{}内部采用的是vue语法
组件的特点:
1)组件都有管理组件html页面结果的 template 实例成员,template中有且只有一个根标签
2)根组件都是作为最顶层父组件,局部与全局组件作为子组件,也可以成为其他局部与全局组件的父组件
3)子组件的数据需要隔离(数据组件化,每一个组件拥有自己数据的独立名称空间)
4)局部组件必须注册后才能使用,全局组件不需要注册,提倡使用局部组件
5)组件中出现的所有变量(模板中、逻辑中),由该组件自己提供管理
6) 局部全局和根组件都是一个vue实例,一个实例对应一套html、css、js结构,所以实例就是组件
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div id="app"> {{ msg }} </div> </body> <script src="js/vue.js"></script> <script> /** * 组件 * 概念:html、css与js的集合体,为该集合体命名,用该名字复用html、css与js组成的集合体 => 复用性 * * 组件分类: * 根组件:new Vue() 生成的组件 * 局部组件:组件名 = {},{}内部采用的是vue语法 * 全局组件:Vue.component('组件名', {}),{}内部采用的是vue语法 * * 组件的特点: * 1)组件都有管理组件html页面结果的 template 实例成员,template中有且只有一个根标签 * 2)根组件都是作为最顶层父组件,局部与全局组件作为子组件,也可以成为其他局部与全局组件的父组件 * 3)子组件的数据需要隔离(数据组件化,每一个组件拥有自己数据的独立名称空间) * 4)局部组件必须注册后才能使用,全局组件不需要注册,提倡使用局部组件 * 5)组件中出现的所有变量(模板中、逻辑中),由该组件自己提供管理 * 6) 局部全局和根组件都是一个vue实例,一个实例对应一套html、css、js结构,所以实例就是组件 */ new Vue({ el: '#app', // 被组件 template 模块进行替换的占位符 data: { msg: '组件信息' }, template: '<p>{{ msg }}</p>' }) // 总结:根组件,可以不明确template,template默认采用挂载点页面结构;如果设置的template,挂载点内部的内容无效,因为会被替换 // 解释:html,body标签不能被替换,所以不能作为挂载点 </script> </html>
子组件
声明局部组件:局部组件要在其父组件中注册 components 才能使用
1、声明组件 2、注册组件 3、渲染组件 => 全局组件不需要注册
组件里面大写字母,对应的是 -加上对应的小写字母
子组件:
<div id="app"> <div class="wrap"> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> </div> </div>
<script>
let localTag = { template: ` <div class="box" @click="fn"> <img src="img/001.jpg" alt=""> <h2>美女</h2> </div> `, methods: { fn() { console.log(this) } } };
new Vue({
el: '#app',
data: {},
components: { // 注册组件
localTag,
}
})
</script>
全局组件:
<div id="app"> <div class="wrap"> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> </div> </div> <script> Vue.component('global-tag', { template: ` <div class="box" @click="fn"> <img src="img/002.jpg" alt=""> <h2>大长腿</h2> </div> `, methods: { fn() { console.log(this) } } }); </script>
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>子组件</title> <style> body, h2 { margin: 0; } .wrap { width: 880px; margin: 0 auto; } .wrap:after { content: ''; display: block; clear: both; } .box { width: 200px; border-radius: 10px; overflow: hidden; background-color: #eee; float: left; margin: 10px; } .box img { width: 100%; } .box h2 { text-align: center; font-weight: normal; font-size: 20px; } </style> </head> <body> <div id="app"> <div class="wrap"> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> <global-tag></global-tag> </div> </div> </body> <script src="js/vue.js"></script> <script> // 声明局部组件:局部组件要在其父组件中注册才能使用 // 1、声明组件 2、注册组件 3、渲染组件 => 全局组件不需要注册 let localTag = { template: ` <div class="box" @click="fn"> <img src="img/001.jpg" alt=""> <h2>美女</h2> </div> `, methods: { fn() { console.log(this) } } }; Vue.component('global-tag', { template: ` <div class="box" @click="fn"> <img src="img/002.jpg" alt=""> <h2>大长腿</h2> </div> `, methods: { fn() { console.log(this) } } }); new Vue({ el: '#app', data: {}, components: { // 注册组件 localTag, } }) </script> </html>
组件的数据局部化
局部或全局取件,一个组件可能会被复用多次,每个组件都应该有自己独立的变量名称空间
数据需要组件化,作为方法的返回值(方法执行后会产生一个局部作用域,把每个数据隔离开)
.
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>组件化</title> <style> body, h2 { margin: 0; } .wrap { width: 880px; margin: 0 auto; } .wrap:after { content: ''; display: block; clear: both; } .box { width: 200px; border-radius: 10px; overflow: hidden; background-color: #eee; float: left; margin: 10px; } .box img { width: 100%; } .box h2 { text-align: center; font-weight: normal; font-size: 20px; } </style> </head> <body> <div id="app"> <div class="wrap"> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> <local-tag></local-tag> </div> </div> </body> <script src="js/vue.js"></script> <script> let localTag = { template: ` <div class="box" @click="fn"> <img src="img/001.jpg" alt=""> <h2>捶了{{ count }}下</h2> </div> `, data() { // 局部或全局取件,一个组件可能会被复用多次,每个组件都应该有自己独立的变量名称空间 return { count: 0, } }, // 数据需要组件化,作为方法的返回值(方法执行后会产生一个局部作用域) methods: { fn() { console.log(this); this.count++; } } }; new Vue({ el: '#app', data: {}, components: { localTag, } }); ` class A: name = 'Owen' def __init__(self, name): self.name = name a1 = A('1') a2 = A('2') a1.name a2.name `; </script> </html>
组件传参---父传子 props
通过绑定属性的方式进行数据传递
1)子组件可以通过props自定义组件属性(采用反射机制,需要填写字符串,但是使用时可以直接作为变量)
2)子组件会在父组件中渲染,渲染时,将父组件的变量绑定给子组件的自定义属性,将可以将变量值传递给子组件
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>父传子</title>
<style>
body, h2 {
margin: 0;
}
.wrap {
880px;
margin: 0 auto;
}
.wrap:after {
content: '';
display: block;
clear: both;
}
.box {
200px;
border-radius: 10px;
overflow: hidden;
background-color: #eee;
float: left;
margin: 10px;
}
.box img {
200px;
height: 240px;
}
.box h2 {
text-align: center;
font-weight: normal;
font-size: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="wrap">
<local-tag v-for="dog in dogs" :abc="dog" def="12345" :xyz="dog.name"></local-tag>
</div>
</div>
</body>
<script src="js/vue.js"></script>
<script>
let dogs = [
{
name: '二哈1号',
img: 'img/100.jpg',
},
{
name: '二哈2号',
img: 'img/200.jpg',
},
{
name: '二哈3号',
img: 'img/300.jpg',
},
{
name: '二哈4号',
img: 'img/400.jpg',
},
{
name: '二哈1号',
img: 'img/100.jpg',
},
{
name: '二哈2号',
img: 'img/200.jpg',
},
{
name: '二哈3号',
img: 'img/300.jpg',
},
{
name: '二哈4号',
img: 'img/400.jpg',
}
];
// 1)子组件可以通过props自定义组件属性(采用反射机制,需要填写字符串,但是使用时可以直接作为变量)
// 2)子组件会在父组件中渲染,渲染时,将父组件的变量绑定给子组件的自定义属性,将可以将变量值传递给子组件
let localTag = {
props: ['abc', 'def', 'xyz'],
template: `
<div class="box" @click="fn">
<img :src="abc.img" alt="">
<h2>捶{{ abc.name }}{{ count}}下</h2>
<!--<h3>{{ abc }}</h3>-->
<!--<h3>{{ def }}</h3>-->
<!--<h3>{{ xyz }}</h3>-->
</div>
`,
data() {
return {
count: 0,
}
},
methods: {
fn() {
console.log(this.abc);
this.count++;
}
}
};
new Vue({
el: '#app',
data: {
dogs,
},
components: {
localTag,
}
});
</script>
</html>
<div id="app"> <global-tag :sup_data1='sup_data1' :supData2='sup_data2'></global-tag> </div> <script type="text/javascript"> Vue.component('global-tag', { props:['sup_data1', 'supdata2'], template: '<div>{{ sup_data1 }} {{ supdata2 }}</div>' }) new Vue({ el: '#app', data: { sup_data1: '数据1', sup_data2: '数据2' } }) </script>
组件传参---子传父
通过发送事件请求的方式进行数据传递
this.$emit('自定义事件名', 触发事件回调的参数们)
自定义组件标签的事件
自定义事件是属于子组件的,子组件在父组件中渲染并绑定事件方法,所以事件方法由父组件来实现
子组件如何触发自定义事件:this.$emit('自定义事件名', 触发事件回调的参数们)
子组件触发自定义事件,携带出子组件的内容,在父组件中实现自定义事件的方法,拿到子组件传递给父组件的消息
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <title>子传父</title> </head> <body> <div id="app"> <h1>{{ h1 }}</h1> <h3>{{ h3 }}</h3> <!--自定义组件标签的事件 自定义事件是属于子组件的,子组件在父组件中渲染并绑定事件方法,所以事件方法由父组件来实现 子组件如何触发自定义事件:this.$emit('自定义事件名', 触发事件回调的参数们) 子组件触发自定义事件,携带出子组件的内容,在父组件中实现自定义事件的方法,拿到子组件传递给父组件的消息 --> <tag @action="actionFn"></tag> <hr> <tag2 @h1a="aFn1" @h3a="aFn3"></tag2> </div> </body> <script src="js/vue.js"></script> <script> let tag = { template: ` <div> <input type="text" v-model="t1"> <input type="text" v-model="t2"> <button @click="changeTitle">修改标题</button> </div> `, data() { return { t1: '', t2: '', } }, methods: { changeTitle() { if (this.t1 && this.t2) { // console.log(this.t1, this.t2); this.$emit('action', this.t1, this.t2); this.t1 = ''; this.t2 = ''; } } } }; let tag2 = { template: ` <div> 主标题内容:<input type="text" v-model="t1" @input="t1Fn"> 子标题内容:<input type="text" v-model="t2"> </div> `, data() { return { t1: '', t2: '', } }, methods: { t1Fn() { this.$emit('h1a', this.t1); } }, watch: { t2 () { this.$emit('h3a', this.t2); } } }; new Vue({ el: '#app', data: { h1: '主标题', h3: '子标题' }, components: { tag, tag2, }, methods: { actionFn(a, b, c) { // console.log('触发了', a, b, c); this.h1 = a; this.h3 = b; }, aFn1(a) { if (!a) { this.h1 = '主标题'; return; } this.h1 = a; }, aFn3(a) { if (!a) { this.h3 = '子标题'; return; } this.h3 = a; }, } }) </script> </html>
<div id="app"> <global-tag @send_action='receiveAction'></global-tag> </div> <script type="text/javascript"> Vue.component('global-tag', { data () { return { sub_data1: "数据1", sub_data2: '数据2' } }, template: '<div @click="clickAction">发生</div>', methods: { clickAction () { this.$emit('send_action', this.sub_data1, this.sub_data2) } } }) new Vue({ el: '#app', methods: { receiveAction (v1, v2) { console.log(v1, v2) } } }) </script>