当前位置: 首页 > article >正文

vue常见题型(10-15)

文章目录

  • 11.Vue中的$nextTick有什么作用
    • 11.1.是什么?
      • 11.1.1场景
    • 11.2.场景
  • 12.vue实例挂载的过程(流程)
    • 12.1.思考
  • 13.diff算法
    • 13.1.是什么
    • 13.2.比较方式
    • 13.3.小结
  • 14.组件和插件有什么区别?
    • 14.1.组件是什么
    • 14.2.插件是什么
    • 14.3.区别
      • 14.3.1.编写形式
        • 14.3.1.1.编写组件
        • 14.3.1.2.编写插件
      • 14.3.2.注册形式
        • 14.3.2.1.组件注册
        • 14.3.2.2.插件注册
    • 14.4.使用场景
  • 15.`Vue`项目中跨域问题
    • 15.1.跨域是什么
    • 15.2.如何解决
      • 15.2.1.CORS
      • 15.2.2.Proxy
        • 方案一
        • 方案二
        • 方案三


11.Vue中的$nextTick有什么作用

11.1.是什么?

🍚定义:在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用此方法,获取更新后的DOM
Vue此框架在更新DOM时是异步执行的。当数据发生变化,将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新。
结构

<div id="app">{{dataListMessage}}</div>

构建实例

const vm = new Vue({
  el:"#app",
  data:{
    dataListMessage:"原始值" 
  }
})

🍿修改值

this.dataListMessage = "新值1"
this.dataListMessage = "新值2"
this.dataListMessage = "新值3"

🍕此时获取页面最新的DOM节点,却发现获取到的是原先的值

console.log(vm.$el.textContent)//原始值

🌭这是因为dataListMessage 数据在发现变化时,vue并不会立刻去更新DOM,而是将修改数据的操作放在了一个异步操作队列中
如果一直修改相同数据,异步操作队列还会进行去重。
等待同一事件循环中的所有数据变化完成之后,会将队列中的事件拿来进行处理,进行DOM的更新。

11.1.1场景

{{num}}
for(let i=0;i<100000;i++){
  num = i
}

🥓如果没有nextTick更新机制,那么num每次更新值都会触发视图更新(更新10万次),有nextTick机制,只需要更新一次,所以 nextTick 本质是一种优化策略

11.2.场景

🥗如果想要在修改数据后立刻得到更新后的DOM结构,可以使用Vue.nextTick()
第一个参数:回调函数(获取最近的DOM结构)
第二个参数:执行函数上下文

//修改数据
vm.dataListMessage = "111"
//dom还未更新
console.log(vm.$el.textContent)//原始的值
Vue.nextTick(function(){
  //dom更新了
  console.log(vm.$el.textContent)//111
})

🥞组件内使用vm.$nextTick()实例方法只需要通过this.$nextTick(),回调函数中的this将自动绑定到当前的Vue实例上

this.dataListMessage = "222新值"
console.log(this.$el.textContent)//“原先的值”
this.$nextTick(function(){
  console.log(this.$el.textContent)
})

🥟🥟$nextTick会返回一个Promise对象,用async/await简化

12.vue实例挂载的过程(流程)

12.1.思考

🍔new Vue() 这个过程内部做了什么? 是如何完成数据的绑定;如何将数据渲染到视图的
调用_init方法

  • 定义$set、$get、$delete、$watch等方法
  • 定义$on、$off、$emit、$off等事件
  • 定义_update、$forceUpdate、$destroy生命周期
    调用$mount进行页面的挂载
  • 通过mountComponent方法
  • 定义updateComponent更新函数
  • 执行render生成虚拟DOM
  • _update将虚拟DOM生成真实DOM结构,并渲染到页面上

13.diff算法

13.1.是什么

🍔是一种通过同层的树节点进行比较的高效算法
特点:

  • 只会在同层进行比较,不会跨层级比较
  • 在比较的过程中,循环从两边向中间比较
    在很多场景下都有应用,在vue中,作用于虚拟dom渲染成真实dom的新旧VNode节点比较

13.2.比较方式

🥟整体策略:深度优先、同层比较

  • 只会在同层级进行比较

