Vue组件模板渲染过程

Vue组件模板渲染过程,这是道面试题,没有回答上来,麻烦会的回答一下

Vue组件模板渲染过程通常包括以下几个步骤:

解析模板:Vue会解析组件模板,找到所有的指令和表达式,并对它们进行相应的处理。

创建渲染函数:Vue会将解析后的模板转换成渲染函数,并将其存储在内存中,以便后续的渲染操作使用。

渲染组件:当组件需要被渲染时,Vue会调用该组件的渲染函数,并将其返回的虚拟DOM树渲染到真实的DOM中。

响应式更新:当组件的数据发生变化时,Vue会根据数据的变化重新渲染组件。Vue使用虚拟DOM进行比对,找到需要更新的部分,然后将其更新到真实的DOM中。

总的来说,Vue组件的渲染过程是一个将模板解析成渲染函数,并将虚拟DOM渲染到真实DOM的过程。在这个过程中,Vue会自动管理组件的响应式更新,确保组件的数据和视图保持同步。

用自己话进行描述会更好,
Vue组件渲染和更新的过程简单地概况为以下几个步骤:

img

初始化组件实例:在渲染一个组件之前,Vue会创建一个组件实例,并将组件的选项对象进行合并、处理,最终形成一个组件实例的配置对象。
渲染组件:Vue将组件实例的配置对象转化为一个渲染函数,并执行该渲染函数,生成一个虚拟DOM树。此时,Vue会对虚拟DOM树进行初次渲染,将组件显示在页面上。
监听数据变化:当组件实例中的响应式数据发生变化时,Vue会立即检测到这些变化,并重新计算组件的渲染函数,生成一个新的虚拟DOM树。
对比新旧虚拟DOM树:Vue会将新生成的虚拟DOM树和上一次渲染时生成的虚拟DOM树进行比较,找出需要更新的部分。
更新组件:Vue会将需要更新的部分进行精细化地修改,使组件达到更新的效果。如果有需要,Vue会重新渲染整个组件。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7748133
  • 这篇博客也不错, 你可以看下vue复选框的用法,单个,多个复选框(简单demo代码全)点击复选框事件
  • 除此之外, 这篇博客: vue必知必会,Vue在工程项目中常用知识点梳理与总结。中的 3.1 基本请求配置 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    下面将给出一个具体的配置方法:

    1. 在src目录下,新建request目录,新建http.js文件
    /* 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)
          })
      });
    }
    
    1. 在main的js中引入文件
    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;
    
    1. 具体方法中使用
    this.post('item_1/请求地址',params)
    	.then((resp)=>{
    	
    	}).error((err)=>{
    	
    	})
    
  • 您还可以看一下 马金聚老师的Vue全家桶技术+商城项目实战+源码解析课程中的 Vue开篇介绍小节, 巩固相关知识点

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^