组件化开发
作者:互联网
什么是组件化
-
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
-
但如果,我们将一个页面拆分成一个个的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
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>
标签:Vue,const,cpn,app,开发,组件,data 来源: https://www.cnblogs.com/coderElian/p/15126499.html