Vue前端面试题(下)

简介: 笔记

MVVM


谈谈你对MVVM开发模式的理解

MVVM分为Model、View、ViewModel三者。

Model 代表数据模型,数据和业务逻辑都在Model层中定义;

View 代表UI视图,负责数据的展示;

ViewModel 负责监听 Model 中数据的改变并且控制视图的更新,处理用户交互操作;

Model 和 View 并无直接关联,而是通过 ViewModel 来进行联系的,Model 和 ViewModel 之间有着双向数据绑定的联系。因此当 Model 中的数据改变时会触发 View 层的刷新,View 中由于用户交互操作而改变的数据也会在 Model 中同步。

这种模式实现了 Model 和 View 的数据自动同步,因此开发者只需要专注对数据的维护操作即可,而不需要自己操作 dom。


为什么会出现MVVM

前端开发中暴露出了三个痛点问题:

•       开发者在代码中大量调用相同的 DOM API,处理繁琐 ,操作冗余,使得代码难以维护。

•       大量的 DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。

•       当 Model 频繁发生变化,开发者需要主动更新到 View ;当用户的操作导致 Model 发生变化,开发者同样需要将变化的数据同步到 Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。其实,早期 jquery 的出现就是为了前端能更简洁的操作 DOM 而设计的,但它只解决了第一个问题,另外两个问题始终伴随着前端一直存在。MVVM 的出现,完美解决了以上三个问题。


DOM


什么是虚拟

虚拟DOM概念随着react的诞生而诞生,由facebook提出,其卓越的性能很快得到广大开发者的认可;继react之后vue2.0也在其核心引入了虚拟DOM的概念

vdom可以看作是一个使用javascript模拟了DOM结构的树形结构,这个树结构包含整个DOM结构的信息.。dom 树对应的虚拟 dom 对象( js 对象)


虚拟dom的原理

diff算法 深度优先遍历

diff的过程就是调用patch函数,就像打补丁一样修改真实dom

virtual dom有哪些好处

•       虚拟 DOM 不会立马进行排版与重绘操作

•       虚拟 DOM 进行频繁修改,然后一次性比较并修改真实 DOM 中需要改的部分,最后在真实 DOM 中进行排版与重绘,减少过多DOM节点排版与重绘损耗

•       虚拟 DOM 有效降低大面积真实 DOM 的重绘与排版,因为最终与真实 DOM 比较差异,可以只渲染局部

虚拟DOM主要做了什么虚拟DOM本身是什么(JS对象)为什么虚拟 DOM 的操作比 DOM 更快;

总之,一切为了减弱频繁的大面积重绘引发的性能问题,不同框架不一定需要虚拟DOM,关键看框架是否频繁会引发大面积的DOM操作

你的知道浏览器的虚拟DOM与真实DOM的区别(注意:需不需要虚拟DOM,其实与框架的DOM操作机制有关):

虚拟DOM不会进行排版与重绘操作

虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分(注意!),最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗

真实DOM频繁排版与重绘的效率是相当低的

虚拟DOM有效降低大面积(真实DOM节点)的重绘与排版,因为最终与真实DOM比较差异,可以只渲染局部(同2)


使用虚拟DOM的损耗计算:

总损耗=虚拟DOM增删改+(与Diff算法效率有关)真实DOM差异增删改+(较少的节点)排版与重绘


直接使用真实DOM的损耗计算:

总损耗=真实DOM完全增删改+(可能较多的节点)排版与重绘

总之,一切为了减弱频繁的大面积重绘引发的性能问题,不同框架不一定需要虚拟DOM,关键看框架是否频繁会引发大面积的DOM操作


说一下virtual Dom中key的作用

实际的标签中可能存在两个一模一样的两个节点,但是在virtual Dom中无法体现这个区别,另一方面为了加快diff算法的速度,一个区别节点的变量的需求变得非常必要。virtual Dom中需要给每个节点一个标识,作为判断是同一个节点的依据。所以这也是 Vue 和 React 中官方推荐列表里的节点使用唯一的 key 来保证性能。其中在diff算法中,大量使用了利用tagName和key组合判断节点之间差异的逻辑代码


为什么要使用虚拟DOM?

