跳至主要內容

Vue

zfh大约 11 分钟约 3440 字...

mvvm 和 mvc 区别

  • MVC 的思想:一句话描述就是 Controller 负责将 Model 的数据用 View 显示出来,换句话说就是在 Controller 里面把 Model 的数据赋值给 View

  • MVVM 新增了 VM 类,做了两件事达到了数据的双向绑定 一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听

  • MVVM 与 MVC 最大的区别就是:它实现了 View 和 Model 的自动同步,也就是当 Model 的属性改变时,我们不用再自己手动操作 Dom 元素,来改变 View 的显示,而是改变属性后该属性对应 View 层显示会自动改变(对应Vue数据驱动的思想)

  • 严格的 MVVM 要求 View 不能和 Model 直接通信,而 Vue 提供了$refs 这个属性,让 Model 可以直接操作 View,违反了这一规定,所以说 Vue 没有完全遵循 MVVM

为什么 data 是一个函数

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

Vue 组件通讯有哪几种方式

  • props$emit:父组件向子组件传递数据是通过 props 传递的,子组件给父组件传递数据是通过$emit 触发事件来做到的

  • $parent,$children 获取当前组件的父组件和当前组件的子组件

  • $attrs$listeners,适用于爷孙组件通讯

  • 父组件中通过 provide 来提供变量,然后在子组件中通过inject来注入变量。(官方不推荐在实际业务中使用,但是写组件库时很常用)

  • $refs 获取组件实例

  • envetBus 任意组件数据传递 这种情况下可以使用全局事件总线的方式 , 兄弟组件如何通讯?

  • vuex状态管理

Vue 的生命周期方法有哪些 一般在哪一步发请求

beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问

created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。这里没有$el,如果非要想与 Dom 进行交互,可以通过 vm.$nextTick 来访问 Dom

beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。

mounted 在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom 节点

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

updated 发生在更新完成之后,当前阶段组件 Dom 已完成更新。要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新,该钩子在服务器端渲染期间不被调用。

beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。我们可以在这时进行善后收尾工作,比如清除计时器。

destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

activated keep-alive 专属,组件被激活时调用

deactivated keep-alive 专属,组件被销毁时调用

可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

异步请求在哪一步发起?

如果异步请求不需要依赖 Dom 推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间;
  • ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性

v-if、v-show 的区别

  • v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。
  • v-show 会被编译成指令,条件不满足时控制样式将对应节点隐藏 (display:none)

使用场景

v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景 v-show 适用于需要非常频繁切换条件的场景

computed 和 watch 的区别

计算属性 computed

  1. 支持缓存,只有依赖数据发生改变,才会重新进行计算
  2. 不支持异步,当 computed 内有异步操作时无效,无法监听数据的变化
  3. computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值,只在相关响应式依赖发生改变时它们才会重新求值
  4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性, 一般用 computed
  5. 如果 computed 属性属性值是函数,那么默认会走 get 方法;函数的返回值就是属性的属性值;在 computed 中的,属性都有一个 get 和一个 set 方法,当数据变化时,调用 set 方法

侦听属性 watch

  1. 不支持缓存,数据发生改变,会直接触发相应的操作
  2. watch支持异步
  3. 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值
  4. 当一个属性发生变化时,需要执行对应的操作
  5. 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
    1. immediate:组件加载立即触发回调函数执行
    2. deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep 无法监听到数组的变动(通过数字下标修改数组中元素的值)和对象的新增,参考 vue 如何监测数据的表动,只有以响应式的方式触发才会被监听到

Vue 和 原生 js(jquery) 的区别

原生 js、jQuery:jQuery 只是对原生 js 的 API 进行了封装,操作更加方便,但是数据和视图层没有分开,本质上还是要操作 DOM 实现逻辑。

vue:不仅对 js 的 API 实现了封装,还实现了其他功能,使数据和视图层分开,通过数据驱动,操作的是数据,而不是 DOM,能让开发者更加关注到数据上

说说 Vue 的优点和缺点(或者项目为什么选择使用 Vue)

优点

  1. 视图数据分离,声明式编码,让操作者不再直接操作 DOM 对象,有更多的去时间思考业务逻辑

  2. 传统方式编写,依赖关系混乱,代码复用率不高。组件化可以提高代码可阅读性以及代码复用率

  3. 虚拟DOM+优秀的diff算法,尽量复用 DOM 节点

