Java教程

组件化开发

本文主要是介绍组件化开发,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录
  • 什么是组件化
  • 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>

父子组件通信案例

要求实现:

  1. 改变子组件中的数字,让父组件中的值改变
  2. 让子组件一中的值永远是子组件二中的值的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:检测对象的变化

父访问子

两种方式:

  1. 下标值(不推荐)$children==》数组,获取所有子组件
  2. 起别名 $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>

子访问父

开发当中不常用,也有两种

  1. $parent,访问上一级组件
  2. $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>
这篇关于组件化开发的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!