虚拟 dom 是相对于浏览器所渲染出来的真实 dom 的,在react,vue等技术出现之前,我们要改变页面展示的内容只能通过遍历查询 dom 树的方式找到需要修改的 dom 然后修改样式行为或者结构,来达到更新 ui 的目的。这种方式相当消耗计算资源,因为每次查询 dom 几乎都需要遍历整颗 dom 树,如果建立一个与 dom 树对应的虚拟 dom 对象( js 对象),以对象嵌套的方式来表示 dom 树,那么每次 dom 的更改 就变成了 js 对象的属性的更改 ,这样一来就能查找 js 对象的属性变化要比查询 dom 树的 性能开销小。

其实并不是查询 dom 树性能开销大而是 dom 树的实现模块和 js 模块是分开的这些跨模块的通讯增加了成本,以及 dom 操作引起的浏览器的回流和重绘,使得性能开销巨大,原本在 pc 端是没有性能问题的,因为 pc 的计算能力强,但是随着移动端的发展,越来越多的网页在智能手机上运行,而手机的性能参差不齐,会有性能问题。

他们的思想是每次更新 dom 都尽量避免刷新整个页面,而是有针对性的 去刷新那被更改的一部分 ,来释放掉被无效渲染占用的 gpu,cup 性能。

 

Vuex


是什么?怎么使用?哪种功能场景使用它?

vue框架中状态管理。在main.js引入store,注入。

新建了一个目录store.js,….. export 。

场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车


vuex有哪几种属性?

有五种,分别是 State、 Getter、Mutation 、Action、 Module

state => 基本数据(数据源存放地)

getters => 从基本数据派生出来的数据

mutations => 提交更改数据的方法,同步!

actions => 像一个装饰器,包裹mutations,使之可以异步。

modules => 模块化Vuex

 

你是怎么认识vuex的?

vuex可以理解为一种状态管理的开发模式或者框架,data中的属性需要共享给其他vue组件使用。状态为state集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。

vuex数据流动过程

1、vuex是什么

公共状态管理

解决多个非父子组件传值问题。

多个页面都能用Vuex中store公共的数据

a、并不是所有的数据都要放在Vuex中,只有各个组件公用的一些数据会放在Vuex当中

b、Vuex是一个公共状态管理模式 并不是数据库 所以不可能持久保存一些数据,当用户刷新浏览器的时候那么数据就有可能消失

c、Vuex主要应用在大型的单页面开发中

2、vuex的特点

1、遵循单向数据流

2、Vuex中的数据是响应式的

3、vuex的流程图:

总结下vuex数据传输流程

1、通过new Vuex.Store()创建一个仓库 state是公共的状态,state—>components渲染页面

2、在组件内部通过this.$store.state.属性 来调用公共状态中的state,进行页面的渲染。

3、当组件需要修改数据的时候,必须遵循单向数据流。组件里在methods中扩展mapActions,调用store里的actions里的方法。

4、actions中的每个方法都会接受一个对象 这个对象里面有一个commit方法,用来触发mutations里面的方法

5、mutations里面的方法用来修改state中的数据 mutations里面的方法都会接收到2个参数 一个是store中的state, 另外一个是需要传递到参数

6、当mutations中的方法执行完毕后state会发生改变,因为vuex的数据是响应式的 所以组件的状态也会发生改变

vuex的理解 对无状态组件的理解,使用过程中遇到的问题,如何解决的

watch computed区别

1、methods,computed的区别

例子:

var vm = new Vue({
el: '#app',
data: {
msg: 'nihao',
text: 'byebye'
},
computed: {
getmsg: function () {
return this.msg
}
},
methods:{
gettext:function () {
return this.msg
}
}
})
msg:{{getmsg}}
text:{{gettext()}}

在这个例子中,只要msg值发生变化,getmsg方法就会触发,而text的值发生变化,只要没有调用gettext方法,显示的值不会动态改变。就是说,methods中就是普通的方法,通过调用执行,computed中的方法会监听自己的依赖,依赖发生变化方法会自动执行。

1.      computed 和methods 达到的效果是相同的

2.      计算属性computed和methods都不应该使用箭头函数来定义计算属性 因为箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向Vue

不同点是:

3.      计算属性compute是基于他们的依赖(如果是实例范畴之外的依赖,比如非响应式的not reactive是不会触发属性更新的)进行缓存(计算属性的结果会被缓存),只有相关依赖会发生改变时才会重新求值,未改变只会返回只之前的结果,不在执行函数 .原值与新值一样不会触发,函数的返回值就是最终获取的值.

4.      computed是响应式的,methods并非响应式。

5.      调用方式不一样,computed定义的成员像属性一样访问,methods定义的成员必须以函数形式调用。

6.      computed是带缓存的,只有其引用的响应式属性(属性绑定)发生改变时才会重新计算(如果引用的属性没有改变,则调用上一次缓存值),而methods里的函数在每次调用时都要执行

