当前位置:   article > 正文

收集的问答_vue 调用视频接口 没有销毁

vue 调用视频接口 没有销毁

new

new 关键字在 JavaScript 中用于调用构造函数,通过 new 关键字调用构造函数可以创建一个新的对象。构造函数可以看作是用来初始化对象的特殊函数,它会为新对象设置属性和方法。当使用 new 关键字和构造函数一起调用时,会创建一个空对象,并将这个空对象绑定到构造函数中的 this 关键字。然后构造函数中的代码会初始化这个对象的属性和方法,最终返回这个新的对象。通过这种方式我们可以轻松地创建多个拥有相似属性和方法的对象,实现了代码的重用和结构的清晰化。”

Foo明明只是一个函数,可是为什么new Foo()执行后会突然返回一个对象呢?
我们从结果出发可以推断出,既然返回了一个对象,那么这事肯定和对象有关系。

实际上new帮我们做了这样几件事:

  1. 帮我们创建了一个空对象,例如:obj;
  2. 将空对象原型的内存地址__proto__指向函数的原型对象;(这里涉及到了原型链的知识)
  3. 利用函数的call方法,将原本指向window的绑定对象this指向了obj。(这样一来,当我们向函数中再传递实参时,对象的属性就会被挂载到obj上。)
  4. 利用函数返回对象obj。
  1. function Foo(name) {
  2. this.name = name;
  3. return this;
  4. }
  5. var obj = {};
  6. obj.__proto__ = Foo.prototype;
  7. // Foo.call(obj, 'mm');
  8. var foo = Foo.call(obj, 'mm');
  9. console.log(foo);

 

https://www.cnblogs.com/buildnewhomeland/p/12797537.html

垃圾回收机制

垃圾回收机制
作用:清除不在使用的对象,腾出内存空间

  • 对象不再被引用的时候是垃圾;
  • 对象不能从根上访问到时也是垃圾;

引用计数法 用了+1没用–1 =0就会触发垃圾回收机制 有bug循环的时候不会为0一直不会回收 
标记清除法 所有对象为0从根对象开始遍历存货的为1 为0的清除

jsonp跨域原理

jsonp是一种跨域通信的手段,它的原理其实很简单:

  1. 首先是利用script标签的src属性来实现跨域。

  2. 通过将前端方法作为参数传递到服务器端,然后由服务器端注入参数之后再返回,实现服务器端向客户端通信。

  3. 由于使用script标签的src属性,因此只支持get方法

前端-多线程处理Web Workers

前端-多线程处理Web Workers - 知乎

Echarts

 title:{}//标题组件
        tooltip:{},//提示框组件
        yAxis:[],//y轴
        xAxis:[],//x轴
        legend:{},//图例组件
        grid:{},//内绘网格
        toolbox:{},//工具
        series:[],//数据有关
        calculable:true//可计算特性

        其中,颜色标注的三部分是成功绘制一个Echarts图表至少包含的部分。

Echarts常用配置项_echarts配置项_zhangxiaobai___的博客-CSDN博客

echarts自适应
当窗口的大小改变时,ECharts 的图表容器也会随之改变,从而影响图表的大小。通过使用 resize 函数,可以重新绘制图表,从而实现自适应图表大小。

使用 resize()函数
resize0函数是ECharts API提供的函数,接受一个重绘数据的参数,该参数可以是“true”或“false”。当参数为“true”时,将重新绘制图表;当参数为“false”时,不会重新绘制图表。

项目两小时未动未发送请求,退出登录

场景 vue
设置 请求的token在请求头中 请求后最新的token在返回头中

java后台服务 需要拦截器 每次请求查看前端heards里边有没有你设置的token如果有而且没有过期是正确的 那就重新生成最新的token 放在返回的heards里边

在vue的main.js中写入拦截器 拦截所有请求 查看返回的heards里边是否存在token 如果存在更新你本地的token

  1. methods: {
  2. testTime() {
  3. this.currentTime = new Date().getTime(); //更新当前时间
  4. if (this.currentTime - parseInt(localStorage.getItem('lastTime')) > this.timeOut) { //判断是否超时(超时自动退出登录)
  5. this.cleanAllCache(); //清除所有缓存数据
  6. //下面就可以按自己的方式跳转到登录页
  7. window.location.href = `${process.env.VUE_APP_OAUTH_URL}${this.OAUTH}logout?redirect_uri=${window.location.origin}${this.FOLDER_SUFFIX}`;
  8. }
  9. },
  10. setLastTime() {
  11. localStorage.setItem('lastTime', new Date().getTime().toString());//更新操作时间
  12. }
  13. }
  14. created() {
  15. //保存上次进去的时间戳
  16. this.setLastTime();
  17. //用定时器监听是否长时间未操作
  18. window.setInterval(this.testTime, 5 * 1000);
  19. }

微信小程序分层

微信小程序的底层架构原理,及如何做性能优化_小程序分层_浮游本尊的博客-CSDN博客

git代码回滚

拜托,不要再问我Git如何回滚代码 - 知乎

  1. 使用git log命令,查看分支提交历史,确认需要回退的版本
  2. 使用git reset --hard commit_id命令,进行版本回退
  3. 使用git push origin命令,推送至远程分支
回退上个版本:git reset --hard HEAD^ 

【注:HEAD是指向当前版本的指针,HEAD^表示上个版本,HEAD^^表示上上个版本】

reset和revert都可以用来回滚代码。但他们是有区别的,准确来说,reset是用来"回退"版本,而revert是用来"还原"某次或者某几次提交。

$set原理

Vue.set()是将set函数绑定在Vue构造函数上,this.$set()是将set函数绑定在Vue原型上
set函数接收三个参数分别为 target、key、val,其中target的值为数组或者对象
我们平时调用普通数组的push、pop等方法是调用的Array原型上面定义的方法, arrJs的原型是指向Array.prototype,也就是说 arrJs.__proto__ == Array.prototype 。
但是在vue的数组中,我们发现arrVue的原型其实不是指向的Array.prototype,而是指向的一个对象,这个对象上面只有7个push、pop等方法,并且这个对象的原型才是指向的Array.prototype。所以我们在vue中调用数组的push、pop等方法时其实不是直接调用的数组原型给我们提供的push、pop等方法,而是调用的这个对象给我们提供的push、pop等方法,因为vue对数组进行了处理让我们调用数组的方式是响应式的

数组的实现原理
首先if判断当前target是不是数组,并且key的值是有效的数组索引。然后将target数组的长度设置为target.length和key中的最大值,我们发现这里直接调用了target.splice(key, 1, val),splice也是vue提供的7个方法中的一种,Vue.set数组实现的原理:其实Vue.set()对于数组的处理其实就是调用了splice方法

对象的实现原理
先判断如果key本来就是对象中的一个属性,并且key不是Object原型上的属性。说明这个key本来就在对象上面已经定义过了的,直接修改值就可以了,可以自动触发响应,vue给响应式对象都加了一个 __ob__ 属性,Observer 实例,如果一个对象有这个 __ob__ 属性,那么就说明这个对象是响应式对象,我们修改对象已有属性的时候就会触发页面渲染,真正处理对象的地方。 defineReactive(ob.value, key, val) 的意思是给新加的属性添加依赖,以后再直接修改这个新的属性的时候就会触发页面渲染。

Vuex中mutation为什么是同步的action为什么是异步

如果我们在mutation中写了异步,commit在触发mutation事件时,异步的回调函数不知道是什么时候执行的,所以在devtools中难以追踪变化

actions 可以做异步操作,但是并不是直接修改数据,而是通过提交mutations 里面的方法

父组件操作子组件的方法

ref 

  1. <el-button type="primary" @click="parentOpenDialog">打开弹窗</el-button>
  2. //父组件使用子组件,写上ref=""
  3. <dialog ref="dialog"></dialog>
  4. //父组件methods
  5. parentOpenDialog() {
  6. this.$nextTick(() => {
  7. this.$refs["dialog"].openDialog();
  8. });
  9. },
  10. //子组件
  11. openDialog() {
  12. this.dialogVisible = true;
  13. }

通过组件的$emit、$on方法

  1. <Button @click="handleClick">点击调用子组件方法</Button>
  2. <Child ref="child"/>
  3. //父组件
  4. methods: {
  5. handleClick() {
  6. this.$refs.child.$emit("childmethod") //子组件$on中的名字
  7. },
  8. }
  9. //子组件
  10. mounted() {
  11. this.$nextTick(function() {
  12. this.$on('childmethods', function() {
  13. console.log('我是子组件方法');
  14. });
  15. });
  16. },