4.渐进式框架,只需一个轻量小巧的核心库,可以引入各式各样的Vue插件进行扩展。

缺点

Vue 是单页面应用对于搜索引擎不友好,影响SEO,比如两个 Vue 页面(路由)它的路径是:index.html#aaa 和 index.html#bbb,但对于搜索引擎来说就是一个页面 index.html,这时搜索引擎就无法收录你的页面

Vue2 和 Vue3 的响应式区别

Vue2:

基于Object.defineProperty不具备监听数组的能力,需要重新定义数组的原型来达到响应式

Object.defineProperty 无法检测到对象属性的添加和删除

由于 Vue 会在初始化实例时对属性执行getter/setter转化,所有属性必须在 data 对象上存在才能让 Vue 将它转换为响应式

深度监听需要一次性递归,对性能影响比较大

Vue3:

基于ProxyReflect可以原生监听数组,可以监听对象属性的添加和删除

提示

  • Proxyopen in new window对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

  • Reflectopen in new window是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handlers (en-US)的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

不需要一次性遍历data的属性,可以显著提高性能

因为ProxyES6新增的属性,有些浏览器还不支持,只能兼容到IE11

vue-router 有几种路由方式?区别?

hash:url#后面的东西就是 hash,hash 虽然出现再 URL 中,但不会被包含再 HTTP 中,对后端完全没有影响,因此改变 hash 不会重新加载页面(兼容性好,但不美观)

history:利用 HTML5 History 中新增的 pushState()和 replaceState()当调用它们修改浏览器的历史记录栈后,虽然当前 url 改变了,但浏览器不会刷新页面。这就为单页面应用前端路由“更新视图但不重新请求页面”提供了基础,虽然美观,但是刷新会出现 404,需要后端进行配置

讲一下 VueX 的工作原理?

  1. Vuex 本质是一个对象
  2. Vuex 对象有两个属性,一个是 install 方法,一个是 Store 这个类
  3. install 方法的作用是将 store 这个实例挂载到所有的组件上,注意是同一个 store 实例。
  4. Store 这个类拥有 commit,dispatch 这些方法,Store 类里将传入的 state 包装成 data,作为 new Vue 的参数,从而实现了 state 值的响应式。

谈一下对 vuex 的理解

vuex 是专门为 vue 提供的全局状态管理系统,用于多个组件中数据共享数据缓存 (无法持久化、内部核心原理是通过创造一个全局实例 new Vue)

主要包括以下几个模块:

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。

  • Getter:getters 可以认为是 store 的计算属性,就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

  • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数。

  • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。

  • Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。(命名空间)

Vuex 中 mapState、mapGetters、mapMutations、mapActions

四个 map 方法的使用open in new window

Vue.set()和 vm.$set()

可以使原来对象数组无法监听变的可监听,使数据正常渲染

$nexttick 是怎么可以获取到更新后的 dom 的?

vue 是依靠数据驱动视图更新的,该更新的过程是异步的。即:当侦听到你的数据发生变化时, Vue 将开启一个队列(该队列被 Vue 官方称为异步更新队列)。视图需要等队列中所有数据变化完成之后,再统一进行更新。

$nextTick(callback),这里的回调函数( callback)将在数据更新完成,视图更新完毕之后被调用

vue-router 中 push 和 replace 的区别

1.this.$router.push()

描述:跳转到不同的 url,但这个方法会向 history 栈添加一个记录,点击后退会返回到上一个页面

2.this.$router.replace()

描述:同样是跳转到指定的 url,但是这个方法不会向 history 里面添加新的记录,点击返回,会跳转到上上一个页面上一个记录是不存在的

3.this.$router.go(n)

相对于当前页面向前或向后跳转多少个页面,类似 window.history.go(n)。n 可为正数可为负数。正数返回上一个页面

项目中 vue-router 设置的是 history 模式,部署到服务器上要怎么处理

我在 koa2 项目中,使用中间件 koa2-connect-history-api-fallback open in new window,它用于处理 vue-router 使用 history 模式返回 404 的问题

上次编辑于:
本站勉强运行 小时
本站总访问量
網站計數器