生命周期

Vue生命周期:就是一个Vue实例从创建 到 销毁 的整个过程。
生命周期四个阶段:① 创建 ② 挂载 ③ 更新 ④ 销毁

  1. 创建阶段:创建响应式数据
  2. 挂载阶段:渲染模板
  3. 更新阶段:修改数据,更新视图
  4. 销毁阶段:销毁Vue实例

image.png

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
<div id="app">
<h3>{{ title }}</h3>
<div>
<button @click="count--">-</button>
<span>{{ count }}</span>
<button @click="count++">+</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
count: 100,
title: '计数器'
},
beforeCreate(){ }
// 1. 创建阶段(准备数据)
//进行创建响应式数据阶段created(){ }

beforeMount( ){ }
// 2. 挂载阶段(渲染模板)
//进行挂载数据阶段 mounted(){ }
beforeUpdate(){ }
// 3. 更新阶段(修改数据 → 更新视图)
//进行update阶段 updated(){ }
beforeDestroy(){ }
// 4. 卸载阶段
// destroyed(){}
})
</script>

Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】→ 让开发者可以在【特定阶段】运行自己的代码

image.png

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

<div id="app">
<h3>{{ title }}</h3>
<div>
<button @click="count--">-</button>
<span>{{ count }}</span>
<button @click="count++">+</button>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
count: 100,
title: '计数器'
},
//TODO: 和生命周期图一同观察每个阶段的console的内容
// 1. 创建阶段(准备数据)
beforeCreate () {
console.log('beforeCreate 响应式数据准备好之前', this.count)
},
created () {
console.log('created 响应式数据准备好之后', this.count)
// this.数据名 = 请求回来的数据
// 可以开始发送初始化渲染的请求了
},

// 2. 挂载阶段(渲染模板)
beforeMount () {
console.log('beforeMount 模板渲染之前', document.querySelector('h3').innerHTML)
},
mounted () {
console.log('mounted 模板渲染之后', document.querySelector('h3').innerHTML)
// 可以开始操作dom了
},

// 3. 更新阶段(修改数据 → 更新视图)
beforeUpdate () {
console.log('beforeUpdate 数据修改了,视图还没更新', document.querySelector('span').innerHTML)
},
updated () {
console.log('updated 数据修改了,视图已经更新', document.querySelector('span').innerHTML)
},

// 4. 卸载阶段
beforeDestroy () {
console.log('beforeDestroy, 卸载前')
console.log('清除掉一些Vue以外的资源占用,定时器,延时器...')
},
destroyed () {
console.log('destroyed,卸载后')
}
})
</script>

</body>
</html>

案例

image.png

需求:

1.基本渲染
2.添加功能
3.删除功能
4.饼图渲染

相关代码实现