微信小程序获取appId

let appId=wx.getAccountInfoSync().miniProgram.appId

asyan await

  • async/await 更加优雅的异步编程的写法
    1.它是消灭异步回调的终极武器
    2.它是同步语法,也就是用同步的写法写异步的代码
  • 分别使用 .then 和 await 来获取结果
  • 区别
    1.await 完全没有回调函数
    2.await 是同步写法,异步操作
    3.await 后面不仅仅可以接 promise对象,还可以接 async 函数

async/await的使用方法 - 简书

mixin

Vue 混入(mixin)详细介绍(可复用性、全局混入)_vue mixin_前端不释卷leo的博客-CSDN博客

一.什么是mixins(混入)? mixins是对vue组件的一种扩展,将一些公用的常用数据或者方法,构建一个可被混入的数据结构,被不同的vue组件进行合并,就可以在不同的vue组件中使用相同的方法或者基础数据。

二.作用:
1.更高效的实现组件内容的复用
2.将组件内部data,method等与父组件相应内容进行合并,相当于在引入后,父组件的各种属性,方法进行了扩充
3.对数据,对象进行合并,要以组件为优先

三.本质:
其实就是javaScript的深拷贝 对"对象"的"值"的传递,复制,合并
类似于js中封装的一些公用的方法

this.setDate的原理和限制

this.setData 是一个用于修改页面数据的函数。它的作用是将传入的对象的属性和值应用到小程序页面的数据对象上,并触发页面的重新渲染。

改变 this.data是同步,换句话说,若直接修改 this.data 而不调用 this.setData方法,是无法改变页面的状态的,还会造成数据不一致

当逻辑层data数据渲染到界面的时候,逻辑层的数据需要经过系统层,当系统层接收到这个逻辑层的数据后

系统层在把数据转发给渲染层,然后在渲染层展示出来,在这个过程当中是异步的

setData 将数据从逻辑层发送到视图层是异步,同时改变对应的this.data的值是同步,它并不是实时的,这也导致了必须要考虑性能的因素

本地存储数据不是响应式的如何变成响应式

 由于他不是一个具有属性的对象

首先尝试经过重写localStorage的方法来修复上面的demo,以追踪那些组件实例请求了localstorage的数据项。

Provide和inject

为了避免重复声明props 、一般用于封装组件库,在父组件中使用 provide 抛出数据,可在任意隔代组件下直接使用 inject 获取数据、实现页面刷新 

本身不是响应式的vue2函数返回一个对象可以通过写成对象形式,或者函数形式变成响应式的函数形式的话可以用计算属性去处理一下直接返回结果,Vue3可以通过ref和reactive

provide/inject 不是可响应的
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的

实现全局传递

provide/inject 只能从祖先传递给后代,但是可以通过在App.vue绑定provide,所有的子组件就都能注入inject,从而达到全局传递。

  1. data() {
  2. return {
  3. message:"hello",
  4. obj:{
  5. message:"hello"
  6. }
  7. },
  8. provide(){
  9. return{
  10. message:()=>this.message,
  11. obj:this.obj
  12. }
  13. }
  14. inject:['message']
  15. //inject:['obj']

实现页面刷新

1 . 用vue-router重新路由到当前页面,页面是不进行刷新的
2 . 采用window.reload(),或者router.go(0)刷新时,整个浏览器进行了重新加载,闪烁,体验不好

那我们怎么做呢?
跟上面的原理差不多,我们只在控制路由的组件中写一个函数(使用 v-if 控制 router-view 的显示隐藏,这里的原理不作赘述),然后把这个函数传递给后代,然后在后代组件中调用这个方法即可刷新路由啦。

  1. //app.vue
  2. <router-view v-if="isShowRouter"/>
  3. export default {
  4.  name: 'App',
  5.  provide(){
  6.   return{
  7.    reload:this.reload
  8.   }
  9.  },
  10.  data(){
  11.   return{
  12.    isShowRouter:true,
  13.   }
  14.  },
  15.  methods:{
  16.   reload(){
  17.    this.isShowRouter = false;
  18.    this.$nextTick(()=>{
  19.     this.isShowRouter = true;
  20.    })
  21.   }
  22.  }
  23. }
  24. //后代组件
  25. export default {
  26.  inject:['reload'], 
  27. }

插槽区别 作用域插槽特点

匿名插槽
在父组件中   子组件引用的中间也有内容 有代码  父组件可以决定里面html代码的样式 还有数据内容
子组件   使用  slot 插槽标签  可以上父组件传来的内容进行展示 至于在哪里展示 由子组件决定

具名插槽
这个和匿名插槽 区别就是这个是由名字  在标签上  加一个slot 属性 起一个自定义的名字
在子组件中    引用的时候 我们 需要在 slot标签上加上 一个  name属性 名字 就是我们在父组件中自定义的那个名字

作用域插槽
子组件可以通过作用域插槽的方式把数据传递给父组件,父组件插槽使用 是父组件引用子组件中的数据 

什么叫做内容分发  说实话这个问题很模糊 想回答的准确点确实有点难
一个通俗点的回答就是 父组件的数据和子组件的模板配合起来使用就是内容分发 

使用keep-alive缓存的组件需要重新渲染怎么处理

keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。

优点
在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性

举个栗子:
当我们从首页–>列表页–>商详页–>再返回,这时候列表页应该是需要keep-alive

从首页–>列表页–>商详页–>返回到列表页(需要缓存)–>返回到首页(需要缓存)–>再次进入列表页(不需要缓存),这时候可以按需来控制页面的keep-alive

在路由中设置keepAlive属性判断是否需要缓存

beforeRouteEnter
activated
beforeRouteEnter
每次组件渲染的时候,都会执行beforeRouteEnter

beforeRouteEnter(to, from, next){
    next(vm=>{
        console.log(vm)
        // 每次进入路由执行
        vm.getData()  // 获取数据
    })
},
activated
在keep-alive缓存的组件被激活的时候,都会执行activated钩子

activated(){
   this.getData() // 获取数据
},
注意:服务器端渲染期间acvtived不被调用。

vue的内置组件

Vue内置组件 - 简书

Sass Less编译成css原理

Sass和Less学习_less和sass怎么定义变量_秋榆枫的博客-CSDN博客

意思大概就是less是css的超集,因此在less中转换为css节点是比较慢的
原理主要分析:
less 是预编译处理器,所以会在编译前进行处理成css

  • 首先less 会转换为ast(抽象语法树)语法
  • 然后遍历转换后所有的节点
  • 最后再形成css树
  • Less 使用 @ 符号声明变量
  • Sass/Scss 使用 $ 符号声明变量

vuex存储和本地存储区别

  • 1.区别:vuex存储在内存,localstorage(本地存储)则以文件的方式存储在本地,永久保存;sessionstorage( 会话存储 ) ,临时保存。localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理。

  • 2.应用场景:vuex用于组件之间的传值,localstorage则主要用于不同页面之间的传值。

  • 3.永久性:当刷新页面时vuex存储的值会丢失,localstorage不会。注:很多同学觉得用localstorage可以代替vuex, 对于不变的数据确实可以,但是当两个组件共用一个数据源(对象或数组)时,如果其中一个组件改变了该数据源,希望另一个组件响应该变化时,localstorage无法做到响应式,vuex可以绑定数据响应式。
    Vuex数据状态持久化的使用场景

  • 1、购物车
    比如你把商品加入购物车后,没有保存到后台的情况下,前端来存,就可以通过这种方式vuex+localStorage(sessionStorage)。

  • 2、会话状态
    授权登录后,token就可以用Vuex+localStorage(sessionStorage)来存储。

关于cookie与本地 存储的区别的问题.
1. cookie在浏览器和服务器间来回传递.而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存.
2. cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下.存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识.sessionStorage和localStorage 虽然也有存储大小的限制

promise方法

promise.all()该方法用于将多个Promise实例,包装成一个新的Promise实例。返回的数组结果顺序不会改变,即使P2的返回要比P1的返回快,顺序依然是P1, P2。 Promise.all成功返回成功数组,失败返回失败数据,一但失败就不会继续往下走

需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。

Promise.race是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败

使用场景: Promise.all和Promise.race都是有使用场景的。 有些时候我们做一个操作可能得同时需要不同的接口返回的数据,这时我们就可以使用Promise.all; 有时我们比如说有好几个服务器的好几个接口都提供同样的服务,我们不知道哪个接口更快,就可以使用Promise.race,哪个接口的数据先回来我们就用哪个接口的数据

href 与 src?

href (Hypertext Reference)指定网络资源的位置,从而在当前元素或者当前文档和由当前属性定义的需要的锚点或资源之间定义一个链接或者关系。(目的不是为了引用资源,而是为了建立联系,让当前标签能够链接到目标地址。) src source(缩写),指向外部资源的位置,指向的内容将会应用到文档中当前标签所在位置。

href与src的区别
1、请求资源类型不同:href 指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的联系。在请求 src 资源时会将其指向的资源下载并应用到文档中,比如 JavaScript 脚本,img 图片;
2、作用结果不同:href 用于在当前文档和引用资源之间确立联系;src 用于替换当前内容;
3、浏览器解析方式不同:当浏览器解析到src ,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等也如此,类似于将所指向资源应用到当前内容。这也是为什么建议把 js 脚本放在底部而不是头部的原因。

js的变量提升

在js中,变量和函数的声明会被提升到最顶部执行 函数提升高于变量的提升 函数内部如果用var声明了相同名称的外部变量,函数将不再向上寻找 匿名函数不会提升

Vue 中操作 data 中数组的方法中哪些可以触发视图更新

push()、pop()、shift()、unshift()、splice()、sort()、reverse()这些方法会改变被操作的数组; filter()、concat()、 slice()这些方法不会改变被操作的数组,返回一个新的数组; 以上方法都可以触发视图更新。

利用索引直接设置一个数组项,例:this.array[index] = newValue

直接修改数组的长度,例:this.array.length = newLength

以上两种方法不可以触发视图更新;

this.$set(this.array,index,newValue)

this.array.splice(index,1,newValue)

可以用 this.array.splice(newLength)

说一下你在 Vue 中踩过的坑

1、第一个是给对象添加属性的时候,直接通过给 data 里面的对象添加属性然后赋值,新添加的属性不是响应式的

【解决办法】通过 Vue.set(对象,属性,值)这种方式就可以达到,对象新添加的属性是响应式的

1、在 created 操作 dom 的时候,是报错的,获取不到 dom,这个时候实例 Vue实例没有挂载

【解决办法】通过:Vue.nextTick(回调函数进行获取)

Vue 组件 data 为什么必须是函数

1、每个组件都是 Vue 的实例。

2、组件共享 data 属性,当 data 的值是同一个引用类型的值时,改变其中一

个会影响其他

3、组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果。

Object.defineProperty 和 Proxy 的区别(必会)

1)Proxy 的优势如下:

