关于vue实例的声明周期,从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期 (https://cn.vuejs.org/v2/guide/instance.html#实例生命周期 )
而声明周期勾子就是生命周期事件的别名而已 (https://cn.vuejs.org/v2/api/#选项-生命周期钩子 )
生命周期钩子 = 生命周期函数 = 生命周期事件
一、生命周期函数的主要分类
1、创建期间的生命周期函数
1、beforeCreate #实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
2、created #实例已经在内存中创建OK,此时 data 和 methods 已经创建OK
#此时还没有开始 编译模板。我们可以在这里进行Ajax请求。
3、beforeMount #此时已经完成了模板的编译,但是还没有挂载到页面中
4、mounted #此时,已经将编译好的模板,挂载到了页面指定的容器中显示
#(mounted之后,表示真实DOM渲染完了,可以操作DOM了)
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
<!--这个div区域就是MVVM中的 View 视图-->
<div id="app1">
</div>
</body>
<script>
new Vue({
el: '#app1',
data: {
msg: 'hello vuejs'
},
// 这是第1个生命周期函数,表示实例完全被创建出来之前,会执行它
beforeCreate: function () {
console.log('01 beforeCreate', this.msg);
//注意:在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
},
// 这是第2个生命周期函数
created: function () {
console.log('02 created', this.msg);
//注意:如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
},
// 这是第3个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把模板渲染到页面中
beforeMount: function () {
console.log('03 beforeMount', this.msg);
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
},
// 这是第4个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
mounted: function () {
console.log('04 mounted', this.msg);
// 注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了
// 此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
}
});
</script>
</html>
2、运行期间的生命周期函数
1、beforeUpdate #状态更新之前执行此函数, 此时 data 中的状态值是最新的
#但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
2、updated #实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据
#都已经完成了更新,界面已经被重新渲染好了
PS:数据发生变化时,会触发这两个方法。不过,我们一般用watch来做
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
</head>
<body>
<!--这个div区域就是MVVM中的 View-->
<div id="app1">
<input type="button" value="修改flag" @click="myMethod">
<h3 id="h3">{{ flag }}</h3>
</div>
</body>
<script>
new Vue({
el: '#app1',
data: {
msg: 'hello vue',
flag: false
},
methods: {
myMethod: function () {
this.flag = true;
}
},
// 接下来的是运行中的两个事件
// 这时候,我们的界面还没有被更新【但是,数据被更新了吗? 数据肯定被更新了】
beforeUpdate() {
console.log('-------------05 beforeUpdate', this.msg);
// 结论:当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
console.log('界面上DOM元素显示的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据:' + this.flag)
},
updated() {
console.log('-------------06 updated', this.msg);
// 结论:updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
console.log('界面上DOM元素显示的内容:' + document.getElementById('h3').innerText)
console.log('data 中的 msg 数据:' + this.flag)
}
});
</script>
</html>
可以看得到,当执行 beforeUpdate 的时候,页面中的显示的数据还是旧的,但此时 data 数据是最新的。 updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
3、销毁期间的生命周期函数
1、beforeDestroy #实例销毁之前调用。在这一步,实例仍然完全可用。
2、destroyed #Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定
#所有的事件监听器会被移除,所有的子实例也会被销毁
PS:
可以在beforeDestroy里清除定时器、或清除事件绑定
4、生命周期函数图解
二、axios 发送Ajax请求
#参考文档
https://blog.csdn.net/sunyctf/article/details/129002056
https://blog.csdn.net/weixin_40017062/article/details/131810859
我们直接所有的vue代码都是写在index.html文件中的,这样其实很不好,我们将他修改一下,改成从.vue中读取配置
vi public/index.html
<!DOCTYPE html>
<html lang="">
<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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
index.html文件回归初始状态,声明app表示入口
vi my-vue-app/src/main.js
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.mount('#app')
vi my-vue-app/src/App.vue
<template>
<div id="app">
<HelloWorld></HelloWorld>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
vi my-vue-app/src/components/HelloWorld.vue
<template>
123
</template>
<script>
export default {
name: "HelloWorld",
}
</script>
<style scoped>
</style>
访问
http://127.0.0.1:8080/
我们上面经过绑定配置,已经将HelloWorld.vue 绑定到了index.html中了,后续配置都是基于HelloWorld.vue文件
安装axios
cd .\my-vue-app\
npm install axios --save
三、GET请求
创建测试json文件
vi my-vue-app/public/data.json
{
"ret": "0",
"data": [
{ "path": "page1", "component": "Page1" , "ip": "Page1" },
{ "path": "page2", "component": "Page2" , "ip": "Page1"},
{ "path": "page3", "component": "Page3" , "ip": "Page1"}
]
}
我们通过get请求其他后端的api通常会返回类似上面的一个json配置,我们通过这个来模拟请求接口返回的数据,因为我们这个json文件是直接添加到index.html的同级目录,可以直接通过浏览器访问
http://127.0.0.1:8080/data.json
vi my-vue-app/src/components/HelloWorld.vue
<template>
{{json}}
</template>
<script>
import axios from "axios"
export default {
name: "HelloWorld",
data(){
return{
json: "" //定义一个空数据,与div交互用
}
},
created() { //created 页面部署时自动执行
axios.get("http://localhost:8080/data.json")
.then((result) => {
this.json = result.data //result.data 会将返回的json交给data中的json变量
console.log(result.data)
})
.catch((err) =>{{
console.log(err)
}}
)
}
}
</script>
<style scoped>
</style>
访问页面
http://localhost:8080/
目前看起来没什么问题,直接请求地址+json文件返回了信息,但是一遍来说我们的后端程序都不会放到前端节点的相同主机上,需要跨站访问,比如
https://www.runoob.com/try/ajax/json_demo.json
我们把上面代码中的url地址换成这个再跑下
vi my-vue-app/src/components/HelloWorld.vue
<template>
{{json}}
</template>
<script>
import axios from "axios"
export default {
name: "HelloWorld",
data(){
return{
json: "" //定义一个空数据,与div交互用
}
},
created() { //created 页面部署时自动执行
axios.get("https://www.runoob.com/try/ajax/json_demo.json")
.then((result) => {
this.json = result.data //result.data 会将返回的json交给data中的json变量
console.log(result.data)
})
.catch((err) =>{{
console.log(err)
}}
)
}
}
</script>
<style scoped>
</style>
我们打开页面发现什么信息都没有,按F12打开开发者工具发现下面这么一条报错
已拦截跨源请求:同源策略禁止读取位于 http://localhost:8080/data.json 的远程资源。(原因:CORS 头缺少 'Access-Control-Allow-Origin')。状态码:200。
跨域访问--配置代理
我们在自己独立使用的时候你直接改成127.0.0.1其实也能访问,但不可能所有的接口都在当前本机上,只要跨主机都会报错并且无法获取到数据,所以我们要先做一点改造
my-vue-app/vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
"/try":{ //try 这个用来和根路径 baseURL 进行匹配 以try开头的请求会转到下面的地址
target: 'https://www.runoob.com',
changeOrigin: true,
}
}
}
})
重启服务
ctrl + c 停止
#启动
npm run serve
如果要配置多个代理,就把proxy那好行多复制几次
四、POST请求
post请求常用的数据请求格式有三种
1、Content-Type : application/x-www-form-urlencoded。
ajax默认的数据格式。请求体中的数据会以json字符串的形式发送到后端。
2、Content-Type : application/json ; charset=utf-8。
axios默认的数据格式。请求体中的数据会以普通表单形式(键值对)发送到后端。
3、Content-Type : multipart/form-data 。
它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
1、Content-Type:application/x-www-form-urlencoded json请求后端
my-vue-app/src/components/HelloWorld.vue
<template>
<div class="hello">...</div>
</template>
<script>
import axios from "axios";
import qs from 'qs';
export default {
name: "HelloWorld",
created() {
// 对象data的属性名uname和upwd引号可加可不加
let data = {uname:"dingding",upwd:"123456"};
axios.post("/data.json",qs.stringify({ data }))
.then(res=>{
console.log(res);
})
},
};
</script>
因为我这里是post了一个json文件所以会有报错,不过没关系,我们查看一下这条post请求的请求头,发现确实是application/x-www-form-urlencoded,请求参数也可以看到
2 Content-Type: multipart/form-data(常用于表单提交(图片上传、文件上传))
<template>
<div className="hello">......</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
let data = {uname: "dingding", upwd: 123456};
let formData = new FormData();
for (let key in data) {
formData.append(key, data[key]);
}
console.log(formData);
axios.post("/date.json", formData).then((res) => {
console.log(res.data);
});
},
};
</script>
<style scoped>
</style>
3、Content-Type: application/json
方式一 、请求别名的使用
axios.post(url[, data[, config]]) 用于发送数据 `data`对象是作为请求主体被发送的数据
post 无参数请求
<template>
<div class="hello">......</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//把get无参请求的get改为post即可
axios.post("/data.json").then(res=>{
console.log(res)
});
},
};
</script>
<style scoped>...</style>
post 带参数 查询字符串形式
<template>
<div class="hello">......</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//发送post请求携带参数,直接使用"uname=dingding&upwd=123456"
axios.post("/data.json", "uname=dingding&upwd=123456").then(res=>{
console.log(res)
});
},
};
</script>
<style scoped>...</style>
post 带参数 对象形式
<template>
<div class="hello">......</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
//发送post请求携带参数,直接使用"uname=dingding&upwd=123456"
axios.post("/data.json", "uname=dingding&upwd=123456").then(res=>{
console.log(res)
});
},
};
</script>
<style scoped>...</style>
方式二:通过向axios传递相关配置来创建请求
<template>
<div class="hello">......</div>
</template>
<script>
import axios from "axios";
export default {
name: "HelloWorld",
created() {
let data = {uname:"dingding",upwd:123456};
axios({
method:'post',
url:'/data.json',
// 与get请求使用params不同的是,post请求使用data属性
data:data
}).then(res=>{
console.log(res)
})
},
};
</script>
<style scoped>...</style>
注意:别名方式和data方式的相关请求信息
- 请求地址Request URL: http://localhost:8080/data.json,
- 请求头中Content-Type: application/json
- 参数形式:{uname: "dingding", upwd: 123456}
五、put和patch方法
put和patch请求与post请求用法一样类似,同样有x-www-form-urlencoded、applicition/json和form-data,只有method不同,其他相同
let data = {uname:"dingding",upwd:123456};
// axios.put(url[, data[, config]]) 用法同post类似,用于修改数据
axios.put("/data.json", data).then(res=>{
console.log(res)
});
let data = {uname:"dingding",upwd:123456};
// axios.patch(url[, data[, config]]) 用法同post类似,用于修改数据
axios.patch("/data.json", data).then(res=>{
console.log(res)
});
六、delete方法
axios.delete(url[, config])与axios.get(url[, config])用法基本相似,但是作用不同,它用于删除数据,同get方法一样也可以有几种写法
delete请求有时候需要把参数拼接到URL上,有时候像post请求那样把参数放在请求体里面。至于具体怎么调用,需要和后端商量好
方式一:get - params
// 使用别名法
// 传参的2种形式,同get
1、params
axios
.delete("/data.json", {
params: {
id: 12
}
})
.then(res => {
console.log(res, "delete");
});
2、查询字符串形式,即参数拼接到url里
axios
.delete("/data.json?id=2", {
params: {
id: 12
}
})
.then(res => {
console.log(res, "delete");
});
// 不使用别名法 —————通过向axios传递的相关配置创建请求__axios(config)
let params = {
id: 5
};
axios({
method:'delete',
url:'/data.json',
params:params
}).then(res=>{
console.log(res)
})
方式二:post - data
使用类似post请求方式,把axios.delete()中的params改为data,这样请求会把内容放入请求体里面
// 使用别名法
// data
axios
.delete("/data.json", {
data: {
id: 5
}
})
.then(res => {
console.log(res);
});
// 不使用别名法 ————通过传递相关配置创建请求
let data = {
id: 5
};
axios({
method:'delete',
url:'/data.json',
data:data
}).then(res=>{
console.log(res)
})
注意:delete请求中,get-params方式和post-data方式相关请求信息的区别
- params方式会将请求参数拼接在URL上面,Request URL: http://localhost:8080/data.json?id=5
- 参数形式:id:5
- Content-Type: text/html; charset=utf-8