Vue全家桶之组件化开发
Posted 前端加油
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue全家桶之组件化开发相关的知识,希望对你有一定的参考价值。
Vue全家桶之组件化开发
文章目录
1. 组件化开发思想
组件
是可复用的 Vue 实例, 把一些公共的模块抽取出来,然后写成单独的的工具组件或者页面,在需要的页面中就直接引入即可,那么我们可以将其抽出为一个组件进行复用,提高了代码的复用率
组件化开发思想
:如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。
- 我们将一个完整的页面分成很多个组件。
- 每个组件都用于实现页面的一个功能块。
- 而每一个组件又可以进行细分。
组件化思想的应用
:
- 有了组件化的思想,我们在之后的开发中就要充分的利用它。
- 尽可能的将页面拆分成一个个小的、可复用的组件。
- 这样让我们的代码更加方便组织和管理,并且扩展性也更强。
2. 组件的注册
2.1 全局组件注册语法
使用Vue.component('button-counter', cpnc)
方式注册,直接使用<button-counter></button-counter>
调用。button-counter
是全局组件的名字,cpnc
是定义的组件对象。
Vue.component("button-counter", {
data: 组件数据,
template: 组件模块内容
});
//注册一个名为button-counter 的新组件
Vue.component("button-counter", {
data: function () {
return {
count: 0,
};
},
template: '<button @click="count++">点击{{count}}次</button>',
});
2.2 组件用法
<div id="app">
<!-- 组件的使用 -->
<button-counter></button-counter>
<button-counter></button-counter>
</div>
//1-组件的基本使用.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<div id="app">
<!-- 全局组件的使用 -->
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
//全局组件的注册
Vue.component("button-counter", {
data: function () {
return {
count: 0,
};
},
template: `
<div>
<button @click="handle">点击了{{count}}次</button>
</div>
`,
});
const app = new Vue({
el: "#app",
data: {},
methods: {},
});
</script>
</body>
</html>
2.3 组件注册注意事项
-
data必须是一个函数
保证每个模板的数据是相互独立的
-
组件模板内容必须是单个跟元素
只能有一个父元素,如上面代码中的div
-
组件模板内容可以是模板字符串``
ES6 引入新的声明字符串的方式 ``
-
组件命名方式
短横线方式 my-component (推荐)
驼峰方式 MyComponent
2.4 局部组件注册
局部组件
,只能在当前vue实例挂载的对象中使用,类似于局部变量,有块级作用域。
//注册方式
const app = new Vue({
el:"#app",
components:{//局部组件创建
'hello-world': HelloWorld
}
})
使用方式与全局变量一样,直接使用<hello-world></hello-world>
调用。 'hello-world’组件命名的名字,HelloWorld定义的组件对象。
//04-局部组件用法.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<hello-world></hello-world>
</div>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
var HelloWorld = {
data: function () {
return {
msg: 'helloworld'
}
},
template: `
<div>{{msg}}</div>
`
}
const app = new Vue({
el: "#app",
data: {},
components: {
'hello-world': HelloWorld
}
})
</script>
</body>
</html>
3. 组件间数据交互
3.1 父组件向子组件传值props
1.子组件内部通过props接收父组件传递过来的值
props传递数据原则:单向数据流,只能父传子
v-bind是不支持使用驼峰标识的,例如cUser
要改成c-User
。
Vue.component(‘menu-item',{
//props接受父组件传递的数据
props: ['title'],
template: '<div>{{ title }}</div>'
})
2.父组件通过属性将值传递给子组件
//传统方式
<menu-item title="来自父组件的数据"></menu-item>
//动态绑定
<menu-item :title="title"></menu-item>
//07-父组件向子组件传值-props命名规则.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<div>{{pmsg}}</div>
//传统方式
<menu-item title='来自父组件的值'></menu-item>
//动态绑定
<menu-item :title='ptitle' content='hello'></menu-item>
</div>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
//相对于Vue实例为子组件
Vue.component('menu-item', {
//props接受父组件传递的数据
props: ['title', 'content'],
data: function () {
return {
msg: '子组件本身的数据'
}
},
template: `
<div>{{msg + '-----' +title + '-----' +content}}</div>
`
})
//Vue实例为根组件
const app = new Vue({
el: "#app",
data: {
pmsg: "父组件中内容",
ptitle: '动态绑定的值'
}
})
</script>
</body>
</html>
3.props属性名规则
-
在props中使用驼峰形式,在html中需要使用短横线的形式
-
字符串形式的模板中没有这个限制
Vue.component(‘menu-item', { // 在JavaScript中是驼峰式的 props: ['menuTitle'], template: '<div>{{ menuTitle }}</div>' }) //在html中是短横线方式的 <menu-item menu-title=“nihao"></menu-item>
4.props属性值类型
-
字符串String
-
数值Number
-
布尔值Boolean
-
数组Array
-
对象Object
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="app"> <div>{{pmsg}}</div> //字符串 数字 布尔类型 数组 对象 <menu-item :pstr='pstr' :pnum='12' pboo='true' :parr='parr' :pobj='pobj'></menu-item> </div> <script type="text/javascript" src="js/vue.js"></script> <script type="text/javascript"> Vue.component('menu-item', { props: ['pstr','pnum','pboo','parr','pobj'], template: ` <div> <div>{{pstr}}</div> <div>{{12 + pnum}}</div> <div>{{typeof pboo}}</div> <ul> <li :key='index' v-for='(item,index) in parr'>{{item}}</li> </ul> <span>{{pobj.name}}</span> <span>{{pobj.age}}</span> </div> </div> ` }); var vm = new Vue({ el: '#app', data: { pmsg: '父组件中内容', pstr: 'hello', parr: ['apple','orange','banana'], pobj: { name: 'lisi', age: 12 } } }); </script> </body> </html>
3.2 子组件向父组件传值$emit
1.子组件通过自定义事件向父组件传递信息
子组件向父组件传值,使用自定义事件$emit
。$emit(自定义事件名称)
<button @click='$emit("enlarge-text")'>扩大父组件字体</button>
2.在父组件中监听子组件的事件
<menu-item @enlarge-text='handle'></menu-item>
//09-子组件向父组件传值.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<!-- 整个app为父组件 -->
<div id="app">
<div :style='{fontSize:fontsize+"px"}'>{{msg}}</div>
<!-- 在父组件中监听子组件事件 -->
<menu-item @enlarge-text='handle'></menu-item>
</div>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
//子组件点击按钮控制父组件字体大小
//创建子组件
Vue.component('menu-item', {
template: `
<button @click='$emit("enlarge-text")'>扩大父组件字体</button>
`
})
const app = new Vue({
el: "#app",
data: {
msg: '父组件中的内容',
fontsize: 10
},
methods: {
handle: function () {
this.fontsize += 5;
}
}
})
</script>
</body>
</html>
3.子组件通过自定义事件向父组件传递信息,携带额外的值
5为另外额外的值
<button @click='$emit("enlarge-text", 5)'>扩大父组件中字体大小</button>
4.父组件监听子组件的事件
通过$event接受额外的值
<menu-item @enlarge-text='handle($event)'></menu-item>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<div :style='{fontSize:fontsize+"px"}'>{{msg}}</div>
<menu-item @enlarge-text='handle($event)'></menu-item>
</div>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
Vue.component('menu-item', {
template: `
<button @click='$emit("enlarge-text",5)'>扩大父组件字体</button>
`
})
const app = new Vue({
el: "#app",
data: {
msg: '父组件中的内容',
fontsize: 10
},
methods: {
handle: function (val) {
this.fontsize += val;
}
}
})
</script>
</body>
</html>
3.3 非父子组件间传值
1.单独的事件中心管理组件间的通信
var eventHub = new Vue()
2.监听事件与销毁事件
$on用于监听事件,add-todo为事件名称,addTodo为事件函数
$off用于销毁事件
eventHub.$on('add-todo', addTodo)
eventHub.$off('add-todo')
3.触发事件
$emit用于触发事件,add-todo为事件名称, id为携带参数
eventHub.$emit(‘add-todo', id)
//11-兄弟组件之间数据交互.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app">
<div>父组件</div>
<div>
<button @click='handle'>销毁事件</button>
</div>
<test-tom></test-tom>
<test-jerry></test-jerry>
</div>
<script type='text/javascript' src='js/vue.js'></script>
<script type='text/javascript'>
//提供事件中心
var hub = new Vue()
Vue.component('test-tom', {
data: function () {
return {
num: 0
}
},
template: `
<div>
<div>Tom:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function () {
//触发兄弟组件的事件
hub.$emit('jerry-event', 2)
}
},
mounted: function () {
//监听事件
hub.$on('tom-event', val => {
this.num += val;
})
}
})
Vue.component('test-jerry', {
data: function () {
return {
num: 0
}
},
template: `
<div>
<div>Jerry:{{num}}</div>
<div>
<button @click='handle'>点击</button>
</div>
</div>
`,
methods: {
handle: function () {
//触发兄弟组件的事件
hub.$emit('tom-event', 1)
}
},
mounted: function () {
//监听事件
hub.$on('jerry-event', val => {
this.num += val;
})
}
})
const app = new Vue({
el: "#app",
data: {},
methods: {
handle: function () {
//销毁事件
hub.$off('tom-event');
hub.$off('jerry-event')
}
}
})
</script>
</body>
</html>
4. 组件插槽
4.1 组件插槽的作用
编译作用域
:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
插槽的目的是让我们原来的设备具备更多的扩展性。比如电脑的USB我们可以插入U盘、硬盘、手机、音响、键盘、鼠标等等。
组件的插槽
是为了让我们封装的组件更加具有扩展性,让使用者可以决定组件内部的一些内容到底展示什么。
组件插槽的作用
:父组件向子组件传递内容
4.2 组件插槽基本用法
在子组件中,使用特殊的元素<slot>
就可以为子组件开启一个插槽。
该插槽插入什么内容取决于父组件如何使用。
如何封装合适呢?
抽取共性,保留不同。最好的封装方式就是将共性抽取到组件中,将不同预留为插槽。
1.插槽位置
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
2.插槽内容
<alert-box>Something had happened.</alert-box>
//12-插槽基本用法.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<alert-box>有bug发生</alert-box>
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
Vue.component('alert-box', {
template: `
<div>
<strong>ERROR:</strong>
<slot>默认内容</slot>
</div>
`
});
var vm =以上是关于Vue全家桶之组件化开发的主要内容,如果未能解决你的问题,请参考以下文章