Proxy 可以直接监听对象而非属性;

Proxy 可以直接监听数组的变化;

Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等

等是 Object.defineProperty 不具备的;

Proxy 返 回 的 是 一 个 新 对 象 , 我 们 可 以 只 操 作 新 的 对 象 达 到 目 的 , 而Object.defineProperty 只能遍历对象属性直接修改;

Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;

2)Object.defineProperty 的优势如下:

兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill

磨平

get和post区别

1.get一般是获取数据,post一般是提交数据
2.get参数会放在url上,所以安全性比较差,post是放在body中
3.get请求时会被缓存,post请求不会被缓存
4.get请求刷新服务器或退回是没有影响的,post请求退回时会重新提交数据
5.get请求会被保存在浏览器历史记录中,post不会
6.get请求只能进行url编码,post请求退回时会重新提交数据

css

css不会阻塞dom树的解析 css会阻塞dom树的渲染 css加载会阻塞后面js的执行

vue3异步组件

Suspense vue3的异步组件 #xxxx===v-solt 缩写 涩丝pen次

  1. <Suspense>
  2.    <template #default>
  3.     <组件>
  4.    </template>    
  5. </Suspense>

Echarts地图配置

注册地图series 先在echats里面下载地图数据json然后引入 ruai久丝T map

  1. onMouted(()=>{
  2.    //基于准备好的dom,初始化echarts实例
  3.    var myChart = echarts.init(chart.value);
  4.    //注册可用地图
  5.    echarts.registerMap('china'.地图数据);
  6.    //使用刚指定的配置项和数据显示图表。
  7.    myChart.setOption(option);
  8.    window.addEventListener('resize',()=>{
  9.        myChart.resize()
  10.   })
  11. })

Echarts

1.常用组件有那些
title标题组件 show text link
toolbox工具栏 导出图片 数据视图 切换 缩放 show orient feature tooltip tigger 触发类型
markPoint 图标标线
markLine图标的标线

解决刷新后二次加载路由

matcher 咩缺

  1. const router=createRouter()
  2. export function resetRouter(){
  3.    const newRouter = createRouter()
  4.    router.matcher = newRouter.matcher
  5. }

动态路由

?

语义化的理解

在写HTML页面结构时所用的标签有意义 头部用head hei得 主体用main 妹 底部用foot

如何判断页面是否语义化 把css去掉如果能够清晰的看出来页面结构,显示内容较为正常

为什么要选择语义化 1.让html结构更加清晰明了 2.方便团队协作,利于开发 3.有利于爬虫和SEO 4.能够让浏览器更好的解析代码 5.给用户带来更好的体验

解决了移动端那些兼容问题

1.移动端字体小于12px时异常显示 应该先把整体放大一倍,然后再用transform进行缩小
2.IOS下input输入框在输入引文首字母默认大写 <input autocapitaliza='off' autocorrect='off'/>
3.禁止IOS识别长串数字为电话 添加meta属性<meta conten='telephone=no' name='format-detection'>

了解过JWT吗?

JSON web Token 通过JSON形式作为在web应用中的令牌,可以在各方之间安全的把信息作为JSON对象传输,信息传输,授权

JWT的认证流程

1.前端把账号密码发送给后端的接口
2.后端核对账号密码成功后,把用户id等其他信息作为JWT 负载,把它和头部分别进行base64编码拼接后签名,形成一个JWT(token)
3.前端每日请求时都会把JWT放在HTTP请求头的Authorization字段内
4.后端检查是否存在,如果存在就验证JWT的有效性 (签名是否正确,token是否过期)
5.验证通过后后端使用JWT中包含的用户信息进行其他的操作,并返回对应结果

优点 简洁 包含性 包含了很多用户信息 因为token是JSON加密的形式保存在客户端,所以JWT是跨语言的,原则上是任何web形式都支持

svg格式了解多少

基于XML语法格式的图像格式,可缩放矢量图,其他图像是基于像素的,SVG是属于对图像形状的描述,本质是文本文件,体积小,并且不管放大多少倍都不会失真

1.SVG可直接插入页面中,成为DOM一部分,然后用JS或css进行操作

<svg></svg>

2.SVG可作为文件被引入

<img src="pic.svg" />

3.SVG可以转为base64引入页面

说一下浏览器的缓存策略

强缓存(本地缓存) 协商协议(弱缓存)

强缓:不发起请求,直接使用缓存里的内容,浏览器把js,css,image等存到内存中,下次用户访问直接从内存中取,提高性能。

协缓:需要像后台发送请求,通过判断来决定是否使用协商缓存,如果请求内容没有变化,则返回304,浏览器就用缓存里的内容

强缓存的触发:

HTTP1.0:时间戳响应标头

HTTP1.1:Cache-Control响应标头

协商缓存触发:

HTTP1.0:请求头:if-modified-since 响应头: last-modified

HTTP1.1:请求头: if-none-match 响应头: Etag

说一下什么是同源策略

http:// www. aaa.com:8080/index/vue.js

协议 子域名 主域名 端口号 资源

同源策略是浏览器的核心,如果没有这个策略就会遭受到

主要指的就是协议+域名+端口号三者一致,若其中一个不一样则不是同源,会产生跨域

三个允许跨域加载资源的标签:img link script

跨域是可以发送请求,后端也会正常返回结果,只不过这个结果被浏览器拦截了

这些可以解决跨域问题 JSONP CORS websocket 反向代理

无感登录

1.在相应其中拦截,判断token返回过期后,调用刷新token的接口

2.后端返回过期时间,前端判断token的过期时间,去调用刷新token的接口

3.写定时器,定时刷新token接口

流程

1.登录成功后保存token 和 refresh_token

2.在响应拦截器中对401状态码引入刷新token的api方法调用

3.替换保存本地新的token

4.把错误对象里token替换

5.再次发送未完成的请求

6.如果refresh_token过期了,判断是否过期,过期了就清楚所有token重新登录

Vue中数据持久化

localStorage

vuex-persistedstate 坡c丝听

注意Vuex本身做不到,需要通过vuex-persistedstate插件去做持久化存储

find和filter的区别