13.3.小结

  • 当数据发生改变时,订阅者watcher会调用patch给真实的DOM打补丁
  • 通过isSameVnode进行判断,相同则调用patchVnode方法
    patchVnode做了以下系列操作
  • 找到对应的真实dom,称为el
  • 如果都有文本节点且不相等,将el文本节点设置为Vnode的文本节点
  • 如果oldVnode有子节点而没有VNode,则删除el子节点
  • 如果oldVnode没有子节点而有VNode,则将VNode的子节点真实化后添加到el
  • 如果两者都有子节点,则执行updateChildren函数比较子节点
    🍞updateChildren主要做了以下操作
  • 设置新旧VNode的头尾指针
  • 新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程,调用createElem创建一个新节点,从哈希表寻找key一致的VNode节点再分情况操作。

14.组件和插件有什么区别?

14.1.组件是什么

🍔回顾以前对组件的定义:
🥞是把图形、非图形的各种逻辑抽象为一个统一的概念来实现开发的模式,在vue中每一个.vue文件都可以视为一个组件。
🍿优势:

  • 能降低整个系统的耦合度,在保持接口不变的情况下,可以替换不同的组件快速完成需求
  • 调试方便,整个系统是通过组件组合起来的,在有问题时,可以用排除法直接移除组件,进行调试
  • 提高可维护性,每个组件职责单一,并且组件在系统中是被复用的,所有对代码进行优化可获得系统的整体升级。

14.2.插件是什么

🌯插件通常用来为 Vue添加全局功能。插件的功能范围没有严格的限制-一般有以下几种

  • 添加全局方法或属性。如vue-custom-element
  • 添加全局资源:指令/过滤器/过渡等。如vue-touch
  • 通过全局混入来添加一些组件选项。如vue-router
  • 添加实例方法,通过把它们添加到Vue.prototype上实现
  • 一个库,提供自己的API,同时提供上面提到的一个或多个功能。如vue-router

14.3.区别

🥟以下几个方面:

  • 编写形式
  • 注册形式
  • 使用场景

14.3.1.编写形式

14.3.1.1.编写组件

🍚编写一个组件,常见的vue单文件的这种格式,每一个.vue文件是一个组件

<template>
</template>
<script>
  export default{...}
</script>
<style>
</style>

也可以通过template属性来编写一个组件,如果组件内容多,可以在外部定义template组件内容,反之,可直接写在template属性上

<template id="id">
  <div>component!</div>
</template>
Vue.component('componentA',{
  template:'#id',
  template:`<div>component</div>`
})
14.3.1.2.编写插件

🧀插件的实现应该暴露一个install方法,第一个参数是Vue构造器,第二个参数是一个可选的选项对象

emitFun.install = function(Vue,options){
	//1.添加全局方法或属性
	Vue.addGlobalFun = function(){
	  //... 
	}
	//2.添加全局资源
	Vue.directive('zkshyy',{
	  bind(el,binding,vnode,oldVnode){
	    //... 
	  } 
	})
	//3.注入组件选项
	Vue.mixin({
	  created:function(){
	    //... 
	  } 
	})
	//4.添加实例方法
	Vue.prototype.$addGlobalFun = function(options){
	  //... 
	}
}

14.3.2.注册形式

14.3.2.1.组件注册

🚗vue组件注册分为全局和局部注册
全局:通过Vue.component方法,第一个参数为组件名称,第二个参数为传入的配置项

Vue.component('com-name',{})

局部:只需在用到的地方通过components属性注册一个组件

const comp1 = {...} //定义一个组件
export default{
  components:{
    comp1 //局部注册 
  }
}
14.3.2.2.插件注册

🎉通过Vue.use()的方式进行注册(安装),第一个参数为名字,第二个参数是可选择的配置项

Vue.use(插件名字,{})

需要注意:
注册插件时,需要调用new Vue() 启动应用之前完成
Vue.use会自动阻止多次注册相同插件,只会注册一次

14.4.使用场景

🧨组件(component)用来构成App的业务模块,它的目标是App.vue
🎉插件(plugin)用来增加你的技术栈的功能模块,它的目标是Vue本身

15.Vue项目中跨域问题

15.1.跨域是什么

🥞本质是浏览器基于同源策略的一种安全手段。
同源策略,是一种约定,是浏览器最核心同时最基本的安全功能。
同源,即指在同一个域,具有以下三个相同点

  • 协议相同
  • 主机相同
  • 端口相同
    反之非同源请求,就会产生跨域。一旦跨域,接口是已经把数据返回回来了,是浏览器的限制,而获取不到数据。

15.2.如何解决