7.      computed中的成员可以只定义一个函数作为只读属性,也可以定义get/set变成可读写属性,这点是methods中的成员做不到的。 computed 计算属性的方法在用属性时不用加(),而methods 方法在使用时要像方法一样去用,必须必须要加(){{ mes() }}

默认加载的时候先computed再watch,不执行methods;等触发某一事件后,则是:先methods再watch。

watch适合处理的场景是,侦听一个数的变化,当该数据变化,来处理其他与之相关数据的变化(该数据影响别的多个数据)==当数据发生变化时,执行异步操作或较大开销操作的情况。

computed适合处理的场景是,一个数据属性在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性。

vuex, mobx, redux各自的特点和区别 你在项目中怎么实现路由的嵌套

需要在 VueRouter 的参数中使用 children 配置,这样就可以很好的实现路由嵌套。


 

Vue 3.0


对它的了解

关于Vue 3.0有幸看过尤大的关于3.0版本的RFC Vue Function-based API RFC。 大致说了三个点,第一个是关于提出的新API setup()函数,第二个说了对于Typescript的支持,最后说了关于替换Object.defineProperty为Proxy的支持。

详细说了下关于Proxy代替带来的性能上的提升,因为传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,但使用Proxy又带来了浏览器兼容问题。

1、速度方面:

通过更新 runtime-core 与 runtime-dom ,支持了包括 Fragments、Portals与Suspense w/ async setup() 等(似乎有点越来越像 react),支持 Composition API 、Options API 和 typings,配合 Proxy 的引入,极大程度上提高了响应式的能力。

Composition API 与 Proxy 的运用使得组件化更加灵活,逻辑业务组件的编写与UI组件的多样化能够更好的实现。

2、体积方面:

runtime-core 体积压缩成了 约10kb

3、维护性:

代码迁移成 TypeScript (还没学的抓紧啦)

编译器(Compiler)优化,以下借用尤大大的特性更新图翻译一下:

使用模块化架构

优化 "Block tree"

更激进的 static tree hoisting 功能

支持 Source map

内置标识符前缀(又名 "stripWith")

内置整齐打印功能

移除 source map 和标识符前缀功能后,使用 Brotli 压缩的浏览器版本精简了大约 10KB

可见,编译器更多从数据结构入手,优化架构层级,降低使用成本。

4、更接近原生开发

5、让你更轻松开发

其次是 GitHub 上的源码目录:

reactivity 目录:数据响应式系统,主要使用 Proxy。

runtime-core 目录:支持 v-dom 与 Vue 原生的各种 API 在浏览器上的调用,调用 Vue 特性的相关代码。

runtime-dom 目录: 调用各类浏览器原生 DOM 事件的相关代码。

runtime-test 目录: 测试用的runtime的相关代码。

server-renderer 目录: SSR 相关代码。

compiler-core 目录: 支持 Vue 原生编写的 编译器特性,以及开发者编写的编译器特性的相关代码。

compiler-dom 目录: 调用浏览器的编译器的相关代码。

shared 目录: 无内置API。

vue 目录: 实现 vue 构建与编译的相关代码。

Vue3 proxy解决了哪些问题?Vue3 proxy的优劣Vue响应式原理

在官方文档中,有简单介绍一点,是基于 Object.defineProperty 去实现的;但是有一个要求,就是在 实例化 Vue 构造函数前,所有熬进行双向绑定的数据,都是要在 data 里面去做初始化的,哪怕是一个空值;因为在每次实例化的时候,Vue 会去检测 data ,查看并把存在属性用 Object.defineProperty 进行监听;在每一个需要判断或者展示当前响应式监听的数据时。

初始化的时候,我绑定了一个 name 属性,它在一个 div 里面做了展示;当我在 div 里面添加 name 展示的时候,其实在模板编译的时候,获取了一下 name 属性;因为前面有提到,我给当前的属性绑定了 Object.defineProperty ,所以在获取的时候,我会调用到 get 方法;

在这之前,我有实例化一个 dep 队列,把每次获取 name 属性的地方,做一个 push ;

当我接下来要做数据修改的时候,比如把 zhangsan 变成了 lisi ,那么在 set 方法里,把我当前属性的队列有监听当前属性的位置,全部更新一遍;最后把 data 对象里面的属性值做修改;


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

因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了


Vue 中怎么自定义过滤器

可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值

Vue.filter('reverse', function (value) {
  return value.split('').reverse().join('')
})