区别一:返回的内容不同
    filter 返回是新数组
    find   返回具体的内容
区别二:
    find :匹配到第一个即返回
    filter : 返回整体(没一个匹配到的都返回)

some和every的区别

some  ==》 如果有一项匹配则返回true
every ==》 全部匹配才会返回true

如何统一监听vue组件报错

在App中写一个errorCaptured函数 k耶不缺

  1. errerCaptured(err,vm,info){
  2.    //err 具体错误信息
  3.    //vm 错误发生的组件
  4.    //info 错误信息(指出哪一个地方报的错)
  5.    console.log(err,vm,info)
  6. }

vue.config.errorHandler

接收三个参数:错误、触发错误的组件实例、指定错误源类型的信息字符串。

  1. app.config.errorHandler = (err, instance, info) => {
  2.  // handle error, e.g. report to a service
  3. }

它可以从以下来源捕获错误:

  • 组件渲染

  • 事件处理程序

  • 生命周期钩子

  • setup()函数

  • Watchers

  • 自定义指令钩子

  • 过渡钩子

eventBus实现原理

订阅发布

手写一个订阅发布怎么设计

定义一个对象a 一个用来声明on 一个用来调用emit

  1. let a={
  2. list:[]
  3. on:(fnName,fn)=>{
  4. this.list.push({
  5. Name:fnName,
  6. fn:fn
  7. })
  8. }
  9. },
  10. emit:(fnName,"参数")=>{
  11. this.list.filer(item=>item.name==fnName)[0].fn("chan'shu")
  12. }

自己实现一个vuex

使用eventBus

vue中为什么是this.num不是this.data.num

vue做了一层代理 添加到原型上 extend执行data合并

this

根据函数调用的方式不同,this指向也不同

1.以函数形式调用this是window

2.以方法形式调用,this是调用方法的对象

3.构造函数中this是新建的对象

4.箭头函数没有自己的this,由外层作用域决定

5.通过call和apply调用的函数,它们的第一个参数就是函数的this

6.通过bind返回的函数,this由bind的第一个参数决定(无法修改)

高度塌陷

给父元素写固定高度

给外部的父盒子也添加浮动,让其也脱离标准文档流

父元素添加声明overflow:hidden;(触发一个BFC)

在元素中内容的最后添加一个伪元素,具体设置样式如下

  1. .box:after{
  2. content:"";
  3. clear: both;
  4. display: block;
  5. height: 0;
  6. overflow: hidden;
  7. visibility: hidden;
  8. }

同源策略

1.同源策略是一种约定,它是浏览器最核心也最基本的安全功能 如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。 可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。 它是一个安全策略。所有支持JavaScript的浏览器都会使用这个策略

满足同源的三个条件: 所谓同源是指,域名、协议、端口相同。

2.为什么要同源限制? 同源策略存在的意义: 非同源下的 cookie 等隐私数据可以被随意获取 非同源下的 DOM 可以的随意操作 ajax 可以任意请求的话,用户的各种隐私肯定会泄露,对用户造成不同程度的损失

3.同源策略的限制范围? 不能获取不同源的 cookie,LocalStorage 和 indexDB 不能获取不同源的 DOM() 不能发送不同源的 ajax 请求 (可以向不同源的服务器发起请求,但是返回的数据会被浏览器拦截)

git基础命令

GitHub Flow 是一个轻量级,基于分支的工作流,支持团队和项目的定期部署

	1、 git init 把这个目录变成git可以管理的仓库
	2、 git add 不但可以跟单一文件,也可以跟通配符,更可以跟目录。一个点就把当前目录下所有未追踪的文件全部add了
	3、 git commit -m ‘first commit’把文件提交到仓库
	4、 git remote add origin +//仓库地址 //关联远程仓库 
	5、 git push -u origin master //把本地库的所有内容推送到远程库上

js那些操作会造成内存泄漏

全局变量

循环引用

闭包

setTimeout setInterval

Dom

console.log打印到控制台的对象

作用域作用域链

作用域就是变量的可用性的代码范围,就叫做这个变量的作用域。简单理解,就是在这个范围内,变量是可以使用的,超过这个范围,变量就无法使用,这个范围就是作用域。

作用域分为三种:全局作用域、局部作用域、块级作用域。

全局作用域 顾名思义,全局作用域就是能够在全局使用,可以在代码的任何地方被调用

局部作用域 局部作用域只能作用于局部的代码片段,常见于函数内部,即函数内创建的变量,只能作用于函数内部,函数外部无法使用函数内部创建的变量。

块级作用域 块级作用域是es6新增的,使用let关键字创建变量、const关键字创建常量(当然let、const也会有自己的语法规范,这里不过多展开),作用域只存在于{}花括号内

什么是作用域链

当你要访问一个变量时,首先会在当前作用域下查找,如果当前作用域下没有查找到,则返回上一级作用域进行查找,直到找到全局作用域,这个查找过程形成的链条叫做作用域链。

函数柯里化

一. 什么是函数柯里化

函数柯里化是指将使用多个参数的函数转化成一系列使用一个参数的函数的技术, 它返回一个新的函数, 这个新函数去处理剩余的参数

二. 函数柯里化的实现

实现思路: 通过函数的 length 属性获取函数的形参个数, 形参的个数就是所需参数的个数

三. 函数柯里化的作用

参数复用: 本质上来说就是降低通用性, 提高适用性

假如一个函数需要两个参数, 其中一个参数可能多次调用并不会发生更改, 比如商品打折的力度, 此时可以根据折 扣进行封装

提前返回

经典实例: 元素绑定事件监听器, 区分 IE 浏览器的 attachEvent 方法

延迟计算: 柯里化函数不会立即执行计算,第一次只是返回一个函数,后面的调用才会进行计算

link和@import区别

link与@import的区别:link和import的语法结构不同,<link>是HTML标签,只能在HTML中使用,import是css样式,可以在HTML中通过<style>标签使用,或在css中直接使用。

页面被加载时,link会同时被加载,而@import引用的css会等到页面被加载完再加载

link方式的样式的权重高于@import的权重

bit 与 Byte 的区别

一、用途不一样

Bit 意为"位"或"比特",是计算机运算的基础单位;Byte 意为"字节",是计算机文件大小的基本计算单位;

二、代表的大小不同

1 bit 就是1位二进制数,比如 1 或者 0;1 Byte 就是 1 个字节,1 个字节是由 8 个二进制位组成的。比如1111111,00000000等。

三、代表的内容不一样

Bit 只能代表一个内容,(0或者1,其中的一个),1 Byte 代表 256 个内容 = 2 的 8 次方。

什么是高阶函数

什么是高阶函数:就是一个函数的参数是函数,或者返回值是函数,满足其中一个就是高阶函数

设计模式

  • 设计模式是我们在 解决问题的时候针对特定问题给出的简洁而优化的处理方案

  • 在 JS 设计模式中,最核心的思想:封装变化。

  • 将变与不变分离,确保变化的部分灵活、不变的部分稳定。

一、单例模式

二、 静态工厂模式

三、观察者模式

四、适配器模式

五、注册者模式

vue父子组件生命周期执行顺序

1.挂载

父组件beforeCreate => 父组件created => 父组件beforeMount => 子组件beforeCreate => 子组件created => 子组件beforeMount => 子组件mounted => 父组件mounted

2.更新阶段

父组件beforeUpdate => 子组件beforeUpdate => 子组件updated => 父组件updated

3.销毁阶段

父组件beforeDestroy => 子组件beforeDestroy => 子组件destroyed => 父组件destroyed

简述for in 和 for of 的区别

1、推荐在循环对象属性的时候使用 for...in,在遍历数组的时候的时候使用 for...of
2、for...in 循环出的是 key,for...of 循环出的是 value
3、注意,for...of 是 ES6 新引入的特性。修复了 ES5 引入的 for...in 的不足
4、for...of 不能循环普通的对象(如通过构造函数创造的),需要通过和 Object.keys()搭配使用

flex:1

flex: 1 实际上是三个属性的缩写:flex-grow: 1; flex-shrink: 1 flex-basis: auto;

flex-grow 谷漏 默认为0, 只能是正整数。即父元素有剩余空间也不放大元素。如果为 1,则把剩余空间的一份加给自己的宽度。
flex-shrink 逊克 默认为1,只能是正整数。即父元素空间不足则按比例收缩。如果为 0,则不收缩 flex-basis 背舍丝 默认为 auto, 即元素本身的大小。这个属性定义了在分配多余空间之前,元素占据的主轴空间,浏览器根据这个属性计算是否有多余空间。可以设置为和 width 和 height 属性一样的值,比如 220px,则元素占据固定空间。

