Vue(六)封装组件、组件化开发、组件间传值
目录
一、组件
组件是拥有专属的 HTML+JS+CSS+数据 的可重用的独立的页面功能区域,如果发现网页中有一个功能,可能被多处反复使用,都应封装为组件。
1. 封装组件
(1)创建一个组件
-
Vue.component("组件名",{
-
template:`组件的HTML片段`,
-
data(){
-
return { //相当于之前的data
-
模型变量:值,
-
... ...
-
}
-
},
-
-
//注意:
-
//组件中不再有el:"#app",而是用template:``代替
-
//data不再写对象格式,而是写为函数格式且必须return一个新对象{}
-
//HTML片段仍需写在唯一的父元素中
(2)在页面中使用组件
-
<组件名></组件名>
-
-
<!-- 每个自定义组件其实就是一个自定义的HTML标签而已 -->
每个组件内都是一个缩微的小 new Vue(),所以 new Vue() 中有什么,组件中也应该有什么如:methods:{ ... }、watch:{ ... }、computed:{ ... }、八个生命周期钩子函数等。
2. 组件原理
每当 new Vue() 扫描到一个不认识的标签时,都会去内存中的 vue 类型中找有没有同名的组件,如果找到同名的 vue 组件,就会做三件事:
(1)复制组件 template 中的 HTML 片段代替页面上<组件></组件>标签位置;
(2)自动调用 data() 函数,返回一个新创建的模型对象,其中包含当前组件专属的模型变量;
(3)自动为当前组件区域创建一个缩微版的 new Vue(),j监控该区域。
举例:封装一个计数器组件;
-
<body>
-
<div id="app">
-
<ul>
-
<li>
-
<my-counter></my-counter>
-
</li>
-
<li>
-
<my-counter></my-counter>
-
</li>
-
<li>
-
<my-counter></my-counter>
-
</li>
-
<li>
-
<my-counter></my-counter>
-
</li>
-
</ul>
-
</div>
-
<script>
-
//做一个组件和做new Vue()完全一样:3步
-
Vue.component("my-counter", {
-
//1. 做界面:template里
-
//1.1 唯一父元素
-
//1.2 查找可能发生变化的位置
-
//1.3 触发事件的元素
-
template: `
-
<div>
-
<button @click="minus">-</button>
-
<span>{{n}}</span>
-
<button @click="add">+</button>
-
</div>
-
`,
-
//2. 创建模型对象
-
//2.1 创建data:必须是函数——为了反复调用
-
data() {
-
return {
-
n: 0
-
}
-
},
-
//2.2 创建methods
-
methods: {
-
add() {
-
this.n++
-
},
-
minus() {
-
if (this.n > 0) {
-
this.n--
-
}
-
}
-
}
-
})
-
new Vue({
-
el: "#app"
-
})
-
</script>
-
</body>
效果如下:
为什么组件的data必须是一个函数(高频笔试面试):
可反复调用;
反复创建新对象;
避免组件间数据冲突。
二、组件化开发
前端一个页面的功能和代码量越来越多,但是操作系统是禁止多人协作编写一个文件的。组件化就是将一个大的页面,划分为多个组件区域,分别保存在不同的文件中,由多人协作开发。最后运行时,还能合并在一个页面中运行。
使用组件进行开发便于多人协作,提高开发效率;松耦合,一人出错,不会影响全局。
1. 组件的使用过程
(1)每当拿到一个页面后,先划分组件区域,根据3个原则:位置、功能、是否重用;
(2)为每个组件创建独立的js文件,来保存组件的代码;
(3)回到原页面中引入并使用组件标签,将组件重新拼接回一个完整的页面。
2. 组件分类(vue三大组件)
(1)根组件 new Vue()
整个页面甚至整个项目只有一个 new Vue() 监控全局。
(2)全局组件 Vue.component()
可放在任何位置,没有限制。
(3)子组件
规定只能在指定父组件范围内使用的组件。子组件的创建及使用如下:
a. 只创建一个普通的 js 对象,保存组件的内容;
var 子组件对象名={ 组件内容 }
b. 为父组件添加新成员 components;
-
父组件:{
-
... : ...,
-
components:{ 子组件对象名, ... , }
-
}
c. 在父组件界面中
<子组件标签名></子组件标签名>
举例: 实现待办事项列表的界面部分划分组件;
组件todo.js
-
Vue.component("todo", {
-
template: `
-
<div>
-
<h3>待办事项列表</h3>
-
<todo-add></todo-add>
-
<todo-list></todo-list>
-
</div>
-
`,
-
components: {
-
todoAdd, //vue自动将其翻译为todo-add
-
todoList //vue自动将其翻译为todo-list
-
}
-
})
组件todoAdd.js
-
var todoAdd = {
-
template: `
-
<div>
-
<input><button>+</button>
-
</div>
-
`
-
}
组件todoList.js
-
var todoList = {
-
template: `
-
<ul>
-
<todo-item></todo-item>
-
<todo-item></todo-item>
-
<todo-item></todo-item>
-
<todo-item></todo-item>
-
<todo-item></todo-item>
-
</ul>
-
`,
-
components: {
-
todoItem //vue将其自动翻译为todo-item
-
}
-
}
组件todoItem.js
-
var todoItem = {
-
template: `
-
<span>
-
<li>1 - 吃饭 <a href="javascript:;">×</a></li>
-
<span>
-
`
-
}
首页index.html
-
<!DOCTYPE html>
-
<html lang="en">
-
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<title>Document</title>
-
<script src="js/vue.js"></script>
-
<script src="todoItem.js"></script>
-
<script src="todoList.js"></script>
-
<script src="todoAdd.js"></script>
-
<script src="todo.js"></script>
-
</head>
-
-
<body>
-
<div id="app">
-
<todo></todo>
-
</div>
-
<script>
-
new Vue({
-
el: "#app"
-
})
-
</script>
-
</body>
-
-
</html>
效果如下:
3. 组件间传值——父给子传值
-
//1.父给子:
-
父组件:{
-
template:`
-
<子组件标签 :自定义属性名="父组件的变量">
-
`
-
-
//2.子组件接收属性值:
-
子组件对象:{
-
props:[ "自定义属性名" ]
-
}
-
-
//在子组件内,props中的属性用法和data中的变量用法完全一样
-
//差别在于props的属性值来自于外部传入,data中的变量值由自己定义
举例:使用父给子传值,实现待办事项列表功能;
组件todo.js
-
Vue.component("todo", {
-
template: `
-
<div>
-
<h3>待办事项列表</h3>
-
<todo-add :tasks="tasks"></todo-add>
-
<todo-list :tasks="tasks"></todo-list>
-
</div>
-
`,
-
data() {
-
return {
-
tasks: ["踢足球", "玩游戏", "看电视"]
-
}
-
},
-
components: {
-
todoAdd, //vue自动将其翻译为todo-add
-
todoList //vue自动将其翻译为todo-list
-
}
-
})
组件todoAdd.js
-
var todoAdd = {
-
props: ["tasks"],
-
template: `
-
<div>
-
<input v-model="t"><button @click="add">+</button>
-
</div>
-
`,
-
methods: {
-
add() {
-
this.tasks.push(this.t);
-
this.t = ""
-
}
-
}
-
}
组件todoList.js
-
var todoList = {
-
props: ["tasks"],
-
template: `
-
<ul>
-
<li v-for="(t,i) of tasks" :key="i">
-
<todo-item :t="t" :i="i" :tasks="tasks"></todo-item>
-
</li>
-
</ul>
-
`,
-
components: {
-
todoItem //vue将其自动翻译为todo-item
-
}
-
}
组件todoItem.js
-
var todoItem = {
-
props: ["t", "i", "tasks"],
-
template: `
-
<span>
-
<li>{{i+1}} - {{t}} <a href="javascript:;" @click="del">×</a></li>
-
<span>
-
`,
-
methods: {
-
del() {
-
// 从数组中删除一个元素
-
this.tasks.splice(this.i, 1)
-
}
-
}
-
}
首页index.html
-
<!DOCTYPE html>
-
<html lang="en">
-
-
<head>
-
<meta charset="UTF-8">
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
-
<title>Document</title>
-
<script src="js/vue.js"></script>
-
<script src="todoItem.js"></script>
-
<script src="todoList.js"></script>
-
<script src="todoAdd.js"></script>
-
<script src="todo.js"></script>
-
</head>
-
-
<body>
-
<div id="app">
-
<todo></todo>
-
</div>
-
<script>
-
new Vue({
-
el: "#app"
-
})
-
</script>
-
</body>
-
-
</html>
效果如下:
初始页,
删除,
添加,
文章来源: majinjian.blog.csdn.net,作者:Developer 小马,版权归原作者所有,如需转载,请联系作者。
原文链接:majinjian.blog.csdn.net/article/details/120365513
- 点赞
- 收藏
- 关注作者
评论(0)