🥫列举三种方式

  • JSONP
  • CORS
  • Proxy
    在项目中,主要针对CORSProxy这两种方案进行展开

15.2.1.CORS

🚕CORS是一个系统,由一系列传输的HTTP头组成,决定浏览器是否阻止前端JavaScript代码获取跨域请求的响应。
只需要增加一些HTTP头,让服务器能声明允许的访问来源,只要后端实现了cors,就实现了跨域。
koa框架举例
添加中间件,直接设置Access-Control-Allow-Origin响应头,

app.use(async(ctx,next)=>{
  ctx.set('Access-Control-Allow-Origin', '*');
  ctx.set('Access-Control-Allow-Headers', 'Content-Type, Content-Length, A
uthorization, Accept, X-Requested-With , yourHeaderFeild');
  ctx.set('Access-Control-Allow-Methods', 'PUT','POST','GET','DELETE','OPTIONS');
  if(ctx.method == 'OPTIONS'){
     ctx.body = 200;
  }else{
    await next(); 
  }
})

🐱‍🏍Access-Control-Allow-Origin 设置为*其意义不大,实际应用上,上线前会将Access-Control-Allow-Origin值 设为目标host

15.2.2.Proxy

🍿代理,是一种特殊的网络服务,允许一个通过这个服务与另一个网络终端进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。
一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。

方案一

如果是用vue-cli脚手架工具搭建的项目,可通过webpack为我们起一个本地服务器作为请求的代理对象。
通过该服务器转发请求至目标服务器,得到结果再转发给前端,但是,最终发布上线时如果web应用和接口服务器不在一起仍会跨域
vue.config.js文件,配置以下代码

amodule.exports = {
  devServer:{
    host:'127.xxx',
    port:8083,
    open:true,
    proxy:{
     '/api':{
        target:"",//目标服务器地址
        changeOrigin:true,//是否跨域
        pathRewrite:{
           '^/api':""
        }
      }
    } 
  }
}

🚜通过axios发送请求,配置请求的根路径

axios.defaults.baseRUL = '/api'
方案二

还可通过服务端实现代理请求转发
express框架为例

var express = require('express');
const proxy = require('http-proxy-middleware')
const app = express()
app.use(express.static(_dirname + '/'))
app.use('/api',proxy({target:'http://localhost:8080',changeOrigin:false}));
module.exports = app
方案三

🥓通过配置nginx实现代理

server{
  listen 80;
  # server_name www.josephxia.com;
  location / {
    root /var/www/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html; 
  }
  location /api{
    proxy_pass http://127.0.0.1:3000;
    proxy_redirect off;
    proxy_set_header Host  $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 
  }
}

http://www.kler.cn/a/390661.html

相关文章:

  • Java设计模式面试题及参考答案
  • activiti5基础和springboot整合
  • 金价大跌,特朗普胜选或成导火索
  • Gsensor加速度传感器数据异常及概率性卡死
  • Vim9 语法高亮syntax 在指定的缓冲区和窗口执行命令
  • JUC-locks锁
  • 在AutoDL上部署一个自定义的Python环境并在pycharm上使用
  • Java面试要点06 - static关键字、静态属性与静态方法
  • JavaScript如何操作HTML:动态网页构建指南
  • 数据结构---排序总结
  • Rust实战项目与未来发展——跨平台应用开发项目实践
  • SpringMVC学习记录(三)之响应数据
  • Webserver(5.6)服务器压力测试
  • Cross Modal Transformer: Towards Fast and Robust 3D Object Detection
  • Linux - 弯路系列1:xshell能够连接上linux,但xftp连不上(子账号可以连接,但不能上传数据)
  • 工位管理智能化:Spring Boot企业级平台
  • 如何自己实现事件的订阅和发布呢?
  • IP、网关、子网掩码的验证逻辑及程序(.Net)
  • 亚信安全新一代WAF:抵御勒索攻击的坚固防线
  • perf抓取compass能解析的日志
  • 深入了解区块链:Web3的基础架构与发展
  • 【Android、IOS、Flutter、鸿蒙、ReactNative 】文本Text显示
  • Pytorch如何精准记录函数运行时间
  • 2024下半年软考中项考试成绩多久出来?成绩合格标准是多少?
  • MySQL的ibtmp1文件详解及过大处理策略
  • laravel php artisan storage:link 后通过nginx代理访问图片404 not found问题