Vue面试题

发布于 2022-11-29  33 次阅读


Vue 如何实现双向数据绑定的

Observer(观察者)

  • 给data对象下所有的属性添加上get和set方法。
  • get: 提供属性值的获取。每个属性如果是第一次调用get方法,就给当前属性添加上一个消息订阅器
  • set:当监听到值有改动时,让消息订阅器通知watcher更新页面

Compiler(指令解析器)

  • 扫描根节点下的所有元素,找到每个节点上的指令并解析。
  • 譬如一个input标签有个v-model,首先通过vm实例把属性名相同的值赋给它,再就是添加事件(input),在事件触发的时候把标签上的值赋值给data中相应的属性
  • 如果是个{{}},就给这个属性添加一个watcher,在接收到消息订阅器的消息后调用update方法更新值

Dep(消息订阅器)

  • 负责发布订阅
  • 把订阅者放进数组中,每当notify被调用后(Observer的set改变时触发),会通知watcher订阅者更新视图

Watcher(订阅者)

  • 在消息订阅器上订阅每个属性的变化,在属性变化后收到消息执行回调update方法,从而更新视图

watch,computed,method区别

  1. computed有缓存的,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
  2. methods方法表示一个具体的操作,主要书写业务逻辑。只要调用就会再走一遍代码,不管有没有变化。
  3. watch一个对象,不存在缓存的。键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是computedmethods的结合体;

框架与库的区别

  • 框架是一整套解决方案,对项目侵入性大,开发到后期如果想更换框架,相当于重写
    • nodeJS express
  • 库(插件):提供某一个小功能,侵入性小,如果某个库无法完成某些需求,可以较容易的切换其他库完成
    • jquery ——> zepto
    • EJS ——> art-template

Node(后端)中的MVC 与 前端中的 MVVM 之前的区别

  • MVC是后端的分层开发概念
    • Model (模型层,数据的增删查改crud)
    • View (视图层,前端页面)
    • Control(控制层,处理业务逻辑,登录、注销)
  • MVVM是前端视图层的概念,主要关注视图层分离,也就是说,MVVM把前端的视图层,(每个页面)都分为了三部分:
    • Model (数据层,保存着每个页面中单独的数据)
    • View (视图层,每个页面中的HTML结构)
    • VM (视图模型层,V与M之间的调度者。每当V想要获取或保存数据,都要由VM做中间处理)
      • VM提供了数据的双向绑定

组件化和模块化的区别

  • 模块化:是从代码逻辑的角度进行划分
  • 组件化:是从UI界面的角度进行划分

前端路由和后端路由的区别

  • 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源
  • 前端路由:对于单页面应用程序来说,主要通过URL中的**hash(#号)**来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash(锚点)实现
    • 比如,www.baidu.com 后面加上 /#/xx 这样的内容不会引起页面的刷新
  • 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由)

为什么 Vue 中 style 标签添加上 scoped 就能让样式在当前组件有效

  • 利用css属性选择器实现的

因为只要添加上 scoped ,vue 就会自动给当前组件添加一个自定义 data-v-* 的属性。

然后所有该组件的样式,就会以css属性选择器的形式选中标签,让样式只在当前组件生效

总结一下scoped三条渲染规则:

  1. 给HTML的DOM节点加一个不重复data属性(形如:data-v-123)来表示他的唯一性
  2. 在每句css选择器的末尾(编译后的生成的css语句)加一个当前组件的data属性选择器(如[data-v-123])来私有化样式
  3. 如果组件内部包含有其他组件,只会给其他组件的最外层标签加上当前组件的data属性
// 组件
<div data-v-4412eb03>...</div>
// css
div[data-v-4412eb03] {...}

Vue 的响应式原理中 Object.defineProperty 有什么缺陷?为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?

  1. Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
  2. Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
  3. Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。

答案参考:Daily-Interview-Question - 第51题

Vue.set 是做什么用的?

为什么不能触发页面更新:

因为vue实例时,深度遍历data下所有属性, 把属性全转为 getter/setter。这样才能监听属性变化。所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

当你在对象上新加了一个属性newProperty,当前新加的这个属性并没有加入vue检测数据更新的机制(因为是在初始化之后添加的),vue.$set是能让vue知道你添加了属性, 它会给你做处理。

给数组或对象中添加属性,触发视图更新。

有一个obj:{a:1},想要this.obj.b=233,不会触发视图更新

Vue.set(this.obj, 'b', 233) or this.$set(this.obj, 'b', 233)

Vue内部自己实现了一个对象,其中包含自己的数组操纵方法,使用了能够触发页面更新

双向绑定和 vuex 是否冲突

当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 v-model 会比较棘手:

<input v-model="obj.message">

假设这里的 obj 是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,v-model 会试图直接修改 obj.message。在严格模式中,由于这个修改不是在 mutation 函数中执行的, 这里会抛出一个错误。

用“Vuex 的思维”去解决这个问题的方法是:给 <input> 中绑定 value,然后侦听 input 或者 change 事件,在事件回调中调用 action:

<input :value="message" @input="updateMessage">

// ...
computed: {
  ...mapState({
    message: state => state.obj.message
  })
},
methods: {
  updateMessage (e) {
    this.$store.commit('updateMessage', e.target.value)
  }
}

下面是 mutation 函数:

// ...
mutations: {
  updateMessage (state, message) {
    state.obj.message = message
  }
}

来源:https://vuex.vuejs.org/zh/guide/forms.html

本地映射外网

ngrok

最后更新于 2023-07-20