js

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/**
* 接口文档地址:
* https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc-8df8-0aff8dc317a8/api-53371058
*
* 功能需求:
* 1. 基本渲染
* 2. 添加功能
* 3. 删除功能
* 4. 饼图渲染
*/
const app = new Vue({
el: '#app',
data: {
// 对象数组
list: [
{
id: 0,
name: '',
price: 0,
creator: ''
}
],
//需要添加的单个对象内容
itemName: '',
itemPrice: ''
},
computed: {
totalCount (){
return this.list.reduce((sum, item)=>sum += item.price,0)
}
},

methods: {
// 删除数据
del(id) {
this.list = this.list.filter(item => item.id !== id)
},
add(){
console.log("商品名称:"+ this.itemName)
this.list.unshift({
id: +new Date(),
name: this.itemName,
price: this.itemPrice,
creator: 'rayce'
})
//todo: 更新试图
this.updateView()
// 清空表单
this.itemName= ''
this.itemPrice=''
},
updateView(){
// 更新图表
this.myCharts.setOption({
// 数据项
series: [
{
// data: [
// { value: 1048, name: '球鞋' },
// { value: 735, name: '防晒霜' }
// ]
data: this.list.map(item => ({ value: item.price, name: item.name}))
}
]
})
}

},

async created(){
//发送请求拿到数据, 然后进行渲染
console.log("生命周期的准备响应式数据阶段")
const res = await axios({
url: 'https://applet-base-api-t.itheima.net/bill',
params: {
creator: 'rayce'
}
})
// console.log(res.data.data)
this.list = res.data.data
this.updateView()
},
beforeCreated(){
console.log("生命周期的创建数据阶段。 发送初始化渲染请求")
},

mounted(){
console.log("生命周期的挂载数据阶段(操作dom阶段)")
//进行柄图渲染
//初始化一个饼图 echarts.init(dom) mounted钩子中渲染
//根据数据试试更新饼图 echarts.setOptions({...})

this.myCharts = echarts.init(document.querySelector('#main'))
this.myCharts.setOption({
// 大标题
title: {
text: '消费账单列表',
left: 'center'
},
// 提示框
tooltip: {
trigger: 'item'
},
// 图例
legend: {
orient: 'vertical',
left: 'left'
},
// 数据项
series: [
{
name: '消费账单',
type: 'pie',
radius: '50%', // 半径
data: [
// { value: 1048, name: '球鞋' },
// { value: 735, name: '防晒霜' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
})


}

})

/**
* TODO:
3.思路分析
1.基本渲染
立刻发送请求获取数据 created
拿到数据,存到data的响应式数据中
结合数据,进行渲染 v-for
消费统计 —> 计算属性

2.添加功能
收集表单数据 v-model,使用指令修饰符处理数据
给添加按钮注册点击事件,对输入的内容做非空判断,发送请求
请求成功后,对文本框内容进行清空
重新渲染列表

3.删除功能

注册点击事件,获取当前行的id
根据id发送删除请求
需要重新渲染

4.饼图渲染

*/

html

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- CSS only -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
/>
<style>
.red {
color: red!important;
}
.search {
width: 300px;
margin: 20px 0;
}
.my-form {
display: flex;
margin: 20px 0;
}
.my-form input {
flex: 1;
margin-right: 20px;
}
.table > :not(:first-child) {
border-top: none;
}
.contain {
display: flex;
padding: 10px;
}
.list-box {
flex: 1;
padding: 0 30px;
}
.list-box a {
text-decoration: none;
}
.echarts-box {
width: 600px;
height: 400px;
padding: 30px;
margin: 0 auto;
border: 1px solid #ccc;
}
tfoot {
font-weight: bold;
}
@media screen and (max-width: 1000px) {
.contain {
flex-wrap: wrap;
}
.list-box {
width: 100%;
}
.echarts-box {
margin-top: 30px;
}
}
</style>


<div id="app">
<div class="contain">
<!-- 左侧列表 -->
<div class="list-box">

<!-- 添加资产 -->
<form class="my-form">
<input v-model="itemName" type="text" class="form-control" placeholder="消费名称" />
<input v-model="itemPrice" type="text" class="form-control" placeholder="消费价格" />
<button @click="add()" type="button" class="btn btn-primary">添加账单</button>
</form>

<table class="table table-hover">
<thead>
<tr>
<th>编号</th>
<th>消费名称</th>
<th>消费价格</th>
<th>操作</th>
</tr>
</thead>
<tbody v-if="list.length > 0">
<tr v-for="(item, index) in list">
<td>{{item.id}}</td>
<td>{{ item.name }}</td>
<td>{{ item.price }}</td>
<td @click="del(item.id)"><a>删除</a></td>
</tr>
<!-- <tr>
<td>2</td>
<td>大衣</td>
<td class="red">199.00</td>
<td><a href="javascript:;">删除</a></td>
</tr> -->
</tbody>
<tfoot>
<tr>
<td colspan="4">消费总计: {{ totalCount }}</td>
</tr>
</tfoot>
</table>
</div>

<!-- 右侧图表 -->
<div class="echarts-box" id="main"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.0/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="./zhangdan.js"></script>
</body>
</html>

重点关注图表内容的实现
通过这个案例最好学会echarts的使用。

工程化开发入门

工程化开发模式:基于构建工具(例如:webpack)的环境中开发Vue。
image.png
工程化开发模式优点:
提高编码效率,比如使用JS新语法、Less/Sass、Typescript等通过webpack都可以编译成浏览器识别的ES3/ES5/CSS等
工程化开发模式问题:

  • webpack配置不简单
  • 雷同的基础配置
  • 缺乏统一的标准

为了解决以上问题,所以我们需要一个工具,生成标准化的配置

脚手架Vue CLI

基本介绍:

Vue CLI 是Vue官方提供的一个全局命令工具
可以帮助我们快速创建一个开发Vue项目的标准化基础架子。【集成了webpack配置】

好处:

  1. 开箱即用,零配置
  2. 内置babel等工具
  3. 标准化的webpack配置

使用步骤:

  1. 全局安装(只需安装一次即可) yarn global add @vue/cli 或者 npm i @vue/cli -g
  2. 查看vue/cli版本: vue –version
  3. 创建项目架子:vue create project-name(项目名不能使用中文)
  4. 启动项目:yarn serve 或者 npm run serve(命令不固定,找package.json)

项目目录及其运行流程

项目目录:image.png

  • main.js文件

核心作用: 导入App.vue,基于App.vue 创建结构渲染index.html

  1. 导入vue核心包
  • Vue.config.productionTip = false

提示当前处于什么环境
main.js的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 导入vue核心包
import Vue from 'vue'
import App from './App.vue'
//2. 提示当前的生产环境
Vue.config.productionTip = false

//3. 创建vue实例
new Vue({
// render: h => h(App),
//上述的完整的写法
render: (createElement) =>{
//基于App构建元素结构
return createElement(App)
}
}).$mount('#app')// 和el: '#app'一样, 都是指定管理的容器

运行流程

image.png

组件化开发

  1. 组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。
  2. 好处:便于维护,利于复用 → 提升开发效率。
  3. 组件分类:普通组件、根组件。

比如:下面这个页面,可以把所有的代码都写在一个页面中,但是这样显得代码比较混乱,难易维护。咱们可以按模块进行组件划分

image.png

根组件

image.png

三个组成部分

  • 三部分构成
    • template:结构 (有且只能一个根元素)
    • script: js逻辑
    • style: 样式 (可支持less,需要装包)
  • 让组件支持less(1) style标签,lang=”less” 开启less功能(2) 装包: yarn add less less-loader -D 或者npm i less less-loader -D

普通组件的注册使用- 局部组件

1.特点:

只能在注册的组件内使用

2.步骤:

  1. 创建.vue文件(三个组成部分)
  2. 在使用的组件内先导入再注册,最后使用

3.使用方式:

当成html标签使用即可 <组件名></组件名>

4.注意:

组件名规范 —> 大驼峰命名法, 如 Header

5.语法:

App.vue中 使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
//导入组件
import Head from "./components/Head.vue"
import Main from './components/Main.vue'
import Foot from './components/Foot.vue'
export default {
// 注册组件 (对于导入的组件名和组件对象一样时, 我们可以直接使用组件名)
components: {
// 组件名: 组件对象
Head,
Main,
Foot
}
}
</script>

image.png

1
2
3
4
5
6
7
8
9
10
11
<template>
//使用组件
<!-- 类名·最好和当前组件名同名 -->
<div class="App">
<Head>这里是Head</Head>
<Main>这里是main</Main>
<Foot>这里是Foot</Foot>
</div>

</template>

普通组件的注册使用-全局注册

1.特点:

全局注册的组件,在项目的任何组件中都能使用(相当于工具组件)

2.步骤

  1. 创建.vue组件(三个组成部分)
  2. main.js中进行全局注册

3.使用方式

当成HTML标签直接使用
<组件名></组件名>

4.注意

组件名规范 —> 大驼峰命名法, 如 HmHeader

5.语法

注册:
Vue.component('组件名', 组件对象)

1
2
3
4
//进行全局组件的导入
import Button1 from './components/Button1.vue'
//全局注册组件
Vue.component('Button1', Button1)
1
2
3
4
5
6
<template>
<div class="hm-header">
我是hm-header
<Button1>按钮</Button1>
</div>
</template>

工程化开发入门 综合案例

1
2
3
// 项目快捷键
//1. 所有都折叠 ctrl + k , ctrl + 0
//2. 所有都展开 ctrl + k , ctrl + j

**实现思路: **

  1. 分析页面,按模块拆分组件,搭架子 (局部或全局注册)
  2. 根据设计图,编写组件 html 结构 css 样式 (已准备好)
  3. 拆分封装通用小组件 (局部或全局注册)将来 → 通过 js 动态渲染,实现功能