实现浅拷贝方法

Object.assign()  合并对象

扩展运算符

数组方法实现数组浅拷贝

Array.prototype.slice

Array.prototype.concat

手写实现浅拷贝

创建一个新对象,遍历传入对象的属性for...in... ,如果该属性是传入对象本身的属性(hasOwnProperty),就赋值给新对象newobj[key]=obj[key]

实现深拷贝方法

JSON. parse (JSON. stringify())

使用递归的方式实现深拷贝

递归

就是函数自己调用自己。是循环运算的一种算法模式。

浅拷贝和深拷贝

浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 。

深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象。

深拷贝就是完全拷贝一份新得数据,会在堆内存中开辟新得空间,拷贝的对象被修改后,原对象不受影响。

JSON.pares JSON.styingif缺点拷贝不了函数

区别:浅拷贝基本类型之前互不影响,引用类型其中一个对象改变了地址,就会影响另一个对象;深拷贝 改变新对象不会影响原对象,他们之前互不影响。

Set与Map的区别

1.Map是键值对,Set是值的集合,当然键和值可以是任何的值;

2.Map可以通过get方法获取值,而set不能因为它只有值;

3.都能通过迭代器进行for...of遍历;

4.Set的值是唯一的可以做数组去重,Map由于没有格式限制,可以做数据存储

5.map和set都是stl中的关联容器,map以键值对的形式存储,key=value组成pair,是一组映射关系。set只有值,可以认为只有一个数据,并且set中元素不可以重复且自动排序。

Set对象允许你存储任何类型的值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。

Map对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。构造函数Map可以接受一个数组作为参数。

浏览器如何渲染网页

  1. 解析HTML生成DOM树 - 渲染引擎首先解析HTML文档,生成DOM树

  2. 构建Render树 - 接下来不管是内联式,外联式还是嵌入式引入的CSS样式会被解析生成CSSOM树,根据DOM树与CSSOM树生成另外一棵用于渲染的树-渲染树(Render tree),

  3. 布局Render树 - 然后对渲染树的每个节点进行布局处理,确定其在屏幕上的显示位置

  4. 绘制Render树 - 最后遍历渲染树并用UI后端层将每一个节点绘制出来

解析HTML文件,创建DOM树,自上而下,如果遇到样式(link、style)与脚本(script)都会阻塞

keep-alive

缓存组件内部状态,避免重新渲染

页面第一次进入,钩子的触发顺序created-> mounted-> ,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated

工作中怎么做keep-alive 儿赖无 缓存的 我会自己封装一个方法 给需要缓存得组件路由添加一个自定义属性mate,在有使用路由占位符的地方进行判断=》条件渲染,用wacth进行深度监听路由信息route 拿到路由信息后进行if判断 看组件是否需要缓存,

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。 in库路d

  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。 ex库路d

  • max - 数字。最多可以缓存多少组件实例。 骂x丝

1.activated:页面第一次进入的时候,钩子触发的顺序是created->mounted->activated 2.deactivated :页面退出的时候会触发deactivated,当再次前进或者后退的时候只触发activated

Promise

Promise 是异步编程的一种解决方案解决了回调地狱问题:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。promise有三种状态: pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

1.初始化,状态:pending pen顶

2.当调用resolve(成功),状态:pengding=>fulfilled 佛fei L d

3.当调用reject(失败),状态:pending=>rejected reject t d

Promise本身是同步的,他的then方法和catch方法是异步的

一个异步请求套着一个异步请求,一个异步请求依赖于另一个的执行结果,使用回调的方式相互嵌套。 这会导致代码很丑陋,不方便后期维护

代码的可读性问题 信任问题

Promise.all解决了什么问题:处理请求并发问题

Promise.rase

前端长列表优化

懒渲染

就是常见的无线滚动,每次只渲染一部分(比如10条),等剩余部分滚到可见区域,再渲染一部分

flex的属性

改变主轴的属性是flex-direction

默认值是 row 就是横向排列 x排列

column 纵向排列 y排列

  1. display: flex;

  2. flex-direction: row-reverse 肉 row-reverse 反横向排列

  3. display: flex;

  4. flex-direction: column-reverse; 迪ruai询 阔隆 column-reverse 反纵向排列

  5. display: flex;

  6. justify-content: flex-start; flex-start 默认值 左对齐

  7. display: flex;

  8. justify-content:flex-end; flex-end 右对齐

  9. display: flex;

  10. justify-content:center; center 爵丝Tfai 康Tent 水平居中

  11. display: flex;

  12. justify-content:space-between; 丝背丝 臂蠢 space-between 两端对齐方式

  13. display: flex;

  14. justify-content:space-around; space-around 距离环绕

  15. display: flex; 调整侧轴的对齐方式

  16. align-items: flex-start; flex-start 丝朵T 默认值 上对齐

  17. display: flex;

  18. align-items: flex-end; flex-end and 下对齐

  19. display: flex;

  20. align-items: center; center 森T 垂直居中

行内元素在弹性盒子中会变成块元素

justify-center 横向排列方式

align-center 纵向排列方式

CSS盒子居中的方法

display:flex;

justify-content:center;

align-items: center; 需要写到父盒子中

fixed 废x丝D 固定定位 对象脱离正常文档流 浏览器窗口进行定位

sticky 丝迪k 粘滞定位

position: relative; rui莱t吴 相对定位 对象遵循正常文档流 位置不变

position: absolute; 绝对定位 脱离文档流 离自身最近的定位父级元素的位置进行偏移定位 浏览器窗口进行定位

left: 50%;

top: 50%;

transform: translate(-50%,-50%);

前端WebSocket详解

 即时通信 不刷新获取数据

和http一样,WebSocket也是应用层协议。浏览器和服务器只要完成一次握手的动作,然后浏览器和服务器之间就会脱离http协议,而是用WebSocket自己的ws协议。客户端和服务器端就可以通过tcp连接直接交换数据。

WebSocket方法

  • Socket.send():森得 向服务器发送数据

  • Socket.close():克lwo丝 关闭连接

  • 弹幕

  • 媒体聊天

  • 协同编辑

  • 基于位置的应用

  • 体育实况更新

  • 股票基金报价实时更新

防抖节流

节流 在大量触发的事件当中,我们让他在短时间当中触发少次

防抖 在连续触发事件当中,我们让他在短时间触发一次

防抖 简单地说,就是 当一个动作连续触发,只执行最后一次。

  1. let timer = null
  2. inp.onkeyup = function (e) {
  3. clearTimeout(timer)
  4. timer=setTimeout(() => {
  5. console.log('--------');
  6. console.log(e);
  7. console.log('--------');
  8. }, 2000)
  9. }

防抖应用场景用户 在输入框连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源.

登录、发短信等按钮避免用户点击太快,以致于发送了多次请求,需要用到防抖 连续触发,只执行最后一次 调整浏览器窗口大小时,resize 次数过于频繁,造成计算过多,此时需要一次到位,就用到了防抖 文本编辑器实时保存,当无任何更改操作一秒后进行保存

节流 就是限制一个动作在一段时间内只能执行一次

  1. let ks=0
  2. document.onmousemove=function(e){
  3. let dq=+new Date()
  4. if(dq-ks<1000){
  5. return;
  6. }
  7. // 下个时间段从头开始
  8. ks=dq
  9. console.log('--------');
  10. console.log(e);
  11. console.log('--------');
  12. }

节流应用场景用户 鼠标不断触发某事件时,如点击,只在单位事件内触发一次. 懒加载时要监听计算滚动条的位置,但不必要每次滑动都触发,可以降低计算频率,而不必要浪费CPU资源. 这里我们用一个鼠标跟随效果的例子:

路由守卫

vue-router 路由钩子函数(导航守卫)

路由钩子函数有三种:

  • 全局钩子: beforeEach(全局前置守卫)、 afterEach(全局后置钩子)

  • 路由独享的守卫(单个路由里面的钩子): beforeEnter

  • 组件路由:beforeRouteEnter、 beforeRouteUpdate、 beforeRouteLeave

1、to:即将要进入的目标路由对象;

2、from:当前导航即将要离开的路由对象;

3、next :调用该方法后,才能进入下一个钩子函数(afterEach)。

http状态码

100,接受的请求正在处理,信息类状态码

200(成功)服务器已成功处理了请求。