过滤器也同样接受全局注册和局部注册

对 keep-alive 的了解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染

 

 

 

可以使用API提供的props,实现组件的动态缓存


Vue 中 key 的作用

key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误。

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。


简述Vue的响应式原理


当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。

每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

 

Vue中如何监控某个属性值的变化?


比如现在需要监控data中,obj.a 的变化。Vue中监控对象属性的变化你可以这样:

watch: {
      obj: {
      handler (newValue, oldValue) {
        console.log('obj changed')
      },
      deep: true
    }
  }

deep属性表示深层遍历,但是这么写会监控obj的所有属性变化,并不是我们想要的效果,所以做点修改:

watch: {
   'obj.a': {
      handler (newName, oldName) {
        console.log('obj.a changed')
      }
   }
  }

还有一种方法,可以通过computed 来实现,只需要:

computed: {
    a1 () {
      return this.obj.a
    }
}

利用计算属性的特性来实现,当依赖改变时,便会重新计算一个新值。

Vue中给data中的对象属性添加一个新的属性时会发生什么,如何解决?

示例:

<template>
  <div>
    <ul>
      <li v-for="value in obj" :key="value">
        {{value}}
      </li>
    </ul>
    <button @click="addObjB">添加obj.b</button>
  </div>
</template>
<script>
export default {
  data () {
    return {
      obj: {
        a: 'obj.a'
      }
    }
  },
  methods: {
    addObjB () {
      this.obj.b = 'obj.b'
      console.log(this.obj)
    }
  }
}
</script>
<style></style>

点击button会发现,obj.b 已经成功添加,但是视图并未刷新:

 

 

原因在于在Vue实例创建时,obj.b并未声明,因此就没有被Vue转换为响应式的属性,自然就不会触发视图的更新,这时就需要使用Vue的全局api $set():

addObjB () {
      // this.obj.b = 'obj.b'
      this.$set(this.obj, 'b', 'obj.b')
      console.log(this.obj)
    }

$set()方法相当于手动的去把obj.b处理成一个响应式的属性,此时视图也会跟着改变了:

 

delete和Vue.delete删除数组的区别

delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。

Vue.delete直接删除了数组 改变了数组的键值。

   var a=[1,2,3,4]

   var b=[1,2,3,4]

   delete a[1]

   console.log(a)

   this.$delete(b,1)

   console.log(b)

 

 

 

 

Vue组件间的参数传递


1.父组件与子组件传值

父组件传给子组件:子组件通过props方法接受数据;

子组件传给父组件:$emit方法传递参数

2.非父子组件间的数据传递,兄弟组件传值

eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道。)

场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车

 

state

Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。

mutations

mutations定义的方法动态修改Vuex 的 store 中的状态或数据。

getters

类似vue的计算属性,主要用来过滤一些数据。

action

actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。

const store = new Vuex.Store({ //store实例
      state: {
         count: 0
             },
      mutations: {               
         increment (state) {
          state.count++
         }
          },
      actions: {
         increment (context) {
          context.commit('increment')
   }
 }
})
modules

项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
 }
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
 }
const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
})

对keep-alive 的了解?

keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。

使用方法

 

 

 

参数解释

include - 字符串或正则表达式,只有名称匹配的组件会被缓存

exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存

include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用v-bind 。

使用示例

 

 

 

 

 


css只在当前组件起作用


答:在style标签中写入scoped即可 例如:


vue.js的两个核心是什么?


答:数据驱动、组件系统


vue常用的修饰符?


答:.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用


vue等单页面应用及其优缺点


答:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。

缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

优点:

良好的交互体验

良好的前后端工作分离模式

减轻服务器压力

缺点:

SEO难度较高

前进、后退管理

初次加载耗时多

 

MVC


1.      MVC 是 Model-View-Controller 的缩写,即 模型—视图—控制器。

Model:后端传递的数据。

View:所看到的页面。

Controller:页面业务逻辑。

2.      MVC是单向通信。即View和Model,必须通过Controller来承上启下。

3.      使用MVC的目的就是将M和V的代码分离。

4.      MVC 和 MVVM 的区别 并不是VM完全取代了C,ViewModel 存在目的 在于抽离 Controller 中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在 Controller 中实现。也就是说MVVM实现的是业务逻辑组件的重用。

beforeCreate(创建前) 在数据观测和初始化事件还未开始

created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来

beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。

mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。

beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。

updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。

beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。

destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。

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

加载渲染过程

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子组件更新过程

