组件化开发
2021/8/11 6:07:18
本文主要是介绍组件化开发,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
目录- 什么是组件化
- Vue组件化思想
- 注册组件的基本步骤
- 全局组件和局部组件
- 父组件和子组件
- 注册组件语法糖
- 组件模板的分离写法
- 组件可以访问Vue示例数据吗?
- 父子组件的通信
- props基本用法
- 从子组件传递给父组件
- 父子组件通信案例
- 父访问子
- 子访问父
什么是组件化
-
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
-
但如果,我们将一个页面拆分成一个个的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
Vue组件化思想
-
提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
-
任何的应用都会被抽象成一棵组件树
注册组件的基本步骤
- 组件的使用分成三个步骤
- 创建组件构造器
- 注册组件
- 使用组件
<div id="app"> // 3. 使用组件 <my-cpn></my-cpn> </div> <script src="../js/vue.js"></script> <script> // 1. 创建组件构造器对象 const contConstructor = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容哈哈哈哈哈</p> <p>我是内容呵呵呵呵呵</p> </div>` }) // 2. 注册组件 // component有两个参数 1-组建的标签名 2-组件构造器 Vue.component('my-cpn', contConstructor) const app = new Vue({ el : "#app", data : { message : "你好", } }) </script>
全局组件和局部组件
全局组件,意味着可以在多个Vue的实例下面使用
上面的例子即是全局组件,验证:
<div id="app"> <my-cpn></my-cpn> <my-cpn></my-cpn> <my-cpn></my-cpn> </div> <div id="ppa"> <my-cpn></my-cpn> </div> <script src="../js/vue.js"></script> <script> // 1. 创建组件构造器对象 const contConstructor = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容哈哈哈哈哈</p> <p>我是内容呵呵呵呵呵</p> </div>` }) // 2. 注册组件 // component有两个参数 1-组建的标签名 2-组件构造器 Vue.component('my-cpn', contConstructor) const ppa = new Vue({ el : '#ppa' }) const app = new Vue({ el : "#app", data : { message : "你好", } }) </script>
局部组件:(开发最常用,而且一般只有一个Vue实例)
<script> // 1. 创建组件构造器对象 const contConstructor = Vue.extend({ template: ` <div> <h2>我是标题</h2> <p>我是内容哈哈哈哈哈</p> <p>我是内容呵呵呵呵呵</p> </div>` }) // 2. 注册组件 // component有两个参数 1-组建的标签名 2-组件构造器 // Vue.component('my-cpn', contConstructor) const ppa = new Vue({ el : '#ppa' }) const app = new Vue({ el : "#app", data : { message : "你好", }, components : { cpn : contConstructor } }) </script>
父组件和子组件
<div id="app"> <cpn2></cpn2> </div> <script src="../js/vue.js"></script> <script> // 子组件 const cpnC1 = Vue.extend({ template : ` <div> <h2>我是标题1</h2> <p>我是内容,哈哈哈</p> </div> ` }) // 父组件 const cpnC2 = Vue.extend({ template : ` <div> <h2>我是标题2</h2> <p>我是内容,呵呵呵</p> <cpn1></cpn1> </div> `, components : { cpn1 : cpnC1 } }) // root组件 const app = new Vue({ el : "#app", data : { message : "你好", }, components : { cpn2 : cpnC2 } }) </script>
注册组件语法糖
<div id="app"> <cpn1></cpn1> <cpn2></cpn2> </div> <script src="../js/vue.js"></script> <script> // 全局组件语法糖 Vue.component('cpn1', { template : ` <div> <h2>我是标题1</h2> <p>我是内容,哈哈哈</p> </div> ` }) const app = new Vue({ el : "#app", data : { message : "你好", }, // 局部组件语法糖 components : { 'cpn2' : { template : ` <div> <h2>我是标题2</h2> <p>我是内容,呵呵呵</p> </div> ` } } }) </script>
组件模板的分离写法
<div id="app"> <cpn1></cpn1> <cpn2></cpn2> </div> <!--1. script标签--> <script type="text/x-template" id="cpn1"> <div> <h2>{{message}}1</h2> <p>我是内容,哈哈哈</p> </div> </script> <!--2.template标签--> <template id="cpn2"> <div> <h2>我是标题2</h2> <p>我是内容,呵呵呵</p> </div> </template> <script src="../js/vue.js"></script> <script> // 全局组件语法糖 Vue.component('cpn1', { template : `#cpn1` }) const app = new Vue({ el : "#app", data : { message : "你好", }, components : { 'cpn2' : { template : `#cpn2` } } }) </script>
组件可以访问Vue示例数据吗?
-
组件是一个单独功能模块的封装:
- 这个模块有属于自己的HTML模板,也应该有属性自己的数据data
-
组件中的数据是保存在哪里?顶层的Vue实例中吗?
- 组件对象也有一个data属性(也可以有methods等属性,下面我们有用到)
- 只是这个data属性必须是一个函数
- 而且这个函数返回一个对象,对象内部保存着数据
对于组件中的data为什么是一个函数,是保证每个组件每次返回都是独立的对象
注:其实组件原型就是指向Vue对象,所以基本上Vue有的组件都有
<div id="app"> <cpn1></cpn1> <cpn2></cpn2> </div> <!--1. script标签--> <script type="text/x-template" id="cpn1"> <div> <h2>{{message1}}1</h2> <p>我是内容,哈哈哈</p> </div> </script> <!--2.template标签--> <template id="cpn2"> <div> <h2>{{message2}}</h2> <p>我是内容,呵呵呵</p> </div> </template> <script src="../js/vue.js"></script> <script> // 全局组件语法糖 Vue.component('cpn1', { template : `#cpn1`, data() { return { message1 : '我是标题1' } } }) const app = new Vue({ el : "#app", data : { message : "你好", }, components : { 'cpn2' : { template : `#cpn2`, data() { return { message2 : '我是标题2' } } } } }) </script>
父子组件的通信
-
子组件是不能引用父组件或者Vue实例的数据的。
-
但是,在开发中,往往一些数据需要从上层传递到下层
-
比如,在一个页面中,我们从服务器请求到了很多的数据。
-
其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
-
这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件将数据传递给小组件。
-
-
如何进行父子组件间的通信?Vue官方提到:
- 通过props向子组件传递数据
- 通过事件向父组件发送消息
props基本用法
-
在组件中,使用选项props来声明需要从父级接收到的数据。
-
props的值有两种方式:
-
方式一:字符串数组,数组中的字符串就是传递时的名称
-
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等。
-
方式一:字符串数组
方式二:对象
一方面明明是一个对象,却传一个数组很奇怪,另一方面当需要对props进行类型等验证时,就需要对象写法了。
<div id="app"> <!--<cpn :cmovies="movies" :cmessage="message" ></cpn>--> <cpn :cmessage="message" ></cpn> </div> <template id="cpn"> <div> <p>{{cmessage}}</p> <ul> <li v-for="item in cmovies"> {{item}} </li> </ul> </div> </template> <script src="../js/vue.js"></script> <script> // 父组件传子组件 props const cpn = { template : `#cpn`, // 1-字符串类型 // props : ['cmovies', 'cmessage'] // 2-对象类型 props : { // 1. 类型限制 // cmovies : Array, cmessage : String // 2. 类型限制+默认值 cmovies : { type : Array, // default : [] 如果是Array类型,或Object类型,默认值必须给一个工厂方法 default() { return [] } }, cmessage : { type : String, default: '我不想看', required : true // 动态绑定处为必传项 } } } const app = new Vue({ el : "#app", data : { message : '我要去看', movies : ['海王', '海贼王', '海尔兄弟'] }, components : { cpn } }) </script>
·注意:当在props中使用驼峰命名法的时候,在动态绑定父类对象的时候一定用’-‘连接·
<div id="app"> <cpn :c-info="info" :child-my-message="message"></cpn></div><template id="cpn"> <div> <h2>{{cInfo}}</h2> <h2>{{childMyMessage}}</h2> </div></template>
在props中定义为cInfo,childMyMessage
从子组件传递给父组件
-
通常是子组件中产生一些事件,希望父组件知道,这时需要使用自定义事件来完成。
-
v-on不仅可以用于监听DOM事件,也可用于组件间的自定义事件。
-
在子组件中,通过$emit()来触发事件
-
在父组件中,通过v-on来监听子组件事件
-
<div id="app"> <cpn @itemclick="cpnClick"></cpn> </div> <template id="cpn"> <div> <ul> <li v-for="item in categories"> <button @click="btnClick(item)">{{item.name}}</button> </li> </ul> </div> </template> <script src="../js/vue.js"></script> <script> const cpn = { template : `#cpn`, data() { return { categories: [ {id : 1, name : '热门推荐'}, {id : 2, name : '手机数码'}, {id : 3, name : '家用家电'}, {id : 4, name : '电脑办公'} ] } }, methods : { btnClick(item) { console.log(item.name); this.$emit('itemclick', item) } } } const app = new Vue({ el : "#app", data : { info : { name : 'lidx', age : 25, height : 1.88 }, message : '你好' }, methods : { cpnClick(item) { console.log('父组件'+item.name); } }, components : { cpn } }) </script>
父子组件通信案例
要求实现:
- 改变子组件中的数字,让父组件中的值改变
- 让子组件一中的值永远是子组件二中的值的100倍
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="app"> <h2>父{{num1}}</h2> <h2>父{{num2}}</h2> <cpn :number1="num1" :number2="num2" @num1change="num1haschange" @num2change="num2haschange"></cpn> </div> <template id="cpn"> <div> <h2>props:{{number1}}</h2> <h2>data:{{dnumber1}}</h2> <input type="text" v-model="dnumber1"> <!--<input type="text" :value="dnumber1" @input="num1input">--> <h2>props:{{number2}}</h2> <h2>data:{{dnumber2}}</h2> <input type="text" v-model="dnumber2"> <!--<input type="text" :value="dnumber2" @input="num2input">--> </div> </template> <script src="../js/vue.js"></script> <script> const app = new Vue({ el : "#app", data : { num1 : 1, num2 : 2 }, methods : { num1haschange (value) { this.num1 = parseInt(value) }, num2haschange (value) { this.num2 = parseInt(value) } }, components : { cpn : { template : `#cpn`, props : { number1 : { type : Number }, number2 : { type : Number } }, data () { return { dnumber1 : this.number1, dnumber2 : this.number2 } }, watch : { dnumber1(newValue) { this.dnumber2 = newValue * 100 this.$emit('num1change', newValue) }, dnumber2(newValue) { this.dnumber1 = newValue / 100 this.$emit('num2change', newValue) } } /*methods : { num1input ( event ) { this.dnumber1 = event.target.value this.$emit('num1change', this.dnumber1) this.dnumber2 = this.dnumber1 * 100 this.$emit('num2change', this.dnumber2) }, num2input (event) { this.dnumber2 = event.target.value this.$emit('num2change', this.dnumber2) this.dnumber1 = this.dnumber2 / 100 this.$emit('num1change', this.dnumber1) } }*/ } } }) </script> </body> </html>
watch:检测对象的变化
父访问子
两种方式:
- 下标值(不推荐)$children==》数组,获取所有子组件
- 起别名 $refs==》对象,获取有ref属性的子组件
<div id="app"> <cpn ref="cpn1"></cpn> <button @click="btnClick">按钮</button> </div> <template id="cpn"> <div>我是子组件</div> </template> <script src="../js/vue.js"></script> <script> const app = new Vue({ el : "#app", data : { }, methods : { btnClick() { console.log(this.$children[0].name); console.log(this.$children); // 方式一,获取所有子组件 this.$children[0].showMessage() // 方式一,执行子组件方法 console.log(this.$refs.cpn1.name); console.log(this.$refs); // 方式二,获取所有有ref属性的子组件 this.$refs.cpn1.showMessage() // 方式二,执行子组件方法 } }, components : { cpn : { template : `#cpn`, data() { return { name : 'cpn' } }, methods : { showMessage() { console.log("showMessage()"); } } } } }) </script>
子访问父
开发当中不常用,也有两种
- $parent,访问上一级组件
- $root,访问根组件
<div id="app"> <parentcpn></parentcpn> </div> <template id="cpn"> <div> <h2>我是子组件</h2> <button @click="btnClick">按钮</button> </div> </template> <tempalte id="cpn_parent"> <div> <h2>二级组件</h2> <cpn></cpn> </div> </tempalte> <script src="../js/vue.js"></script> <script> const app = new Vue({ el : "#app", data : { message : "你好", }, methods : { showMessage2() { console.log('我是父组件Vue的方法'); } }, components : { parentcpn : { template : `#cpn_parent`, methods : { showMessage1() { console.log('我是二级组件的方法'); } }, components: { cpn : { template : `#cpn`, methods : { btnClick() { console.log(this.$parent); console.log(this.$root); console.log('我是子组件的方法'); this.$parent.showMessage1() this.$root.showMessage2() } } } } } } }) </script>
这篇关于组件化开发的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24Java中定时任务实现方式及源码剖析
- 2024-11-24鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
- 2024-11-24细说敏捷:敏捷四会之每日站会
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解