3xx(重定向)表示要完成请求,需要进一步操作。通常这些状态代码用来重定向。 301,永久性重定向,表示资源已被分配了新的 URL 302,临时性重定向,表示资源临时被分配了新的 URL 303,表示资源存在另一个URL,用GET方法获取资源 304,(未修改)自从上次请求后,请求网页未修改过。服务器返回此响应时,不会返回网页内容

4xx(请求错误)这些状态码表示请求可能出错,妨碍了服务器的处理 400(错误请求)服务器不理解请求的语法 401表示发送的请求需要有通过HTTP认证的认证信息 403(禁止)服务器拒绝请求 404(未找到)服务器找不到请求网页

5xx(服务器错误)这些状态码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求的错误 500,(服务器内部错误)服务器遇到错误,无法完成请求 503,表示服务器处于停机维护或超负载,无法处理请求

css书写顺序

scss 布局定位第一 盒子模型 文本内容属性

手写深拷贝思路

  1. 判断拷贝的对象是数组还是对象*

  2. 遍历属性*

  3. 是否还有数组或对象 =>递归

  4. 基本数据类型 => 赋值*/

路由懒加载底层

底层是Promise写的不调用不加载

为什么使用组件插槽

组件的内容是根据使用的时候决定

什么是重绘与回流?

重绘:当元素的一部分属性发生改变,如外观、背景、颜色等不会引起布局变化,只需要浏览器根据元素的新属性重新绘制,使元素呈现新的外观叫做重绘

重排(回流):当 render 树中的一部分或者全部因为大小边距等问题发生改变而需要 DOM 树重新计算的过程

重绘不一定需要重排(比如颜色的改变),重排必然导致重绘(比如改变网页位置)

1.多个属性尽量使用简写,例如:boder可以代替boder-width、boder-color、boder-style
2.创建多个dom节点时,使用documentfragment创建
3.避免使用table布局
4.避免设置多层内联样式,避免节点层级过多
5.避免使用css表达式
6.将频繁重绘或回流的节点设置为图层,图层能够阻止该节点的渲染行为影响到别的节点(例:will-change\video\iframe等标签),浏览器会自动将该节点变为图层

说说你对闭包的理解?闭包使用场景

闭包是什么
闭包就是能够读取其他函数内部变量的函数
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围), 这样的组合就是闭包(closure)

形成条件
内部函数引用外部函数的变量的时候闭包就产生了

优点
可以让外部作用访问到内部作用的变量 延长局部变量的生命周期

作用
闭包当中的变量会一直存在于内存当中,可以一直给我们来进行使用 不会被垃圾回收机制处理
外部作用域可以访问函数内部的变量

缺点
因为局部变量会一直存在于内存当中,所以会一直占用这内存空间,对于IE低版本的浏览器来说,容易造成内存泄露,消耗内存

使用场景 封装私有变量 延续局部变量的寿命 函数防抖

为什么要使用闭包
对于普通函数来讲,函数执行完毕之后,会释放掉其内存空间 闭包,不会主动的释放内存空间

JavaScript原型,原型链 ? 有什么特点?

原型

**每一个函数自诞生以来都有一个对象 `prototype` => 显示原型对象**
**每一个对象自诞生以来都一个属性 `__proto__` => 隐式原型对象**

原型链

原型对象也是一个对象,一层一层的串下去,形成了一个链条,叫做原型链

bind、call、apply 区别?如何实现一个bind?

callapplybind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向

apply 以数组的形式传入 改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

call 跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

bind 改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

虚拟dom

什么是虚拟dom?
虚拟dom本质上就是一个普通的JS对象,用于描述视图的界面结构
在vue中,每个组件都有一个render函数,每个render函数都会返回一个虚拟dom树,这也就意味着每个组件都对应一棵虚拟DOM树

为什么需要虚拟dom?
在vue中,渲染视图会调用render函数,这种渲染不仅发生在组件创建时,同时发生在视图依赖的数据更新时。如果在渲染时,直接使用真实DOM,由于真实DOM的创建、更新、插入等操作会带来大量的性能损耗,从而就会极大的降低渲染效率。
因此,vue在渲染时,使用虚拟dom来替代真实dom,主要为解决渲染效率的问题。

虚拟dom是如何转换为真实dom的?
在一个组件实例首次被渲染时,它先生成虚拟dom树,然后根据虚拟dom树创建真实dom,并把真实dom挂载到页面中合适的位置,此时,每个虚拟dom便会对应一个真实的dom。
如果一个组件受响应式数据变化的影响,需要重新渲染时,它仍然会重新调用render函数,创建出一个新的虚拟dom树,用新树和旧树对比,通过对比,vue会找到最小更新量,然后更新必要的真实dom节点
这样一来,就保证了对真实dom达到最小的改动。

模板和虚拟dom的关系
vue框架中有一个compile模块,它主要负责将模板转换为render函数,而render函数调用后将得到虚拟dom。

编译的过程分两步:
将模板字符串转换成为AST
将AST转换为render函数
如果使用传统的引入方式,则编译时间发生在组件第一次加载时,这称之为运行时编译。
如果是在vue-cli的默认配置下,编译发生在打包时,这称之为模板预编译。
编译是一个极其耗费性能的操作,预编译可以有效的提高运行时的性能,而且,由于运行的时候已不需要编译,vue-cli在打包时会排除掉vue中的compile模块,以减少打包体积
模板的存在,仅仅是为了让开发人员更加方便的书写界面代码
vue最终运行的时候,最终需要的是render函数,而不是模板,因此,模板中的各种语法,在虚拟dom中都是不存在的,它们都会变成虚拟dom的配置

虚拟节点

VNode是JavaScript对象。用JavaScript对象来描述真实的DOMDOM标签,属性,内容都变成对象的属性。

VNode的作用 通过render将template模版描述成VNode,然后进行一系列操作之后形成真实的DOM进行挂载。

VNode的优点 兼容性强,不受执行环境的影响。VNode因为是JS对象,不管Node还是浏览器,都可以统一操作,从而获得了服务端渲染、原生渲染、手写渲染函数等能力。 减少操作DOM,任何页面的变化,都只使用VNode进行操作对比,只需要在最后一步挂载更新DOM,不需要频繁操作DOM,从而提高页面性能。

VNode存放哪些信息

  1. data:存储节点的属性,绑定的事件等

  2. elm:真实DOM 节点

  3. context:渲染这个模板的上下文对象

  4. isStatic:是否是静态节点

this.$nextTick原理和使用场景

1.nextTick是什么
        nextTick是等待下一次Dom更新的工具方法

2.为什么需要他
        Vue有一个异步更新策略,意思是如果数据变化,vue不会立即更新DOM,而是开启一个队列,把组件更新的函 数保存到队列中,在同一个事情中发送的所有的数据变更为异步执行批量更新,这一个策略导致我们对数据的 修改不会立即体现在dom上

3.开发的时候如何使用他?我们会在平时的开发中那里用它
        响应式数据变化后获取dom的更新状态,比如希望获取列表更新后的高度 获取元素宽度 created()中进行DOM操作

Vue自定义指令

自定义指令分为全局自定义指令和局部自定义指令|一般用的多的就是全局自定义指令 底莱t吴 应用:获取input的焦点 一键copy的功能 等经常使用的都可以用

  1. 语法 app.directive('defaulFont',{})
  2. app.directive("focus",{
  3. //
  4. mounted(el) {//什么时候添加这个指令,el:绑定元素的真实dom
  5. console.log(el);
  6. el.focus()
  7. },
  8. })
  9. v-focus 直接用在元素中
  10. app.directive("defaulFont",{
  11. //
  12. mounted(el,binding) {//什么时候添加这个指令,el:绑定元素的真实dom
  13. console.log(el,binding);
  14. el.style.fonSize=20+'px'
  15. },
  16. })
  17. v-defaulFont

Vue 数据双向绑定的原理是什么

Vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过

Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给

订阅者,触发相应的监听回调。

vue响应式原理

  • 新增属性、删除属性, 界面不会更新。

  • 直接通过下标修改数组, 界面不会自动更新。

vue响应式也叫作数据双向绑定

首先我们需要通过Object.defineProperty()方法把数据(data)设置为getter和setter的访问形式,getter收集依赖就是收集每个标签和每个数据属性的对应关系,当data对象中属性修改赋值的时候就会触发对应的setter函数拦截进行视图更新

然后我们可以在set方法中去调用操作dom的方法

在vue中,如何侦测一个data的变化?

首先会遍历data,使用Object.defineproperty拦截所有的属性,当用户操作视图会触发set拦截器,set首先会改变当前的数据,然后通知watch,让watch通知视图进行更新,视图重绘。再次从get中获取相应的数据

