vue-生命周期+工程化开发(三)
生命周期
Vue 生命周期 和 生命周期的四个阶段
思考:
- 什么时候可以发送初始化渲染请求?(越早越好)
- 什么时候可以开始操作dom?(至少dom得渲染出来)
Vue生命周期:一个Vue实例从 创建 到 销毁 的整个过程。
生命周期四个阶段:① 创建 (初始化动态数据)② 挂载 (渲染模板)③ 更新 ④ 销毁
Vue 生命周期函数(钩子函数)
Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】→ 让开发者可以在【特定阶段】运行自己的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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: '计数器'
},
// 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>
小黑记账清单
功能需求:
1. 基本渲染
2. 添加功能
3. 删除功能
4. 饼图渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- 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>
</head>
<body>
<div id="app">
<div class="contain">
<!-- 左侧列表 -->
<div class="list-box">
<!-- 添加资产 -->
<form class="my-form">
<input type="text" v-model="name" class="form-control" placeholder="消费名称" />
<input type="text" v-model.number="price" class="form-control" placeholder="消费价格" />
<button type="button" class="btn btn-primary" @click="add()">添加账单</button>
</form>
<table class="table table-hover">
<thead>
<tr>
<th>编号</th>
<th>消费名称</th>
<th>消费价格</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,index) in list" :key="item.id">
<td>{{index+1}}</td>
<td>{{item.name}}</td>
<td :class="{ red: item.price>500}">{{item.price}}</td>
<td><a href="javascript:;" @click="del(item.id)">删除</a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4" class="red">消费总计: {{totalPrice.toFixed(2)}}</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>
/**
* 接口文档地址:
* 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: [],
name: '',
price: null
},
computed: {
totalPrice(){
let total = this.list.reduce((sum,item)=>sum+item.price,0)
return total
}
},
methods: {
async getList(){
// 使用ajax发送请求
const res = await axios.get('https://applet-base-api-t.itheima.net/bill',{
params: {
creator: 'jack'
}
})
// console.log(res);
this.list=res.data.data
// console.log(this.list);
//更新图表
this.Chars.setOption({
series: [
{
// data: [
// { value: 1048, name: 'Search Engine' },
// { value: 735, name: 'Direct' },
// { value: 580, name: 'Email' },
// { value: 484, name: 'Union Ads' },
// { value: 300, name: 'Video Ads' }
// ]
data: this.list.map(item=>{
//返回一个对象
return {value: item.price, name: item.name}
})
}
]
})
},
async add(){
if(!this.name){
alert('请输入商品名称')
return
}
if(typeof this.price!== 'number'){
alert('请输入正确的价格')
return
}
const res = await axios.post('https://applet-base-api-t.itheima.net/bill',{
creator: 'jack',
name: this.name,
price: this.price
})
//重新渲染
this.getList()
//重置输入框
this.name = ''
this.price = null
},
async del(id){
const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
//重新渲染
this.getList()
}
},
// 在数据动态化后执行的钩子函数
created(){
//数据出初始化完成后,获取数据
this.getList()
},
//在视图渲染完成后执行
mounted(){
//初始化echarts对象
this.Chars = echarts.init(document.querySelector('#main'))
this.Chars.setOption({
// 标题
title: {
text: '消费账单列表',
left: 'center'
},
//
tooltip: {
trigger: 'item'
},
// 小图标
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '消费账单',
type: 'pie',
radius: '50%',
data: [
{ value: 1048, name: 'Search Engine' },
{ value: 735, name: 'Direct' },
{ value: 580, name: 'Email' },
{ value: 484, name: 'Union Ads' },
{ value: 300, name: 'Video Ads' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
})
}
})
</script>
</body>
</html>
案例总结:
工程化开发入门
开发 Vue 的两种方式:
1. 核心包传统开发模式:基于 html / css / js 文件,直接引入核心包,开发 Vue。
2. 工程化开发模式:基于构建工具(例如:webpack ) 的环境中开发 Vue。
工程化开发 & 脚手架 Vue CLI
基本介绍:
Vue CLI 是 Vue 官方提供的一个全局命令工具。
可以帮助我们快速创建一个开发 Vue 项目的标准化基础架子。【集成了 webpack 配置】
好处:
1. 开箱即用,零配置
2. 内置 babel 等工具
3. 标准化
使用步骤:
1. 全局安装 (一次) :yarn global add @vue/cli 或 npm i @vue/cli -g
2. 查看 Vue 版本:vue --version
3. 创建项目架子:vue create project-name(项目名-不能用中文)
4. 启动项目: yarn serve 或 npm run serve(找package.json)
脚手架目录文件介绍 & 项目运行流程
组件化开发 & 根组件
① 组件化:一个页面可以拆分成一个个组件,每个组件有着自己独立的结构、样式、行为。 好处:便于维护,利于复用 → 提升开发效率。
组件分类:普通组件、根组件。
② 根组件:整个应用最上层的组件,包裹所有普通小组件。
App.vue 文件(单文件组件)的三个组成部分
普通组件的注册使用
组件注册的两种方式:
1. 局部注册:只能在注册的组件内使用
① 创建 .vue 文件 (三个组成部分)
② 在使用的组件内导入并注册
2. 全局注册:所有组件内都能使用
局部注册
全局注册
小结:
(1) 组件化:
页面可拆分成一个个组件,每个组件有着独立的结构、样式、行为
① 好处:便于维护,利于复用 → 提升开发效率。
② 组件分类:普通组件、根组件。
(2) 根组件:
整个应用最上层的组件,包裹所有普通小组件。
一个根组件App.vue,包含的三个部分:
① template 结构 (只能有一个根节点)
② style 样式 (可以支持less,需要装包 less 和 less-loader )
③ script 行为
两种注册方式:
① 局部注册:
(1) 创建.vue组件 (单文件组件)
(2) 使用的组件内导入,并局部注册 components: { 组件名:组件对象 }
② 全局注册:
(1) 创建.vue组件 (单文件组件)
(2) main.js内导入,并全局注册 Vue.component(组件名, 组件对象)
使用:
<组件名></组件名>
技巧:
一般都用局部注册,如果发现确实是通用组件,再抽离到全局。
综合案例:小兔鲜首页
页面开发思路:
1. 分析页面,按模块拆分组件,搭架子 (局部或全局注册)
2. 根据设计图,编写组件 html 结构 css 样式 (已准备好)
3. 拆分封装通用小组件 (局部或全局注册)
将来 → 通过 js 动态渲染,实现功能