组件化开发:
1. 问题: 使用Vue.component()创建的组件,可在程序的任何位置使用,毫无限制!
2. 原因: Vue.component()创建的组件,叫全局组件!可以在项目的任何位置随意使用的组件。
3. Vue中共包括3种组件:
(1). new Vue() —— 根组件,一个页面甚至一个项目中只有一个根组件!
(2). Vue.component() —— 全局组件,如果我们希望一个功能可以在程序的任何页面,任何位置都能使用时,就创建全局组件!
(3). 子组件:
a. 什么是: 被限制只能在父组件内使用的组件。超出父组件使用子组件,会报错!
b. 何时: 如果我们希望一个组件,只能在它的父组件下使用时,出了父组件不能用时,就创建子组件
c. 如何: 3步:
1). 先创建一个子组件对象: 2个特点:
i. 其实就是一个普通的js对象: var 子组件对象名={}
ii. 但是子组件对象的内容和Vue.component()创建的组件的内容要求完全一样:
//驼峰
var 子组件对象名={
template:`<唯一父元素>
子组件的HTML内容
</唯一父元素>`,
data(){
return {
变量:值,
... : ...
}
},
//其余和new Vue()完全一样!
}
2). 在子组件的父组件对象中添加新的components成员:
父组件对象:{
template:`...`,
data(){ return { ... } },
methods:{ ... },
... ...,
components:{
子组件对象名, ... ...
//驼峰
}
}
3). 在父组件的template中,就可使用子组件标签名,引入子组件内容
父组件对象:{
template:`<唯一父元素>
... ...
<!-- -分割 -->
<子组件标签名></子组件标签名>
... ...
</唯一父元素>`,
... ...,
components:{
子组件对象名, ... ...
}
}
d. 子组件的命名: 比如: todo-item
1). 创建子组件对象时: var todoItem={ todo-item的内容 } //在js里
2). 在父组件components中引入子组件时: components:{ todoItem }
强调: components知道在HTML内容中不能使用驼峰命名,所以components会自动将子组件对象的驼峰命名,翻译为-分割:
todoItem ->翻译为-> <todo-item>
3). 在父组件template中使用子组件标签时:
template:`<唯一父元素>
<todo-item></todo-item>
</唯一父元素>`
- 总结: 所以如果限制一个组件只能在其父组件内使用时,都要创建为子组件。
- 示例: 使用子组件限制组件不能超出其父组件范围使用
1_todo/todo.js
Vue.component("todo",{
template:`<div>
<h3>待办实现列表</h3>
<todo-add></todo-add>
<todo-list></todo-list>
</div>`,
components:{
todoAdd, todoList
}
})
1_todo/todo-add.js
var todoAdd={
template:`<div>
<input><button>+</button>
</div>`
};
var todoList={1_todo/todo-list.js
template:`<ul>
<todo-item></todo-item>
<todo-item></todo-item>
<todo-item></todo-item>
</ul>`,
components:{
todoItem
}
};
1_todo/todo-item.js
var todoItem={
template:`<li>
1 - 吃饭 <a href="javascript:;">×</a>
</li>`
};
1_todo/todo.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="todo-add.js"></script>
<script src="todo-item.js"></script>
<script src="todo-list.js">
//components:{ todoItem }
//子组件必须放在父组件之前
</script>
<script src="todo.js">
//components:{ todoAdd, todoList }
//子组件必须放在父组件之前引入!
</script>
</head>
<body>
<div id="app">
<todo></todo>
<!--尝试在todo外使用todoList的子组件todoItem,结果报错!-->
<!-- <todo-item></todo-item> -->
</div>
<script>
new Vue({
el:"#app"
})
</script>
</body>
</html>
运行结果:
2. 组件间传值:(父给子)
(1). 问题:Vue中子组件无权直接使用父组件中的模型变量!
(2). 原因: Vue中每个子组件都是一个完全独立的封闭的个体!互不干扰!内部的数据都是专属的!
(3). 解决: 其实,Vue中提供了从父组件,向子组件传值的途径!今后,只要子组件想使用组件中的成员,都可请父组件传过来!
(4). 如何: 2步:
a. 父给:
父组件对象:{
template:...<子组件 :自定义属性名="父组件中的模型变量"></子组件>
} 为子组件添加一个自定义属性,用":"将父组件的模型变量保存进自定义属性
b. 子接:
子组件对象:{
props:[“自定义属性名”]
//props: 从子组件身上获取指定名称的自定义属性值
//props中获得的自定义属性名用法的data中的变量用法完全一样!
}
(5). 示例: 使用父给子传参为待办事项列表绑定数据
2_todo/todo.js
Vue.component("todo",{
template:`<div>
<h3>待办实现列表</h3>
<todo-add></todo-add>
<!--因为list需要tasks数组,所以父组件就将tasks数组放在todo-list组件的tasks属性中-->
<todo-list :tasks="tasks"></todo-list>
</div>`,
components:{
todoAdd, todoList
},
data(){
return {
tasks:["吃饭","睡觉","打亮亮"]
}
}
})
2_todo/todo-add.js:
var todoList={
template:`<ul>
<!--就可以使用父组件传来的tasks数组-->
<todo-item v-for="(t,i) of tasks" :key="i" :t="t" :i="i"></todo-item>
</ul>`,
//因为list中需要用到父组件放入tasks属性中的数组,所以
props:[ "tasks" ],
components:{
todoItem
}
};
2_todo/todo-item.js
var todoItem={
props:["t", "i"],
template:`<li>
{{i+1}} - {{t}} <a href="javascript:;">×</a>
</li>`
};
2_todo/todo.html
<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="todo-add.js"></script>
<script src="todo-item.js"></script>
<script src="todo-list.js">
//components:{ todoItem }
//子组件必须放在父组件之前
</script>
<script src="todo.js">
//components:{ todoAdd, todoList }
//子组件必须放在父组件之前引入!
</script>
</head>
<body>
<div id="app">
<todo></todo>
<!--尝试在todo外使用todoList的子组件todoItem,结果报错!-->
<!-- <todo-item></todo-item> -->
</div>
<script>
new Vue({
el:"#app"
})
</script>
</body>
运行结果:
总结:
只要希望重用一块独立的功能区域就用组件:
(1). 定义组件
Vue.component(组件标签名
,{
template:HTML内容片段
,
data(){ return { 变量 } },
//其余和new Vue()完全相同
})
(2). 在HTML中使用自定义组件
<组件标签名/>或双标记也行
(3). 原理: new Vue()扫描到自定义组件标签,
a.组件的template中的HTML内容代替页面中<组件标签>位置。
b. 并为这个小区域专门创建一个缩微版的vue类型对象。
1). 调用组件的data()函数为当前组件副本创建一个专属数据对象副本。
2). 引入组件对象中的methods等其他内容到当前组件对象副本中
9. 组件化开发:
(1). 步骤:
a. 拿到页面先划分功能区域
1). 从上到下,按功能不同划分区域
2). 按是否重用划分
b. 为每个组件创建独立的.js文件,其中包含一个组件对象及其内容
c. 将所有组件引入唯一完整的html页面中,并在
(2). 运行时:
a. new Vue()扫描
b. 父组件扫描自己内部的template内容,创建并替换子组件
(3). 三种组件:
a. 根组件: new Vue()
b. 全局组件: Vue.component(…)
c. 子组件: 3步
1). var 子组件对象名={
内容必须符合组件的要求
}
子组件对象名必须是驼峰命名
2). 父组件对象中:{
… …
components: { 子组件对象名, … ,… }
}
子组件对象名必须是驼峰命名
3). 父组件template中用<子组件标签名/>引入子组件内容
components会将子组件对象名的驼峰命名自动翻译为-分隔
所以, 使用子组件标签时,要用-分隔多个单词
(4). 组件间传参: 父给子
a. 父组件给:
<子组件 :自定义属性名=“父组件变量”>
b. 子组件取:
props:[“自定义属性名”]
结果: 在子组件内,props中的"自定义属性名"与子组件自己data中的变量用法完全相同!