一:组件化开发基础
1.组件是什么?有什么用?
组件就是:扩展 HTML 元素,封装可重用的代码
,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html
组件的分类:
- 全局组件:可以放在根中
- 局部组件:
工程化开发之后:
1个组件 就是1个xx.vue
二:组件的注册方式
1. 定义全局组件,绑定事件,编写样式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>全局组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><div @click="handleClick">我是根部组件</div><global></global><ul><li v-for="i in 4"><global></global></li></ul>
</div></body>
<script>// 创建1个组件对象(全局组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是头部组件</div><div v-if="isShow">显示消失</div></div>`,methods: {handleClick() {console.log('我被点击了')this.isShow = !this.isShow}},data() {return {isShow: true}}})let vm = new Vue({el: '#box',data: {isShow: true},methods: {handleClick() {console.log('我被点击了 我是根组件')}}})
</script>
</html>
3. 定义局部组件
① 局部组件 放在 Vue实例(根组件) 中
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>局部组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box" style="max-width: 300px"><local></local><global></global>
</div></body>
<script>// 创建1个组件对象(全局组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;">我是全局组件</div></div>`,})let vm = new Vue({el: '#box',data: {},// 创建1个组件对象(局部组件)components: {local: { // local 组件名template: `<div><div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;"@click="handleClick">我是局部组件</div></div>`, // 组件的模板methods: {handleClick() {console.log('我被点击了')}}}}})
</script>
</html>
② 局部组件 放在 全局组件 中
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>局部组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box" style="max-width: 300px"><ul><li v-for="i in 3"><global></global></li></ul>
</div></body>
<script>// 创建1个组件对象(全局组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;">我是全局的组件</div><local></local><local></local><br></div>`,// 创建1个组件对象(局部组件)components: {local: {template: `<div><div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是局部组件</div></div>`,}}})let vm = new Vue({el: '#box',})
</script>
</html>
注意点:
- 定义的组件(body中的位置)必须要放在Vue实例(这也是一个组件 根组件)中
- 局部组件 必须放在 全局组件/根组件 中,无法单独使用
- 定义的组件必须在Vue实例的上方
二:组件编写方式 与 Vue实例的区别
Vue实例(其实,它也是1个组件,是1个根组件)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><ul><li>字符串:{{name}}</li><li>数值:{{age}}</li><li><button @click="handleClick()">Click Here</button></li></ul>
</div></body>
<script>let vm = new Vue({el: '#box',data: {name: 'Darker',age: 18,},methods: {handleClick() {alert('按钮被点击')}}})
</script>
</html>
组件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>局部组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box" style="max-width: 300px"><ul><li v-for="i in 3"><global></global></li></ul>
</div></body>
<script>// 创建1个组件对象(全局组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px 10px; border-radius: 5px;margin: 5px 0;">我是全局组件</div><local></local><br></div>`,// 创建1个组件对象(局部组件)components: {local: {template: `<div><div style="background: rgba(104,255,104,0.7); padding: 5px 10px; border-radius: 5px; margin: 3px 50px 3px 0;">我是局部组件</div></div>`,}}})let vm = new Vue({el: '#box',})
</script>
</html>
区别:
1.自定义组件需要有1个 root element
,一般包裹在 1个div
中
2.父子组件的data
是无法共享的
- 这一点就像Docker的容器一样,是相互隔离的
- 就算父子的data中数据相同,拥有相同的方法,也是互不影响的
3.组件可以有data、methods、computed....,但是 data
必须是一个函数
Vue实例:data是1个键值对,用来存放属性的
var vm = new Vue({el: '#box',data: {isShow: true}
})
组件:data是1个函数,需要有返回值(return
)
Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;" @click="handleClick">我是头部组件</div><div v-if="isShow">显示消失</div></div>
`,methods: {handleClick() {console.log('我被点击了')this.isShow = !this.isShow}},data() {return {isShow: true}}
})
三:组件通信
1.父传子
- 在全局组件中自定义属性:
<global :myname="name" :myage="19"></global>
- 在组件中获取:
{{myname}}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><!-- myName是自定义属性 --><global myname="name" myage="18"></global><global :myname="name" :myage="19"></global><global :myname="'Ben'" :myage="20"></global>
</div></body>
<script>// 创建1个组件对象(全局组件/子组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div>{{myname}}{{myage}}</div>`,props: ['myname', 'myage']})// 父组件let vm = new Vue({el: '#box',data: {name: 'darker'},})
</script>
</html>
属性验证
- 限制父传子的变量类型
props: {myname: String,isshow: Boolean
}
- 父传子时候注意以下区别
<global :myname="name" :is_show="'false'"></global>
<global :myname="name" :is_show="false"></global>
<global :myname="name" :is_show="is_show"></global>
- 实例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>组件</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><!-- myName是自定义属性 --><!-- <global :myname="name" :myage="19" :isshow="'false'"></global>--><global :my_name="name" :is_show="is_show"></global><global :my_name="name" :is_show="false"></global>
</div></body>
<script>// 创建1个组件对象(全局组件/子组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;">我是子组件:{{is_show}}</div><span>{{my_name}}</span></div>`,props: {my_name: String,is_show: Boolean}})// 父组件let vm = new Vue({el: '#box',data: {name: 'darker',is_show: true},})
</script>
</html>
2.子传父(通过事件)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>子传父</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><global @my_event="handleClick($event)"></global>
</div></body>
<script>// 创建1个组件对象(全局组件/子组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div><button @click="handleNav">点我</button></div>`,data() {return {name: 'Darker'}},methods: {handleNav() {console.log('我是子组件的函数')this.$emit('my_event', 666, 777, this.name)}}})// 父组件let vm = new Vue({el: '#box',data: {},methods: {handleClick(a,b,c) {console.log('我是父组件的函数')console.log(a)console.log(b)console.log(c)}}})
</script>
</html>
3.子传父(控制子组件的显示和隐藏)
点击子组件,就会触发父组件的某个函数执行
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>子传父</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><global @my_event="handleClick($event)"></global>
</div></body>
<script>// 创建1个组件对象(全局组件/子组件)Vue.component('global', {template: `<div><div style="background: rgba(255,104,104,0.7); padding: 5px;">全局组件/子组件</div><button @click="handleNav">点我</button></div>`,data() {return {name: 'Darker'}},methods: {handleNav() {console.log('我是子组件的函数')this.$emit('my_event', 666, 777, this.name)}}})// 父组件let vm = new Vue({el: '#box',data: {},methods: {handleClick(a,b,c) {console.log('我是父组件的函数')console.log(a)console.log(b)console.log(c)}}})
</script>
</html>
小案例
- 子组件有1个按钮 和 1个输入框,子组件输入完内容后,数据在父组件中展示
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>子传父 小案例</title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body><div id="box"><global @my_event="handleShow($event)"></global><br><div>父组件接收到的数据:{{name}}</div>
</div></body>
<script>// 创建1个组件对象(全局组件/子组件)Vue.component('global', {template: `<div><input type="text" v-model="myText"><button @click="handleClick">点我传数据</button></div>`,data() {return {myText: ''}},methods: {handleClick() {this.$emit('my_event', this.myText)}}})// 父组件let vm = new Vue({el: '#box',data: {name: ''},methods: {handleShow(a) {this.name = a}}})
</script>
</html>