Vue CLI的安装

学习VUE组件化开发之前,先了解一下VUE CLI,工欲善其事必先利其器嘛

官网地址

首先需要一个node.js环境,然后安装Vue CLI

1
2
3
npm install -g @vue/cli
# OR
yarn global add @vue/cli

之后就可以通过指令来创建vue项目了

1
vue create project

VUE CLI还支持可视化创建项目,实测巨卡无比,这里就不展开介绍了

输入创建项目命令之后,就可以创建工程,根据需求勾选对应选项

创建完毕之后,进入对应的文件夹,然后运行serve,就可以在页面上看到这个项目

1
2
cd project
npm run serve

创建好的项目目录结构如图所示

其中node_modules文件夹放的是插件之类的东西,public文件夹里放的项目中要用到的资源,比如css之类的,src中放的主要是我们要写的代码,其中components中放的是组件,一会儿来讲,App.vue文件是项目的主体,可以看做是index.html之类的东西,而main.js则负责将App.vue实例化并渲染到页面上

Vue组件

App.vue本身就是一个组件,可以看到它分为三个部分,template标签包裹的html部分,script部分包裹的js部分以及style标签包裹的css部分

现在让我们把原有的示例代码删除,自己来写一个简单的组件熟悉一下

首先是template部分,和html几乎是一样的,只是外面多了一个template标签,这是一个固定的格式

1
2
3
4
5
<template>
<div id="app">
<h1>{{ msg }}</h1>
</div>
</template>

script部分的格式和之前的vue对象稍有不同,其中data是函数的形式,格式如下

1
2
3
4
5
6
7
8
9
10
<script>
export default {
el: "#app",
data: function(){
return{
msg: "helloworld"
}
}
};
</script>

CSS部分则和普通的css写法相同

1
2
3
4
5
6
<style>
h1{
color: orange;
text-align: center;
}
</style>

子组件的调用

我们可以在components里面创建组件,组件内的写法和之前是一样的

组件的引入需要在父组件中先import,然后在components中写入,然后可以在template中像使用标签一样去使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
// import引入
import Header from "./components/header"
import Body from "./components/body"
import Footer from "./components/footer"

export default {
el: "#app",
data: function(){
return{
msg: "helloworld"
}
},
// 注册
components:{
Header,
Body,
Footer
}
};
</script>

需要一提的是上面components里面的写法是简写,实际上每一项应该是Header:Header这样的格式,当命名和引入名相同时可以简写为一个

引入完之后就可以在template中直接使用了

1
2
3
4
5
6
7
8
<template>
<div id="app">
<h1>{{ msg }}</h1>
<Header></Header>
<Body></Body>
<Footer></Footer>
</div>
</template>

如果有组件特别的常用,我们可以全局注册,这样就不需要在多个页面反复导入和注册,全局注册在main.js里面导入和注册,Footer组件的全局注册方式如下

1
2
3
// main.js
import Footer from './components/Footer'
Vue.component('Footer',Footer)

组件中的数据传递

父组件向子组件传值

vue中父组件给子组件传值需要父组件在标签内设置参数,且需要子组件设置参数表props

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 父组件的template中 -->
<div id="app">
<child-com v-for="star in stars" :key="star.id" :star="star" :name="star.name" :gender="star.gender">
</div>

<!-- 子组件中 -->
<script>
export default{
el: "#app",
// 传入的数据可以是值或者直接是一个对象
props: ["name", "gender", "star"]
}
</script>

可以看到子组件props中的变量名其实就是父组件的绑定名,父组件将自己组件中的变量绑定到子组件props中的变量名上,传递给子组件使用,子组件就可以直接地使用这些变量,比如

1
2
3
<template>
<h1>{{name}}</h1>
</template>

传参设置

在组件接受参数的时候还可以设定传参类型,比如设定必须传入数字,字符串等等,实现格式如下

1
2
3
4
5
6
7
8
9
10
<script>
export default{
el: "#app"
props:{
id: Number,
name: String,
star: Object
}
}
</script>

也可以设置多种格式,设置默认值default,设置required要求值必须被传入,或是使用validator对传入的值进行校验,使用示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script>
export default{
props:{
id: Number,
name: String,
star: Object,
// 可以设置多种格式
age: [Number, String],
// 可以设置默认值
nickname:{
type: String,
default: "无昵称"
},
// 设定该数据必须被传入
tel:{
type: Number,
required: true
},
// 对传入参数进行校验
number:{
validator:function(value){
if(value > 0){
return true;
}else{
console.error("number值不能为负")
return false;
}
}
}
}
}
</script>

子组件向父组件传值

子组件给父组件传值,本质上是通过通知的方式使得父组件改变自己的值

需要在父组件内绑定一个方法,然后子组件使用$emit触发事件向父组件的函数传值,通知父组件更改值

1
2
<!-- 父组件中绑定事件 -->
<child-com @changeNum="changeFn"></child-com>
1
2
3
4
5
6
7
8
9
10
11
12
// 父组件中使用methods
methods:{
changeFn: function(data){
this.num = data
}
}
// 在子组件内通知父组件改变属性
methods:{
fn: function(){
this.$emit("changeNum", 100)
}
}

子组件之间的互相传值

父组件作为媒介

子组件之间数据传递最朴素的方法,就是通过父组件,将数据定义在父组件,子组件A使用$emit来更改父组件的值,然后通过父组件传递给子组件B

中央总线方法

创建一个事件总线eventBus.js

1
2
3
4
5
import Vue from 'vue'
// 实例化
let eventBus =new Vue()
// 导出
export default eventBus

组件中接受和发送数据的代码示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import eventBus from '../eventBus'
export default {
data: function () {
return {
msgB: ""
}
},
// 当组件渲染后自动执行
mounted () {
// 监听事件childB (B组件里面用eventBus.$emit触发事件childB)
eventBus.$on('childB', (data) => {
this.msgB = data
})
},
// 发送消息给B组件
methods: {
// 触发事件childA (B组件中eventBus监听事件childA)
sendB: function () {
eventBus.$emit('childA', "hello B,我是A组件")
}
}
}

这里因为两个组件都导入了eventBus实例,用eventBus在子组件触发事件,同时在另一个子组件监听对应的事件,就可以完成子组件间的信息传递