文章目录
- Vue生命周期和生命周期的四个阶段
- created应用—新闻列表渲染
- mounted应用—进入页面搜索框就获得焦点
- 账单统计(Echarts可视化图表渲染)
Vue生命周期和生命周期的四个阶段
思考:
什么时候可以发送初始化渲染请求?(越早越好)
什么时候可以开始操作dom?(至少dom得渲染出来)
Vue生命周期: 一个Vue实例从创建到销毁的整个过程
生命周期四个阶段: ①创建②挂载③更新④销毁
Vue生命周期函数(钩子函数)
Vue生命周期过程中,会自动运行一些函数,被称为【生命周期钩子】—>让开发者可以在【特定阶段】运行自己的代码。
代码说明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>生命周期的四个阶段</title>
</head>
<body>
<div id="app">
<h1>{{title}}</h1>
<button @click="sub">-</button>
<span>{{count}}</span>
<button @click="add">+</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
count: 100,
title: '计数器'
},
// 1.创建阶段(准备数据)
beforeCreate() {
console.log('beforeCreate 响应式数据准备好之前', this.count);//undefined
},
created() {
// created,这一阶段开始,就能发送初始化渲染请求
console.log('Created 响应式数据准备好之后', this.count);// 100
},
// 2.挂载阶段(渲染模板)
beforeMount() {
console.log('beforeMount 模板渲染之前', document.querySelector('h1').innerHTML);// {{title}}
},
mounted() {
// created,这一阶段开始,就能操作dom了
console.log('mounted 模板渲染之后', document.querySelector('h1').innerHTML);// 计数器
},
// 3.更新阶段(修改数据 → 更新视图)
beforeUpdate() {
console.log('beforeUpdate 数据修改了,视图还没更新', document.querySelector('span').innerHTML);
},
updated() {
console.log('Updated 数据修改了,视图已经更新', document.querySelector('span').innerHTML);
},
//4.卸载阶段
//Vue提供了一个语法 Vue对象名.$destroy() 用来查看卸载状态
beforeDestroy() {
console.log('beforeDestory 卸载前');
console.log('清除掉一些Vue以外的资源占用,定时器,延时器...');
},
destroyed() {
console.log('destroyed 卸载后');
},
methods: {
add() {
this.count++
},
sub() {
this.count--
}
}
})
</script>
</body>
</html>
created应用—新闻列表渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>新闻列表渲染</title>
<style>
#app {
width: 500px;
margin: 0 auto;
}
#app ul {
width: 100%;
margin: 0;
padding: 0;
list-style: none;
}
#app ul li.news {
width: 100%;
height: 120px;
display: flex;
background-color: rgb(252, 252, 252);
margin: 20px 0;
border: 1px solid #eee;
border-left: none;
border-right: none;
}
#app ul li.news .left {
width: 70%;
height: 100%;
}
#app ul li.news .left .title {
width: 90%;
height: 70%;
font-size: 18px;
font-weight: bold;
margin: 5px 0;
color: #292929;
}
#app ul li.news .left span {
font-size: 14px;
color: #454545;
margin-right: 20px;
}
#app ul li.news .right {
width: 30%;
height: 100%;
}
#app ul li.news .right img {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in list" :key="item.id" class="news">
<div class="left">
<div class="title">{{item.title}}</div>
<div class="info">
<span>{{item.source}}</span>
<span>{{item.time}}</span>
</div>
</div>
<div class="right">
<img :src="item.img" alt="">
</div>
</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script>
// 接口地址:http://hmajax.itheima.net/api/news
// 请求方式 get
const app = new Vue({
el: '#app',
data: {
list: []
},
async created() {
// 1.发送请求,获取数据
const res = await axios.get('http://hmajax.itheima.net/api/news')
console.log(res);//查看获取到的数据
// 2.将数据更新给data中的list
this.list = res.data.data
}
})
</script>
</body>
</html>
mounted应用—进入页面搜索框就获得焦点
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>搜索框一进入就获得焦点</title>
<style>
.container {
width: 600px;
height: auto;
margin: 0 auto;
}
.container .seacher-container {
width: 100%;
height: 150px;
text-align: center;
background-color: aliceblue;
}
.container .seacher-container .search-box {
width: 80%;
height: 35px;
margin: 20px auto;
border: 1px solid #8b8b8b;
display: flex;
border-radius: 5px;
justify-content: flex-end;
align-items: center;
background-color: #ffffff;
border-right: none;
}
.container .seacher-container .search-box input {
width: 78%;
height: 90%;
border: none;
outline: none;
background-color: #ffffff;
}
.container .seacher-container .search-box button {
width: 20%;
height: 106%;
border: none;
outline: none;
background-color: #ea2704;
color: #f5f5f5;
border-radius: 5px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container" id="app">
<div class="seacher-container">
<img src="http://www.itheima.com/images/logo.png" alt="">
<div class="search-box">
<input type="text" v-model="words" id="inp" autocomplete="off">
<button>搜索一下</button>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
words: ''
},
// 核心思路:
// 1.等输入框渲染出来
// 2.让输入框获取焦点
mounted() {
document.querySelector('#inp').focus()
}
})
</script>
</body>
</html>
账单统计(Echarts可视化图表渲染)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#app {
margin: 0 auto;
width: 1100px;
height: auto;
}
h3 {
color: #8d5252;
}
/* https://www.apifox.cn/apidoc/shared-24459455-ebb1-4fdc- */
.container {
width: 1100px;
display: flex;
justify-content: space-between;
}
.container #tableArea {
width: 50%;
height: auto;
}
.container #tableArea .iptArea {
width: 100%;
height: 30px;
margin-bottom: 10px;
}
.container #tableArea .iptArea input {
width: 40%;
height: 100%;
border: 1px solid #e2e1e1;
border-radius: 4px;
text-indent: 5px;
outline: none;
}
.container #tableArea .iptArea button {
width: 15%;
height: 110%;
border: none;
outline: none;
background-color: rgb(9, 114, 206);
color: #fff;
border-radius: 4px;
cursor: pointer;
}
.container #tableArea table {
width: 100%;
height: auto;
text-align: left;
border-collapse: collapse;
font-size: 14px;
}
.container #tableArea table tr {
height: 40px;
border-bottom: 1px solid #eee;
}
.container #tableArea table tr .red {
color: red;
}
.container #tableArea table tr td a {
color: rgb(42, 97, 238);
text-decoration: none;
}
.container #chartArea {
width: 45%;
height: 330px;
border: 1px solid #eee;
padding: 10px;
}
@media (max-width: 768px) {
.container {
width: 600px;
flex-wrap: wrap;
justify-content: center;
}
.container #tableArea {
width: 90%;
}
.container #chartArea {
width: 90%;
}
}
@media (min-width: 1200px) {
.container {
width: 1100px;
flex-wrap: wrap;
}
.container #tableArea {
width: 50%;
}
.container #chartArea {
width: 45%;
}
}
</style>
</head>
<body>
<div id="app">
<h3>小黑记账清单</h3>
<div class="container">
<div id="tableArea">
<div class="iptArea">
<input type="text" placeholder="消费名称" v-model.trim="name">
<input type="text" placeholder="消费价格" v-model.number="price">
<button @click="addData">添加账单</button>
</div>
<table>
<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 @click="delData(item.id)" href="javascript:;">删除</a></td>
</tr>
</tbody>
<tfoot>
<tr>
<th colspan="4">消费总计:<span>{{totalPrice}}</span></th>
</tr>
</tfoot>
</table>
</div>
<div id="chartArea">
<div id="main" style="width:550px;height:330px;"></div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.0/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<!--
//接口地址
// 查询我的账单列表 https://applet-base-api-t.itheima.net/bill get请求方式,请求参数creator
// 删除账单明细 https://applet-base-api-t.itheima.net/bill/{id} delete请求方式,请求参数id
// 添加账单 https://applet-base-api-t.itheima.net/bill post请求方式,请求参数creator、name、 price
// 转换 https://applet-base-api-t.itheima.net/bill
-->
<script>
const app = new Vue({
el: '#app',
data: {
list: [],
name: '',
price: ''
},
computed: {
totalPrice() {
return this.list.reduce((sum, item) => sum + item.price, 0).toFixed(2)
}
},
created() {
this.getData()
},
mounted() {
this.myChart = echarts.init(document.getElementById('main'));
this.myChart.setOption({
title: {
text: '消费账单列表',
left: 'center'
},
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
name: '消费账单',
type: 'pie',
radius: '50%',
data: [
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
},
methods: {
async getData() {
const res = await axios.get('https://applet-base-api-t.itheima.net/bill', {
params: {
creator: '小黑'
}
})
this.list = res.data.data
this.myChart.setOption(
{
series: [
{
data: this.list.map(item => ({ value: item.price, name: item.name }))
}
]
}
)
},
async addData() {
// 优化
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: '小黑',
name: this.name,
price: this.price
})
console.log(res);
// 重新再渲染一次
this.getData()
// 清空输入框
this.name = ''
this.price = ''
},
async delData(id) {
const res = await axios.delete(`https://applet-base-api-t.itheima.net/bill/${id}`)
console.log(res);
// 重新再渲染一次
this.getData()
}
}
})
</script>
</body>
</html>