组件化
(重点)Vue组件化开发
1、什么是组件化?
面对复杂问题的处理方式,把问题拆解成很多个能处理的小问题,再将其放在整体中,会发现大的问题也会迎刃而解。
- 组件化开发的优势:可维护性高 可复用性高
Vue组件化思想
- 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
- 任何的应用都会被抽象成一颗组件树。
2、全局组件
通过Vue.component('组件名称', {}),通过这个方法注册的都是全局组件,也就是他们再注册之后可以用在任何新创建的Vue 实例挂载的区域内。
<body>
<div id="app">
<my-con></my-con>
<div>
<my-con></my-con>
</div>
</div>
<my-con></my-con>
</body>
<script>
Vue.component('my-con', {
template: '<section><h3>组件标题</h3><p>组件内容</p></section>'
})
const vm = new Vue({
el: '#app'
})
</script>
3、局部组件
通过 Vue.component 方式注册的组件,称之为全局组件。任何地方都可以使用。全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
注册局部组件
<body>
<div id="app">
<my-con></my-con>
<div>
<my-con></my-con>
</div>
</div>
<div id="app1">
<my-con1></my-con1>
</div>
</body>
<template id="template1">
<section>
<h3>组件标题</h3>
<p>组件内容</p>
</section>
</template>
<template id="template2">
<section>
<h3>组件标题B</h3>
<p>组件内容B</p>
</section>
</template>
<script>
var componentA = {
template: '#template1'
}
var componentB = {
template: '#template2'
}
const vm = new Vue({
el: '#app',
components: {
'my-con': componentA
}
})
const vm1 = new Vue({
el: '#app1',
components: {
'my-con1': componentB
}
})
</script>
父组件和子组件
组件和组件之间存在层级关系,而其中一种最重要的关系就是父子组件关系。
注意: 父组件中定义了title属性,子组件是不能使用的
那组件如果要使用data定义自己属性保存数据要怎么做呢?
- 组件对象也有一个data的属性(也有methods等属性,下面我们有用到)
- 只是这个data属性必须是一个函数,而且函数返回一个对象 ,对象保存着数据
为什么data在组件中必须是一个函数呢?
原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响。
父子组件间的通讯
父级向子级传递
在组件中,使用选项props来声明需要从父级接收到的数据。
props的值有两种方式:
- 字符串数组,数组中的字符串就是传递时的名称。
- 对象,对象可以设置传递时的类型(String,Number,Boolean,Array, Object,Date,Function,Symbol),也可以设置默认值等。
<div id='app'>
<!-- 1 在父组件中,调用子组件的时候,通过标签属性的方式传入子组件内部-->
<child :num = "fatherNum"></child>
</div>
<template id="tmpl">
<div>
<!-- 3 在子组件中 使用这个数据 -->
<p>{{ num }}</p>
</div>
</template>
<script>
let child = {
template:"#tmpl",
// 2 在子组件中,接收传进来的num属性
props:["num"]
}
new Vue({
el:'#app',
data:{
fatherNum:20
},
components:{
child
}
})
</script>
子级向父级传递
父组件向子组件传递数据,通过自定义事件
<div id='app'>
<p>父组件中的fatherNum为:{{fatherNum}}</p>
<!-- 2 在父组件中,调用子组件的时候, 通过自定义事件的方式,定义事件函数 -->
<child :num="fatherNum" @fn="chanFatherNum"></child>
</div>
<template id="tmpl">
<div>
<p>{{num}}</p>
<button @click="add">按钮</button>
</div>
</template>
<script>
// 单向数据流 父 -> 子 , 子组件无法直接修改父组件数据
let child = {
template:"#tmpl",
props:["num"],
data(){
return{
step:10
}
},
methods:{
add(){
// 3 在子组件中,触发自定义事件,从而执行chanFatherNum这个函数
// $emit(事件名,参数) 专门用来触发自定义事件
this.$emit("fn", this.step)
}
}
}
new Vue({
el:'#app',
data:{
fatherNum:20
},
components:{
child
},
// 1 在父组件中,准备一个修改父组件数据的方法
methods:{
chanFatherNum(val){
this.fatherNum+=val
}
}
})
总结:
什么时候用父传子? 子组件中想要用父组件的数据
什么时候用子传父? 子组件中修改父组件数据的时候
非父子组件通讯
这个之后的vuex会涉及,暂时先不提
实际工作中如果遇到跨组件或者非父组件间的传递数据,那该怎么办?第一个可以使用中央事件总线,也就是一个中介来完成。第二个就是使用
Vuex提供的功能,学习Vuex之后再进行讨论。