在vue3中,它重写响应式原理实现了深度响应式,首先会使用proxy进行代理,拦截data中属性的所有操作,包括属性的读写,添加删除等等,其次会使用reflect进行反射,动态对被代理的对象的响应属性进行特定的操作,代理对象和反射对象必须相互配合才能实现响应式

v-model双向绑定原理

  1. v-bind绑定一个value属性 绑定数据的value

  2. v-on指令给当前元素绑定input事件 触发输入事件

vue中如何进行依赖收集

在getter中收集依赖,在setter中触发依赖。先收集依赖,即把用到该数据的地方收集起来,然后等属性发生变化时,把之前收集好的依赖循环触发一遍就行了。

vue实例挂载的过程

在执行$mount的时候,vue会先判断render函数是否存在,
若存在,则执行render编译模板,
若不存在,则判断template,
若template存在,则将template通过render函数编译成Vnode,最后更新DOM,在这过程中,初始化时调用了Watcher类来充当观察者模式,一旦vm实例中的数据发生变化,Watcher就执行回调函数

Vue的更新策略 Vue采用异步渲染呢

Vue 是组件级更新,如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,所以为了性能, Vue 会在本轮数据更新后,在异步更新视图。这也是nextTick 产生的原因。异步渲染核心思想是 nextTick 。

箭头函数和普通函数有什么区别?

1.this指向的问题

箭头函数中的this只在箭头函数定义时就决定的,而且不可修改的(call,apply,bind)

箭头函数的this指向定义时候外层第一个普通函数的this

2.箭头函数不能new(不能当作构造函数)

3.箭头函数没有原型Prototype

介绍一下css的盒子模型

css的盒子模型有哪些:标准盒子模型,IE盒子模型

把盒子设置为IE盒模型,不论内边距距,边框如何改变盒子的真实宽高都不会发生改变。

css的盒子模型区别

标准盒子模式:margin boreder padding content
IE盒子模型:margin content(boreder+padding+content)
通过css如何转换盒子模型
box-sizing:content-box 标准盒子模型
box-sizing:boreder-box IE盒子模型

BFC

BFC就是页面上一个隔离的独立容器,容器里面的子元素不会影响到外面的元素
1.了解BFC:块级格式化上下文
2.BFC的原则:如果一个元素具有BFC那么内部元素再怎么弄,都不会影响到外面的元素
3.如何触发BFC float的值非none overflow的值非visible display的值为inline-block table-cell
position的值为absoute fixed

延迟加载JS有那些方式

延迟加载:async defer 低f儿
defer :等html全部解析完成,才会执行js代码,顺次执行js脚本
async :async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)

js微任务和宏任务

js代码执行流程:同步执行完==》事件循环
	同步的任务都执行完了,才会执行事件循环的内容
	进入事件循环:请求,定时器,事件...
事件循环中包含:微任务 宏任务
微任务:Promise.then
宏任务:setTimeout..
要执行宏任务的前提是清空了所有的微任务
流程:同步==》事件循环 微任务和宏任务==》微任务==》宏任务=》微任务...

var let const的区别

letvar用来声明变量赋值后可以改变它的值,const用来声明常量赋值后就不能改变它的值。

const不允许只声明不赋值,一旦声明就必须赋值

var是函数作用域,letconst是块级作用域。

var有提升的功能,letconst没有

关键字变量提升块级作用域重复声明同名变量重新赋值
var×
let××
const×××

在最外层的作用域,也就是全局作用域,用var声明的变量,会作为window的一个属性

花括号{}就是块级作用域,函数作用域就是函数里面的内容

变量就是赋值后可以改变它的值,常量就是赋值后就不能改变它的值。

H5 的新特性有哪些?C3 的新特性有哪些

拖拽释放 自定义属性 data-id 音频 ,视频(audio, video) 画布 Canvas 存储

颜色: 新增 RGBA , HSLA 模式 文字阴影(text-shadow) 边框: 圆角(border-radius) 边框阴影 : box-shadow

盒子模型: box-sizing 渐变 过渡 : transition 自定义动画 border-image 图片边框 字体图标 iconfont

弹性布局 flex

性能优化

路由懒加载

函数式组件

Vue 提供了一种称为函数式组件的组件类型,用来定义那些没有响应数据,也不需要有任何生命周期的场景, 它只接受一些props 来显示组件。

缓存不活动的组件实例( keep-alive)

监听事件销毁 addEventListener

循环添加key

活用v-show,减少v-if

1.按需引入,减少打包体积

3.打包移除console.log

1.减少HTTP请求数

使用字体图标代替图片

减少发送网络请求:在后台管理系统对数据进行增删改查的时候我们前端处理没有直接拿到最新的数据等切换页面重新加载页面的时候才统一发送一个请求发到最新数据进行渲染

watch和watchEffect

他是一个立即执行函数,如果被动追踪他的依赖,当这些依赖改变的时候重新执行函数

他是侦听一个或者多个响应式数据源并在数据源改变时候调用一个回调函数

watchEffect是一个特殊的watch,传入的函数既是依赖的数据源,也是回调函数。如果我们更不关心响应式变化的前后值,只是想拿一些数据做一些事情,那么我们就用watchEffect

如果我们需要一个某个或多个数据,还需要他的前后值变化,做一些逻辑处理,我们就使用watch

wtchEffect在使用的时候,传入函数会立即执行 watch默认的情况并不会执行回调函数,除非我们手动添加配置immediate:true

Vue3

vue3与react、 react hooks - 简书

vue3生命周期

Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:

beforeDestroy改名为 beforeUnmount

destroyed改名为 unmounted

Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

beforeCreate===>setup()

created=======>setup()

beforeMount ===>onBeforeMount

mounted=======>onMounted

beforeUpdate===>onBeforeUpdate

updated =======>onUpdated

beforeUnmount ==>onBeforeUnmount

unmounted =====>onUnmounted

Vue3 Hooks理解 

1.更好的逻辑复用与代码组织
2.减小了代码体积
3.没有this的烦恼

hook是钩子的意思,看到“钩子”是不是就想到了钩子函数?事实上,hooks 还真是函数的一种写法。

vue3 借鉴 react hooks 开发出了 Composition API ,所以也就意味着 Composition API 也能进行自定义封装 hooks。

vue3 中的 hooks 就是函数的一种写法,就是将文件的一些单独功能的js代码进行抽离出来,放到单独的js文件中,或者说是一些可以复用的公共方法/功能。其实 hooks 和 vue2 中的 mixin 有点类似,但是相对 mixins 而言, hooks 更清楚复用功能代码的来源, 更清晰易懂,可以提高代码的复用性,让我们在不同的组件中都可以利用hook函数。

Vue3 Hooks和React Hooks区别

react

16.8版本出现hook

hook的目标:让你在不编写 class 的情况下使用 state 以及其他的 React 特性(生命周期)

hook不允许出现在条件语句中,因为react hook底层是基于链表实现,调用的条件是每次组件被render的时候都会顺序执行所有的hooks

这是react的一个缺点,不过也有解决方案

  1. function demo(){    
  2.     const [name, setName] = useState('hannie');
  3.     if(...){
  4.         const [val, setVal] = useState('age');
  5.     }
  6. }
  7. 此代码会报错,因为hook出现在条件语句中
  8. 复制代码

常见的hook,看我的另一篇[React基础知识]几个use+'...'常用hook,集体参考官网

Vue

vue3.0版本出现hook

hook目的:让你在函数组件里“钩入” value(2.x中的data) 及生命周期等特性的函数

vue hook只会在setup函数被调用的时候被注册一次

在此写几个主要使用的hook,具体参考官网

  1. reactive
  2. ref
  3. computed
  4. watchEffect
  5. onMounted, onUpdated, onUnmounted
  6. 。。。
  7. 复制代码
Vue2Vue3
beforeCreatesetup(替代)
createdsetup(替代)
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured

对比

vue的hook思想来源于react

相同点:

  1. 基于函数的组合式 API 提供了与 React Hooks 同等级别的逻辑组合能力
  • vue hook目的:让你在函数组件里“钩入” value(2.x中的data) 及生命周期等特性的函数
  • react hook的目标:让你在不编写 class 的情况下使用 state 以及其他的 React 特性(生命周期)
  1. 都是在版本中出现
  • vue3.0版本出现hook
  • react16.8版本出现hook

不同点:

  1. hook执行次数
    组合式 API(vue hook) 的 setup() 函数只会被调用一次react数据更改的时候,会导致重新render,重新render又会重新把hooks重新注册一次