父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

父beforeUpdate->父updated

销毁过程

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

介绍JSX

jsx可以像我们写HTML文件一样写业务代码,借助于babel,会将jsx语法转换成render语法,没有什么副作用。

vue template语法简单明了,数据操作与视图分离,开发体验友好。但是在某些特定场合中,会限制一些功能的扩展,如动态使用过滤器、解析字符串类型的模板文件等。以上功能的实现可以借助vue的render语法,render语法比template更偏底层,允许在HTML中使用js语法,可以极大的扩展HTML的能力。render函数注入了一个参数createElement,用来创建我们所需要的标签内容,有三个参数:HTML标签(elementTag),标签属性(option),子元素(children);从createElement的参数列表里面可以看出,如果组件内部结构嵌套比较深,render的语法写起来会比较繁琐,需要不断的调用createElement,对于想偷懒的我,还是想想有没有什么比较简易的写法,jsx无疑是一种很好的选择,区别在于jsx可以像我们写HTML文件一样写业务代码,借助于babel,会将jsx语法转换成render语法,没有什么副作用。


vue.nextTick实现原理


Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。

1.在Vue生命周期的created()钩子函数进行DOM操作一定要放到Vue.nextTick()的回调函数中。

在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题。

2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部尝试对异步队列使用原生的Promise.then和MessageChannel,如果执行环境不支持,会采用setTimeout(fn, 0)代替。

例如,当你设置vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个“tick”更新。多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员沿着“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback)。这样回调函数在 DOM 更新完成后就会调用。


Emit事件怎么发,需要引入什么


子组件: 通过 emit("listenToChildEvent", deliver)

父组件:进行绑定事件的,调用方法

v-on:listenToChildEvent="showMsgFromChild"

 

使用import时,webpack对node_modules里的依赖会做什么


配置相关路径


vue怎么监听数组


在将数组处理成响应式数据后,如果使用数组原始方法改变数组时,数组值会发生变化,但是并不会触发数组的setter来通知所有依赖该数组的地方进行更新,为此,vue通过重写数组的某些方法来监听数组变化,重写后的方法中会手动触发通知该数组的所有依赖进行更新。

我们知道通过Object.defineProperty()劫持数组为其设置getter和setter后,调用的数组的push、splice、pop等方法改变数组元素时并不会触发数组的setter,这就会造成使用上述方法改变数组后,页面上并不能及时体现这些变化,也就是数组数据变化不是响应式的(对上述不了解的可以参考这篇文章)。但实际用vue开发时,对于响应式数组,使用push、splice、pop等方法改变数组时,页面会及时体现这种变化,那么vue中是如何实现的呢?通过vue源码可以看出,vue重写了数组的push、splice、pop等方法

因为监听的数组带来的代价和一些问题,Vue使用了重写原型的方案代替。拦截了数组的一些方法,在这个过程中再去做通知变化等操作。


Proxy 相比于 defineProperty 的优势


Proxy的优势:

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

•       可以直接监听数组的变化

•       拦截方式较多

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

•       Proxy作为新标准将受到浏览器厂商重点持续的性能优化

Object.defineProperty的优势如下:

•       兼容性好,支持IE9

restful接口架构的优缺点


RESTful


架构优点:

1.      前后端分离,减少流量

2.      安全问题集中在接口上,由于接受json格式,防止了注入型等安全问题

3.      前端无关化,后端只负责数据处理,前端表现方式可以是任何前端语言(android,ios,html5)

4.      前端和后端人员更加专注于各自开发,只需接口文档便可完成前后端交互,无需过多相互了解

5.      服务器性能优化:由于前端是静态页面,通过nginx便可获取,服务器主要压力放在了接口上


什么是RESTful API?怎么使用?


是一个api的标准,无状态请求。请求的路由地址是固定的,如果是tp5则先路由配置中把资源路由配置好。标准有:.get  .post .put .delete


RESTful架构设计原则(不同公司具体细节可能不同):

1.      在接口命名时应该用名词,不应该用动词,因为通过接口操作到是资源。

2.      在url中加入版本号,利于版本迭代管理更加直观

https://www.rgc.com/v1/

3.      对于资源的操作类型应该是通过http动词表示。

•       GET /zoos:列出所有动物园

•       POST /zoos:新建一个动物园

•       GET /zoos/ID:获取某个指定动物园的信息

•       PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)

•       DELETE /zoos/ID:删除某个动物园

•       GET /zoos/ID/animals:列出某个指定动物园的所有动物

•       DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

