vue生命周期和发送Ajax请求
一 vue生命周期介绍
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
生命周期图示:
二 vue生命周期钩子函数
钩子函数 | 描述 |
---|---|
beforeCreate | 创建Vue实例之前调用 |
created | 创建Vue实例成功后调用(可以在此处发送异步请求后端数据) |
beforeMount | 渲染DOM之前调用 |
mounted | 渲染DOM之后调用 |
beforeUpdate | 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染) |
updated | 重新渲染完成之后调用 |
beforeDestroy | 销毁之前调用 |
destroyed | 销毁之后调用 |
三 测试
小案例:组件创建,开启定时器,不停的打印hello,在destroyed中对定时器进行销毁
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<div>
<button @click="delComponent">组件删除</button>
</div>
<print v-if="show"></print>
</div>
</body>
<script>
Vue.component('print', {
template: `
<div>
{{title}}
<button @click="handleClick">改title</button>
</div>
`,
data() {
return {
title: 'Hello World!',
task: ''
}
},
methods: {
handleClick() {
this.title = 'Hello Vue!'
}
},
created() {
// 开启定时任务
this.task = setInterval(() => {
console.log('定时任务开启')
}, 1000)
},
destroyed() {
// 清除定时器任务
clearInterval(this.task)
this.task = ''
}
})
let vm = new Vue({
el: '#app',
data: {
show: true
},
methods: {
delComponent() {
this.show = !this.show
}
}
})
</script>
</html>
三 发送Ajax请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<div id="app">
<h1>jquery发送ajax获取数据</h1>
<button @click="getData1">点击获取数据</button>
<p>name:{{name}}</p>
<p>age:{{age}}</p>
<h1>fetch发送ajax获取数据</h1>
<button @click="getData2">点击获取数据</button>
<p>name:{{name}}</p>
<p>age:{{age}}</p>
<h1>axios发送ajax获取数据</h1>
<button @click="getData3">点击获取数据</button>
<p>name:{{name}}</p>
<p>age:{{age}}</p>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
name: '',
age: ''
},
methods: {
getData1() {
$.ajax({
url: 'http://127.0.0.1:5000/',
type: 'get',
success: data => {
console.log(data, typeof (data))
data = JSON.parse(data)
this.name = data.name
this.age = data.age
}
})
},
getData2() {
fetch('http://127.0.0.1:5000/').then(res => res.json()).then(res => {
console.log(res, typeof (res))
this.name = res.name
this.age = res.age
})
},
getData3() {
// vue用的较多
axios.get('http://127.0.0.1:5000/').then(res => {
console.log(res, typeof (res))
this.name = res.data.name
this.age = res.data.age
})
}
}
})
</script>
</html>
flask写的服务器:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def get_data():
res = jsonify({'name': 'xuxiaoxu', 'age': 18})
# 解决跨域问题
res.headers = {'Access-Control-Allow-Origin': '*'}
return res
if __name__ == '__main__':
app.run()
基于django的服务器
# views.py
from django.shortcuts import render
from django.http import JsonResponse
def get_data(request):
res = JsonResponse({'name': 'xuxiaoxu', 'age': 18})
res.headers = {'Access-Control-Allow-Origin': '*'}
return res
# urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.get_data),
]
获取电影详情示例
{
"status": 0,
"data": {
"films": [
{
"filmId": 6112,
"name": "万里归途",
"poster": "https://pic.maizuo.com/usr/movie/f31367bb1a275f032ea3793a0571d9e0.jpg",
"actors": [
{
"name": "饶晓志",
"role": "导演",
"avatarAddress": "https://pic.maizuo.com/usr/movie/3c1b606e514b6cd66d376b56275dcc76.jpg"
},
{
"name": "张译",
"role": "演员",
"avatarAddress": "https://pic.maizuo.com/usr/movie/ff9aafa8c6033a1277d5ecd65822f8ae.jpg"
},
{
"name": "王俊凯",
"role": "演员",
"avatarAddress": "https://pic.maizuo.com/usr/movie/8dc6e01594d200ac39199d633a75ba52.jpg"
},
{
"name": "殷桃",
"role": "演员",
"avatarAddress": "https://pic.maizuo.com/usr/movie/f408ad8336d8a870569a60a47deda5fb.jpg"
},
{
"name": "成泰燊",
"role": "参赞衔",
"avatarAddress": "https://pic.maizuo.com/usr/movie/4c87d92b3571c7f7fe82fa260c875c5c.jpg"
}
],
"director": "饶晓志",
"category": "剧情|战争",
"synopsis": "电影根据真实事件改编。 努米亚共和国爆发战乱,前驻地外交官宗大伟(张译 饰)与外交部新人成朗(王俊凯 饰)受命前往协助撤侨。任务顺利结束,却得知还有一批被困同胞,正在白婳(殷桃 饰)的带领下,前往边境撤离点。情急之下,两人放弃了回家机会,逆行进入战区。赤手空拳的外交官,穿越战火和荒漠,面对反叛军的枪口,如何带领同胞走出一条回家之路……",
"filmType": {
"name": "2D",
"value": 1
},
"nation": "中国大陆",
"language": "",
"videoId": "",
"premiereAt": 1664496000,
"timeType": 3,
"runtime": 137,
"grade": "7.3",
"item": {
"name": "2D",
"type": 1
},
"isPresale": true,
"isSale": false
},
{
"filmId": 6082,
"name": "哥,你好",
"poster": "https://pic.maizuo.com/usr/movie/f85b53cad68c6c0c2cba934107f2199e.jpg",
"actors": [
{
"name": "张栾",
"role": "导演",
"avatarAddress": "https://pic.maizuo.com/usr/movie/af46993a79d581185576526064e225b8.jpg"
},
{
"name": "马丽",
"role": "陆春丽",
"avatarAddress": "https://pic.maizuo.com/usr/movie/7be380f850bafaf66e5133915ee63bc1.jpg"
},
{
"name": "常远",
"role": "小伍",
"avatarAddress": "https://pic.maizuo.com/usr/movie/7473171dfa35d0fba57818ee1d43f22a.jpg"
},
{
"name": "魏翔",
"role": "伍红旗",
"avatarAddress": "https://pic.maizuo.com/usr/movie/164dd1b5511460986861db8726a6c817.jpg"
},
{
"name": "贾冰",
"role": "强哥",
"avatarAddress": "https://pic.maizuo.com/usr/movie/9db69a519c13e7d47a784834419c9422.jpg"
}
],
"director": "张栾",
"category": "喜剧|剧情",
"synopsis": "马丽常远魏翔金牌喜剧阵容联手中秋送欢乐!与父亲老伍(魏翔 饰)终年不合的小伍(常远 饰)阴差阳错回到80年代,意外搅黄了父亲与母亲大陆(马丽 饰)的初次相遇。为了纠正这个错误,他想尽办法一次次重返过去,鼓励老妈追老爸,让人啼笑皆非的闹剧不断上演。父母相遇相恋的命运,是否会因为小伍的干预而转变?尘封在父亲心里的秘密,又将如何慢慢揭开……",
"filmType": {
"name": "2D",
"value": 1
},
"nation": "中国大陆",
"language": "",
"videoId": "",
"premiereAt": 1662681600,
"timeType": 3,
"runtime": 111,
"grade": "7.9",
"item": {
"name": "2D",
"type": 1
},
"isPresale": true,
"isSale": false
},
{
"filmId": 6105,
"name": "平凡英雄",
"poster": "https://pic.maizuo.com/usr/movie/48a4189005bb14638db1f38263dffbc1.jpg",
"actors": [
{
"name": "陈国辉",
"role": "导演",
"avatarAddress": "https://pic.maizuo.com/usr/movie/7597a67312336c6b8dd07d7caa885bd6.jpg"
},
{
"name": "李冰冰",
"role": "周燕",
"avatarAddress": "https://pic.maizuo.com/usr/movie/a0f12731794f77de79b088d6b49aa80b.jpg"
},
{
"name": "冯绍峰",
"role": "林立",
"avatarAddress": "https://pic.maizuo.com/usr/movie/63cd6726f250c6788cc8d8f4caab1509.jpg"
},
{
"name": "黄晓明",
"role": "谢辉阳",
"avatarAddress": "https://pic.maizuo.com/usr/movie/f13e0f0f69f0dbc32cf837a56552a135.jpg"
},
{
"name": "林永健",
"role": "唐伟",
"avatarAddress": "https://pic.maizuo.com/usr/movie/1f587be5fd447c6ce9239ccffc66453e.jpg"
}
],
"director": "陈国辉",
"category": "剧情",
"synopsis": "2021年4月30日,一名7岁的小男孩因手臂被拖拉机绞断,需紧急前往乌鲁木齐进行接臂手术。当地医生告知,手术须在6小时之内完成,否则细胞坏死后将无法治疗。于是一场与时间赛跑的接力救援赛就此展开。",
"filmType": {
"name": "2D",
"value": 1
},
"nation": "中国大陆",
"language": "",
"videoId": "",
"premiereAt": 1664496000,
"timeType": 3,
"runtime": 120,
"grade": "7.2",
"item": {
"name": "2D",
"type": 1
},
"isPresale": true,
"isSale": false
}
],
"total": 43
},
"msg": "ok"
}
数据:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="obj in filmsList">
电影名:{{obj.name}}
<br>
描述:{{obj.synopsis}}
<h2>电影海报</h2>
<img :src="obj.poster" alt="" width="300px" height="400px">
<br>
<h4>剧组成员:</h4>
<div v-for="info in obj.actors">
名字:{{info.name}}
<br>
角色:{{info.role}}
<br>
头像:<img :src="info.avatarAddress" alt="" width="200px" height="200px">
<hr>
</div>
<br>
</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
filmsList: []
},
created() {
axios.get('http://127.0.0.1:5000/movie_data/').then(data => {
console.log(data)
this.filmsList = data.data.data.films
})
}
})
</script>
</html>
基于flask的服务器
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/movie_data/')
def movie_data():
with open(r'./data.json', 'r', encoding='utf8') as e:
import json
res = json.load(e)
res = jsonify(res)
res.headers = {'Access-Control-Allow-Origin': '*'}
return res
if __name__ == '__main__':
app.run()
基于django的服务器
def movie_data(request):
with open('data.json', 'r', encoding='utf8') as e:
import json
res = json.load(e)
res = JsonResponse(res)
res.headers = {'Access-Control-Allow-Origin': '*'}
return res
四 计算属性
在插值语法中写上函数名加括号,每一次页面刷新,都会执行该函数,会浪费资源。
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
message:'hello'
},
computed:{
reversedMessage(){
console.log('执行了reversedMessage')
return this.message.split('').reverse().join('')
}
}
})
</script>
</html>
打开浏览器的控制台,自行修改例子中的 vm。vm.reversedMessage 的值始终取决于 vm.message 的值。
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
计算属性重写过滤类
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p><input type="text" v-model="search" placeholder="输入搜索内容"></p>
<ul>
<li v-for="i in showDate">{{i}}</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
search: '',
dataArray: ['a', 'ab', 'av', 'b', 'bb', 'bvn', 'dddd']
},
computed: {
showDate() {
return this.dataArray.filter(item =>
item.indexOf(this.search) >= 0
)
}
}
})
</script>
</html>
五 监听属性
当你有一些数据需要随着其它数据变动而变动时,就可以使用watch监听。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue.js"></script>
</head>
<body>
<div id="app">
<p><button @click="selectType='学习'">点我学习</button></p>
<p><button @click="selectType='玩游戏'">点我玩游戏</button></p>
<p><button @click="selectType='睡觉'">点我睡觉</button></p>
<hr>
{{selectType}}
</div>
</body>
<script>
let vm = new Vue({
el: '#app',
data: {
selectType:''
},
watch: {
selectType(val){
console.log(vala)
}
}
})
</script>
</html>