使用 Vue 组合式 API(vue hook) 的代码会是:

  • 一般来说更符合惯用的 JavaScript 代码的直觉;
  • 不需要顾虑调用顺序,也可以用在条件语句中;
  • 不会在每次渲染时重复执行,以降低垃圾回收的压力;
  • 不存在内联处理函数导致子组件永远更新的问题,也不需要 useCallback;
  • 不存在忘记记录依赖的问题,也不需要“useEffect”和“useMemo”并传入依赖数组以捕获过时的变量。Vue 的自动依赖跟踪可以确保侦听器和计算值总是准确无误。
  1. 实现原理不同
    hook执行次数不同,是因为实现原理不同。
    react hook底层是基于链表实现,调用的条件是每次组件被render的时候都会顺序执行所有的hooks;
    vue hook是基于用proxy实现的数据响应机制,只要任何一个更改data的地方,相关的function或者template都会被重新计算,因此避开了react可能遇到的性能上的问题。

  2. 学习成本
    react hook的上手成本相对于vue会难一些,vue天生规避了一些react中比较难处理的地方

Vue3 Hook 和 Mixin & HOC 对比

说到这里,还是不得不把官方对于「Mixin & HOC 模式」所带来的缺点整理一下。
渲染上下文中公开的属性的来源不清楚。 例如,当使用多个 mixin 读取组件的模板时,可能很难确定从哪个 mixin 注入了特定的属性。
命名空间冲突。 Mixins 可能会在属性和方法名称上发生冲突,而 HOC 可能会在预期的 prop 名称上发生冲突。
性能问题,HOC 和无渲染组件需要额外的有状态组件实例,这会降低性能。
而 「Hook」模式带来的好处则是:

暴露给模板的属性具有明确的来源,因为它们是从 Hook 函数返回的值。
Hook 函数返回的值可以任意命名,因此不会发生名称空间冲突。
没有创建仅用于逻辑重用的不必要的组件实例。
当然,这种模式也存在一些缺点,比如 ref 带来的心智负担,详见drawbacks。

vue3有哪些新的组件

Fragment fu莱各闷T

  • 在Vue3中: 组件可以没有根标签, 内部会将多个标签包含在一个Fragment虚拟元素中

  • 好处: 减少标签层级, 减小内存占用

Teleport 台里破T
        什么是Teleport?—— Teleport 是一种能够将我们的组件html结构移动到指定位置的技术

很简单,假如有非常多的弹窗,那么如何管理它们的 z-index 呢,也就是同时弹窗时的层级关系,如果每个弹窗都在各自的父组件中,那么我们是没法控制的,所有有必要把它们都拧出来,放在同一个父元素下面,这样就可以方便的设置层级关系了。

Suspense 丝丝pen刺
        等待异步组件时渲染一些额外内容,让应用有更好的用户体验

Vue3传值

子组件获取父组件数据$parent

前端跨域

1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域

 js事件监听

什么是“事件监听”
DOM允许我们书写JS代码,来让HTML元素对事件作出反应;

事件:用户与网页的交互动作;eg:点击网页;

监听:是为了让计算机随时能够发现这个事件发生了,从而执行程序员预先编写的一些程序;

设置事件监听的方法主要有onxxx和addEventListener()两种

addEventListener是一个侦听事件并处理相应的函数

addEventListener() 方法用于向指定元素添加监听事件。且同一元素目标可重复添加,不会覆盖之前相同事件,配合 removeEventListener() 方法来移除事件。

  1. document.getElementById(元素id).addEventListener("click", function(){
  2. console.log("目标元素被点击了");
  3. });

async和await

在js中 可以通过async关键字来快速创建异步函数

特点

1.async声明的异步函数,它的返回值会自动包装为Promise

2.async声明的异步函数中可以使用await来调用其他异步函数

await

调用异步函数时,可以直接在函数前使用await关键字来对其进行调用

调用await,它会等待Promise执行出结果后将结果返回,可以通过变量来接收结果

注意:await并不是将异步函数改变为同步函数,只是改变了异步函数的调用方式

所以await不是说在哪都能用

当我们使用了await,catch方法就不能调用了,只能通过try-catch来处理可能的异常

await使用的位置

1.async声明的异步函数中

2.可以在模块的外层的作用域中使用await

js中的项目应用什么时候用async和await

获取分页数据的时候;获取列表,点击删除数据确定按钮、点击添加和修改的确定按钮的时候;

微信小程序路由跳转区别

他们的主要区别呢就是:

wx.navigateTo( ):保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面

wx.redirectTo( ):关闭当前页面,跳转到应用内的某个页面。但是不能跳转 tabbar 页面 瑞得莱克T

wx.switchTab( ):跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面 它波

wx.navigateBack( )关闭当前页面,返回上一页面或多级页面。可通过

getCurrentPages() 获取当前的页面栈,决定需要返回几层 卡瑞T

wx.reLaunch( ):关闭所有页面,打开到应用内的某个页面 瑞luang去

微信小程序请求

  1. wx.request({
  2. url: '',//地址
  3. method:'GET',//不行默认get,
  4. data:{}, //请求参数
  5. success(res){ //请求成功 res
  6. console.log(res);
  7. },
  8. fail(err){//请求失败
  9. },
  10. complete(res){ //请求完成
  11. }
  12. })

微信小程序生命周期

onLoad 监听页面加载=>发送请求 pages页面上的属性初始化完毕 options获取参数

onShow 页面首次显示

onReady 页面加载完毕=>可以做dom操作 ruai迪

onHide 页面隐藏 害d

onUnload 页面摧毁 昂漏的

组件生命周期

attached 在组件完全初始化完毕、进入页面节点树后被触发 呃塔去T

detached 在组件离开页面节点树后被触发 滴塔去T

show组件页面展示执行

hide组件所在的页面隐藏执行

resize组件所在的页面尺寸变化执行

微信小程序存储

  1. wx.setStorageSync('name', 'mxf') 存 name,可以直接存对象、布尔类型的值
  2. wx.getStorageSync('name') 取 name
  3. wx.removeStorageSync('name') 删name
  4. clearstorage 删除全部

微信小程序支付流程

点击付款=》给后端发送请求=》后端返回数据=》调用微信支付

点击付款=》获取需要付款的相关数据=》发送请求{{}}=》返回数据

  1. wx.requestPayment({
  2. timeStamp: '',时间戳,从 19701100:00:00 至今的秒数,即当前的时间
  3. nonceStr: '',随机字符串,长度为32个字符以下
  4. package: '',统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=***
  5. signType: 'MD5',签名算法,应与后台下单时的值一致
  6. paySign: '',签名,具体见微信支付文档
  7. success (res) { },接口调用成功的回调函数
  8. fail (res) { }接口调用失败的回调函数
  9. })

微信小程序性能优化

将微信小程序的项目中的图片,放到线上=》除了tabar中的图片

采用分包 主包有自己的pages tabar页面必须在主包内

wx:for =》添加key

尽量少用setData()=>重新执行页面渲染=》页面就获取到最新的数据

微信小程序组件之间传值

子组件给父组件传值this.trggerEvent('事件名称',传递的数据) bind事件名() 接收一个e参数

父组件给子组件传递数据自定义属性{{num=2}} 子组件properties接收

使用本地存储传递数据

使用路由传递数据 字符串拼接 模板字符串

使用全局变量传递数据 globalData 将数据存储为全局变量,在需要使用的页面通过 getApp().globalData 获取。

SEO优化

SEO是搜索引擎优化的英文缩写

如果构建大型网站,如商城类=》SSR服务器渲染

如果正常公司官网,播客网站等=》预渲染/静态化/Phantomjs都比较方便

如果是已用SPA开发完成的项目进行SEO优化,而且部署环境支持node服务器,使用Phantomjs 芬特木

watch 和 computed 和 methods 区别是什么

watch 是监听数据,computed 是计算属性,methods 是方法。

1.computed是计算属性,依赖其他属性值,并且computed的值有缓存。只有computed依赖的属性值发生变化,computed的值才会重新计算。 运用场景:一个数据属性在它所依赖的属性发生变化时,也要发生变化。对于任何复杂逻辑,你都应当使用计算属性。

2.watch:没有缓存性,起到观察的作用,即监听数据的变化。watch为一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。 运用场景:侦听一个数的变化,当该数据变化,来处理其他与之相关数据的变化,即一个数据影响别的多个数据。

3.methods:定义函数,它需要手动调用才能执行

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号