Vue组件模板渲染过程,这是道面试题,没有回答上来,麻烦会的回答一下
Vue组件模板渲染过程通常包括以下几个步骤:
解析模板:Vue会解析组件模板,找到所有的指令和表达式,并对它们进行相应的处理。
创建渲染函数:Vue会将解析后的模板转换成渲染函数,并将其存储在内存中,以便后续的渲染操作使用。
渲染组件:当组件需要被渲染时,Vue会调用该组件的渲染函数,并将其返回的虚拟DOM树渲染到真实的DOM中。
响应式更新:当组件的数据发生变化时,Vue会根据数据的变化重新渲染组件。Vue使用虚拟DOM进行比对,找到需要更新的部分,然后将其更新到真实的DOM中。
总的来说,Vue组件的渲染过程是一个将模板解析成渲染函数,并将虚拟DOM渲染到真实DOM的过程。在这个过程中,Vue会自动管理组件的响应式更新,确保组件的数据和视图保持同步。
用自己话进行描述会更好,
Vue组件渲染和更新的过程简单地概况为以下几个步骤:
初始化组件实例:在渲染一个组件之前,Vue会创建一个组件实例,并将组件的选项对象进行合并、处理,最终形成一个组件实例的配置对象。
渲染组件:Vue将组件实例的配置对象转化为一个渲染函数,并执行该渲染函数,生成一个虚拟DOM树。此时,Vue会对虚拟DOM树进行初次渲染,将组件显示在页面上。
监听数据变化:当组件实例中的响应式数据发生变化时,Vue会立即检测到这些变化,并重新计算组件的渲染函数,生成一个新的虚拟DOM树。
对比新旧虚拟DOM树:Vue会将新生成的虚拟DOM树和上一次渲染时生成的虚拟DOM树进行比较,找出需要更新的部分。
更新组件:Vue会将需要更新的部分进行精细化地修改,使组件达到更新的效果。如果有需要,Vue会重新渲染整个组件。
下面将给出一个具体的配置方法:
/* 1. http.js文件(./src/request/http.js)*/
import axios from 'axios';
import QS from 'qs';
import router from '../router'
/* 配置请求基本信息 */
axios.defaults.timeout = 20000; // 超时时间
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'; //请求头类型,form表单提交
/* 配置不同的地址环境,下面根据不同的项目来说明 */
const devUrl = {
"item-1":"http://dev_ip:port/item_name_1",
"item-2":"http://dev_ip:port/item_name_2".
...
"item-n":"http://dev_ip:port/item_name_n"
}
const testUrl = {
"item-1":"http://test_ip:port/item_name_1",
"item-2":"http://test_ip:port/item_name_2".
...
"item-n":"http://test_ip:port/item_name_n"
}
const prodUrl = {
"item-1":"http://prod_ip:port/item_name_1",
"item-2":"http://prod_ip:port/item_name_2".
...
"item-n":"http://prod_ip:port/item_name_n"
}
const baseUrl = {
"development":devUrl,
"testing":testUrl,
"production":prodUrl
}
/* 从build中获取到构建的环境类型,进而获取到确切的地址配置 */
/* process.env.NODE_ENV 来自于 build(./src/build/build.js)中的配置信息。*/
const url = baseUrl[process.env.NODE_ENV]
/* 配置请求拦截器 */
axios.interceptors.request.use(
config => {
// 每次发送请求之前判断是否存在token
// 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
// 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
let token = localStorage.getItem("token");
for(let item in url){
if (config.url.includes(item)) {
let realUrl = config.url.replace(item,"")
config.url = url[item] + realUrl;/*拼接完整请求路径*/
break
}
}
token && (config.headers.token = token);
return config;
},
error => {
return Promise.error(error);
})
/* 配置响应拦截器,具体项目,具体定制*/
axios.interceptors.response.use(
response => {
// 如果返回的状态码为200,说明接口请求成功,可以正常拿到数据
// 否则的话抛出错误
if(response.data.flag==='-99'){ // -99 即后台权限验证失败的返回值,则返回到登陆页面
localStorage.removeItem('token')
router.replace({path: '/login'});
return
}
if (response.status === 200) {
return Promise.resolve(response);
} else {
return Promise.reject(response);
}
},
// 服务器状态码不是2开头的的情况
// 这里可以跟你们的后台开发人员协商好统一的错误状态码
// 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
// 下面列举几个常见的操作,其他需求可自行扩展
error => {
if (error.response.status) {
switch (error.response.status) {
// 401: 未登录
// 未登录则跳转登录页面,并携带当前页面的路径
// 在登录成功后返回当前页面,这一步需要在登录页操作。
case 401:
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
break;
// 403 token过期
// 登录过期对用户进行提示
// 清除本地token和清空vuex中token对象
// 跳转登录页面
case 403:
Toast({
message: '登录过期,请重新登录',
duration: 1000,
forbidClick: true
});
// 清除token
localStorage.removeItem('token');
store.commit('loginSuccess', null);
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
setTimeout(() => {
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
});
}, 1000);
break;
// 404请求不存在
case 404:
Toast({
message: '网络请求不存在',
duration: 1500,
forbidClick: true
});
break;
// 其他错误,直接抛出错误提示
default:
Toast({
message: error.response.data.message,
duration: 1500,
forbidClick: true
});
}
return Promise.reject(error.response);
}
})
/* 配置get方法,可以直接使用this.get(url,param) 进行调用*/
export function get(url, params) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
}).then(res => {
resolve(res.data);
}).catch(err => {
reject(err.data)
})
});
}
/* 配置post方法(form表单提交数据方式),可以直接使用this.post(url,param) 进行调用*/
export function post(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, QS.stringify(params, {indices: false}))
.then(res => {
resolve(res.data);
})
.catch(err => {
reject(err.data)
})
});
}
/* 配置postJson方法(json数据提交方式),替换配置请求头类型,可以直接使用this.postJon(url,param) 进行调用*/
export function postJson(url, params) {
return new Promise((resolve, reject) => {
axios.post(url, JSON.stringify(params),{
headers:{
'Content-Type': 'application/json'
}
}).then(res => {
resolve(res.data);
}).catch(err => {
reject(err.data)
})
});
}
/* 配置postFormData方法(文件file数据提交方式),替换配置请求头类型,可以直接使用this.postFormData(url,param) 进行调用*/
export function postFormData(url,formData){
return new Promise((resolve, reject) => {
axios.post(url, formData,{
headers:{
'Content-Type' :'multipart/form-data'
}
}).then(res => {
resolve(res.data);
}).catch(err => {
reject(err.data)
})
});
}
import {get,post,postJson,postFormData} from "@/request/http";
Vue.prototype.post = post;
Vue.prototype.get = get;
Vue.prototype.postJson = postJson
Vue.prototype.postFormData = postFormData
Vue.prototype.fetch = fetch;
this.post('item_1/请求地址',params)
.then((resp)=>{
}).error((err)=>{
})