4.      排序规则:默认时升序,‘-’为降序;多个排序规则时以逗号间隔组合。使用sort查询参数限制

GET /tickets?sort=-time,created_at

优先以time倒序显示,其次以created_at正序显示

5.      限制返回值的字段域:明确指定输出字段列表,用于控制网络带宽和速度。使用fields查询参数来限制。

GET /tickets?fileds=id,subject,customer_name,time&sort=-time

返回参数列表为id,subject,customer_name,time,并且以time字段倒序显

6.      HTTP Method分别对于资源的CURD操作

POST(CREATE):在服务器新建一个资源。

PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。

PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。

DELETE(DELETE):从服务器删除资源。

保证 POST,PUT,DELETE,PATCH,GET 操作幂等性。

7.      使用SSL(Secure Sockets Layer 安全套接层)

8.      参数和url采用蛇行命名方式。如:updated_time

9.      服务器请求和返回的数据格式,应该尽量使用JSON,避免使用XML。在 request中的Accept和Response中的Content-Type:application/json

总结:优秀的RESTful接口设计,能够根据请求的路径及请求方法就能看出这个接口主要是对具体某个资源进行什么方法的操作以及返回数据的规则等等。


vue 组件的优点,以及注册使用的过程


首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

例举3种强制类型转换 强制parseInt,parseFloat,number。


Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?


如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。

如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用


axios是什么 怎么使用?


请求后台资源的模块。npm install axios --save装好,

js中使用import进来,然后.get或.post。返回在.then函数中如果成功,失败则是在.catch函数中

axios+tp5进阶中,调用axios.post(‘api/user’)是进行的什么操作?axios.put(‘api/user/8′)呢?

添加用户操作,更新操作。

 

 

 

 


目录
相关文章
|
21天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
21天前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
23天前
|
缓存 前端开发 JavaScript
"面试通关秘籍:深度解析浏览器面试必考问题,从重绘回流到事件委托,让你一举拿下前端 Offer!"
【10月更文挑战第23天】在前端开发面试中,浏览器相关知识是必考内容。本文总结了四个常见问题:浏览器渲染机制、重绘与回流、性能优化及事件委托。通过具体示例和对比分析,帮助求职者更好地理解和准备面试。掌握这些知识点,有助于提升面试表现和实际工作能力。
60 1
|
26天前
|
JavaScript 前端开发 算法
前端优化之超大数组更新:深入分析Vue/React/Svelte的更新渲染策略
本文对比了 Vue、React 和 Svelte 在数组渲染方面的实现方式和优缺点,探讨了它们与直接操作 DOM 的差异及 Web Components 的实现方式。Vue 通过响应式系统自动管理数据变化,React 利用虚拟 DOM 和 `diffing` 算法优化更新,Svelte 通过编译时优化提升性能。文章还介绍了数组更新的优化策略,如使用 `key`、分片渲染、虚拟滚动等,帮助开发者在处理大型数组时提升性能。总结指出,选择合适的框架应根据项目复杂度和性能需求来决定。
|
1月前
|
前端开发 JavaScript 安全
在vue前端开发中基于refreshToken和axios拦截器实现token的无感刷新
在vue前端开发中基于refreshToken和axios拦截器实现token的无感刷新
91 4
|
21天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】 React与Vue:前端框架的巅峰对决与选择策略
|
28天前
|
前端开发 JavaScript API
2025年前端框架是该选vue还是react?有了大模型-例如通义灵码辅助编码,就不用纠结了!vue用的多选react,react用的多选vue
本文比较了Vue和React两大前端框架,从状态管理、数据流、依赖注入、组件管理等方面进行了详细对比。当前版本和下载量数据显示React更为流行,但Vue在国内用户量增长迅速。Vue 3通过组合式API提供了更灵活的状态管理和组件逻辑复用,适合中小型项目;React则更适合大型项目和复杂交互逻辑。文章还给出了选型建议,强调了多框架学习的重要性,认为技术问题已不再是选型的关键,熟悉各框架的最佳实践更为重要。
|
1月前
|
JSON 前端开发 JavaScript
Vue微前端新探:iframe优雅升级,扬长避短,重获新生
Vue微前端新探:iframe优雅升级,扬长避短,重获新生
107 0
|
1月前
|
JavaScript 前端开发 应用服务中间件
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
143 0
|
1月前
|
JavaScript 前端开发 应用服务中间件
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
Vue开发中,在实现单页面应用(SPA)前端路由时的hash模式和history模式的区别及详细介绍
26 0