Vue.Js

Module Four - Vue

「About Base」

MVVM的理解?与MVC有什么不同?

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

a.使用MVC的目的就是将模型与视图分离

b.MVC属于单向通信,必须通过Controller来承上启下,既必须由控制器来获取数据,将结果返回给前端,页面重新渲染

2.MVVM指的是Model-View-ViewModel,即模型-视图-视图模型,「模型」指的是后端传递的数据,「视图」指的是所看到的页面,「视图模型」是MVVM的核心,它是连接View与Model的桥梁,实现view的变化会自动更新到viewModel中,viewModel中的变化也会自动显示在view上,是一种数据驱动视图的模型

区别:

1.MVC中的Control在MVVM中演变成viewModel

2.MVVM通过数据来显示视图,而不是通过节点操作

3.MVVM主要解决了MVC中大量的DOM操作,使页面渲染性能降低,加载速度慢,影响用户体验的问题

Vue响应式数据的原理?

Vue底层对于响应式数据的核心是object.defineProperty,Vue在初始化数据时,会给data中的属性使用object.defineProperty重新定义属性(劫持属性的getter和setter),当页面使用对应属性时,会进行依赖收集(收集当前组件的watcher),如果属性发生变化,会通知相关依赖进行更新操作

     总结:Vue通过数据劫持配合发布者-订阅者的设计模式,内部通过调用object.defineProperty()来劫持各个属性的getter和setter,在数据变化的时候通知订阅者,并触发相应的回调

Vue是如何检测数组的变化?

核心思想:使用了函数劫持的方式,重写了数组的方法(push,pop,unshift,shift···)

Vue将data中的数组,进行了原型链的重写,指向了自己所定义的数组原型方法,当调用数组的API时,可以通知依赖更新,如果数组中包含着引用类型,会对数组中的引用类型再次进行监控

为什么Vue要采取异步渲染?

因为如果不采用异步渲染,那么每次更新数据都会进行重新渲染,为了提高性能,Vue通过异步渲染的方式,在本轮数据更新后,再去异步更新视图

Object.defineProperty有什么缺点?(为什么Vue3.0开始使用Proxy实现响应式)

1.Object.defineProperty只能劫持对象的属性,因此需要遍历对象的每个属性,而Proxy可以直接代理对象

2.Object.defineProperty对新增属性需要手动进行观察,由于Object.defineProperty劫持的是对象的属性(第一点),所以新增属性时,需要重新遍历对象,对其新增属性再使用Object.defineProperty进行劫持 (正是这个原因导致我们在给data中的数组或对象新增属性时,需要使用$set才能保证视图可以更新)

3.Proxy性能高,支持13种拦截方式

nextTick实现原理是什么? 在Vue中有什么作用

原理:EventLoop事件循环

作用:在下次dom更新循环结束后执行延迟回调,当我们修改数据之后立即使用nextTick()来获取最新更新的Dom

watch中的deep:true是如何实现的?

当用户指定了watch中的deep:true时,如果当前监控的值是数组类型(对象类型),会对对象中的每一项进行求值,此时会将当前watcher存入到对应属性的依赖中,这样数组中的对象发生变化也会通知数据进行更新

缺点:由于需要对每一项都进行操作,性能会降低,不建议多次使用deep:true

为什么v-if与v-for不建议连在一起使用?

v-for优先级高于v-if,如果连在一起使用的话会把v-if给每一个元素都添加上,重复运行于每一个v-for循环中,会造成性能浪费

组件的data为什么要写成函数形式

在Vue中,组件都是可复用的,一个组件创建好后,可以在多个地方重复使用,而不管复用多少次,组件内的data都必须是相互隔离,互不影响的,如果data以对象的形式存在,由于Javascript中对象是引用类型,作用域没有隔离,因此data必须以函数的形式返回

总结:为了实现每个组件实例可以维护独立的数据拷贝,不会相互影响

❗ 小知识:new Vue根组件不需要复用,因此不需要以函数方式返回

v-for中的key的作用是什么?

key是为每个vnode指定唯一的id,在同级vnode的Diff过程中,可以根据key快速的进行对比,来判断是否为相同节点,并利用key的唯一性生成map来更快的获取相应的节点,另外指定key后,可以保证渲染的准确性

Vue每个生命周期什么时候被调用?

beforeCreate→ 在实例初始化之后,数据观测(data observer)之前被调用

created→ 实例已经创建完成之后被调用。在这里,实例已完成以下配置:

数据观测(data observer)

属性和方法的运算

watch/event事件回调

但这里还没有$el

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

mounted→$el被新创建的vm.$el替换,并挂载到实例上之后调用该钩子

beforeUpdate→ 数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前

updated→ 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子(该钩子在服务器端渲染期间不被调用)

beforeDestroy→ 实例销毁之前调用,在这里,实例仍然完全可以使用

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


Vue每个生命周期内部可以做什么事?

created→ 实例已经创建完成,由于它是最早触发的,所以可以进行一些数据,资源的请求

mounted→ 实例已经挂载完成,可以进行一些DOM操作

beforeUpdate→ 可以在该钩子中进一步地更改状态,这不会触发附加的渲染过程

updated→ 可以执行依赖于DOM的操作。但在大多数情况下,应避免在该钩子中更改状态,因为这可能导致更新无限循环

destroyed→ 可以执行一些优化操作,例如清空定时器,清理缓存,解除事件绑定等

Vue组件有哪些声明生命周期钩子?

「beforeCreate」、「created」、「beforeMount」、「mounted」、「beforeUpdate」、「updated」、「beforeDestroy」、「destroyed」

❗ 小知识:

<keep-alive>拥有自己独立的钩子函数activated|deactivated

activated→ 在被<keep-alive>包裹的组件中才有效,当组件被激活时使用该钩子

deactivated→ 在被<keep-alive>包裹的组件中才有效,当组件被停止时使用该钩子

Vue的父组件和子组件生命周期钩子执行顺序是什么?

理解渲染过程:

父组件挂载完成必须是等到子组件都挂载完成之后,才算父组件挂载完,所以父组件的mounted肯定是在子组件mounted之后

So:「父」beforeCreate → 「父」created → 「父」beforeMount → 「子」beforeCreate → 「子」created → 「子」beforeMount → 「子」mounted → 「父」mounted

1.子组件更新过程(取决于对父组件是否有影响)

影响到父组件: 「父」beforeUpdate → 「子」beforeUpdate → 「子」updated → 「父」updated

不影响父组件: 「子」beforeUpdate → 「子」updated

2.父组件更新过程(取决于对子组件是否有影响)

影响到子组件: 「父」beforeUpdate → 「子」beforeUpdate → 「子」updated → 「父」updated

不影响子组件: 「父」beforeUpdate → 「父」updated

3.销毁过程

「父」beforeDestroy → 「子」beforeDestroy → 「子」destroyed → 「父」destroyed

怎么理解vue的单向数据流

在vue中,父组件可以通过prop将数据传递给子组件,但这个prop只能由父组件来修改,子组件修改的话会抛出错误

如果是子组件想要修改数据,只能通过$emit由子组件派发事件,并由父组件接收事件进行修改

为什么子组件不可以修改父组件传递的Prop?(为什么vue提倡单向数据流)

由于vue提倡单向数据流,即父级props的更新会流向子组件,但反过来则不行。这是为了防止意外的改变父组件的状态,使得应用的数据流变得难以理解。如果破坏了单项数据流,当应用复杂时,debug的成本将会非常高

组件间有哪些通信方式?

1.父子组件通信

        props/event

        $parent/$children

        ref

        provide/inject

.       sync

2.非父子组件通信

          eventBus

3.通过根实例$root

         vuex

         $attr/$listeners

         provide/inject

❗ 小知识:关于.sync的使用

@假设有一个组件 comp

           <comp :foo.sync="bar"></comp>

@传递foo值并用sync修饰,会被扩展成

          <comp :foo="bar" @update:foo="val => bar = val"></comp>

@当子组件comp需要更新foo的值时,它需要显示地触发一个更新事件

           this.$emit('update:foo', newValue)

vue的动态组件

多个组件通过同一个挂载点进行组件的切换,is的值是哪个组件的名称,那么页面就会显示哪个组件

                        <div :is='xxx'></div>

递归组件的用法

组件是可以在它们自己的模板中调用自身的,不过它们只能通过name选项来做这件事

         首先我们要知道,既然是递归组件,那么一定要有一个结束的条件,否则就会导致组件无限循环使用,最终出现max stack size exceeded的错误,也就是栈溢出。所以,我们应该使用v-if = 'false'来作为递归组件的结束条件,当遇到v-if = 'false'时,组件将不会再进行渲染

自定义组件的语法糖v-model是怎么样实现的?(v-model如何实现双向绑定)

v-model本质是v-bind和v-on的语法糖,用来在表单控件或组件上创建双向绑定。

<input v-model='searchText'>

                                                       等价于

            <inputv-bind:value='searchText'    v-on:input='searchText = $event.target.value'>

在一个组件上使用v-model,默认会为组件绑定名为value的prop和名为input的事件

Vuex和单纯的全局对象有什么区别?

vuex和全局对象主要有两大区别:

         1.vuex的状态存储是响应式的。当vue组件从store中读取状态时,若store中的状态发生变化,那么相应的组件也会得到高效更新

        2.不能直接改变store中的状态,改变store中的状态唯一方法是显示地提交mutation(commit)。这样使得我们可以方便地跟踪每一个状态的变化

为什么vuex的mutation中不能做异步操作?

vuex中所有的状态更新的唯一方式都是提交mutation,异步操作需要通过action来提交mutation(dispatch)。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地使用vuex

每个mutation执行完后都会对应得到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现time-travel了。

如果mutation支持异步操作,就没有办法知道状态是何时更新,无法很好的进行状态追踪,影响调试效率

v-show / v-if 的区别是什么?

   1、v-if指如果条件不成立则不会渲染当前指令所在节点的Dom元素,会在切换过程中对条件块的事件监听器和子组件进行销毁和重建

   2、v-show只是基于css进行切换,不管条件是什么,都会进行渲染(切换display:block | none)

So:v-if切换的开销较大,而v-show初始化的开销较大,所以在需要频繁切换显示和隐藏的Dom元素时,使用v-show更合适,渲染后很少进行切换则使用v-if较合适

computed / watch 的区别是什么?

     1、computed是依赖于其他属性的一个计算值,并且具备缓存,只有当依赖的值发生变化才会更新(自动监听依赖值的变化,从而动态返回内容)

     2、watch是在监听的属性发生变化的时候,触发一个回调,在回调中执行一些逻辑

So:computed和watch区别在于用法上的不同,computed适合在模板渲染中,如果是需要通过依赖来获取动态值,就可以使用计算属性。而如果是想在监听值变化时执行业务逻辑,就使用watch

computed / methods 的区别是什么?

    1、computed是基于它们响应式依赖进行缓存,只有在依赖值发生变化,才会进行计算求值

    2、methods每次使用都会执行相应的方法

Vue中 v-html 有什么作用?会导致什么问题?

v-html可以用来识别HTML标签并渲染出去

导致问题:在网站上动态渲染任意Html,很容易导致受到Xss攻击,所以只能在可信内容上使用v-html,且永远不能用于用户提交的内容上

keep-alive在vue中的作用是什么?

包裹在<keep-alive>里组件,在切换时会保存其组件的状态,使其不被销毁,防止多次渲染,

·keep-alive拥有两个独立的生命周期(activated|deactivated),使keep-alive包裹的组件在切换时不被销毁,而是缓存到内存中并执行deactivated钩子,切换回组件时会获取内存,渲染后执行activated钩子

如何新增自定义指令?

1、创建局部指令

var app = new Vue({ 

 el:'#app', data: {

 }, 

 // 创建指令(可以多个) 

 directives: {

 // 指令名称

 dir1: { 

 inserted(el) { 

 // toDo

 } } }})

2、创建全局指令

Vue.directive('dir2', {

    inserted(el) {

        // inserted 表示元素插入时

        // toDo

    }

})

3、指令使用

<div id="app">

    <div :dir1='..'></div>

</div>

如何自定义过滤器

1、创建局部过滤器

var app = new Vue({

 el:'#app', 

 data: { },

        // 创建指令(可以多个) 

 filters: { 

          // 指令名称 

 newfilter:function(value){ 

         // toDo

 }

 }})

2、创建全局过滤器

Vue.filter('newfilter', function (value) {

    // toDo

})

3、过滤器使用

<div>{{xxx | newfilter}}</div>

vue常用修饰符有哪些,有什么用?

1、.prevent:拦截默认事件

2、.passive:不拦截默认事件

3、.stop:阻止事件冒泡

4、.self:当事件发生在该元素而不是子元素的时候会触发

5、.capture:事件侦听,事件发生的时候会调用

vue等单页面应用优缺点是什么?

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

2、缺点

a.不支持低版本的浏览器,最低只支持IE9

b.不利于SEO的优化

c.第一次加载首页耗时相对长一些,不可以使用浏览器的导航按钮需要自行实现前进和后退

如何让css仅在当前组件中起作用

           在<style>标签上写入scoped即可

「About Router」

关于路由,route / router 有什么区别?

1、route表示路由信息对象,包括path,params,hash,query,fullPath,matched,name等路由信息参数

2、router表示路由实例对象,包括了路由的跳转方法,钩子函数等

 vue-Router中有哪些导航守卫

          1、「全局前置钩子」:beforeEach,beforeResolve,afterEach

          2、「路由独享守卫」:beforeEnter

          3、「组件内部守卫」:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave

导航解析流程:

         1、导航被触发

         2、在失活的组件里调用beforeRouteLeave离开守卫

         3、调用全局的beforeEach守卫

         4、在重用的组件里调用beforeRouteUpdate守卫

         5、在路由配置里调用beforeEnter守卫

         6、解析异步路由组件

         7、在被激活的组件里调用beforeRouteEnter守卫

         8、调用全局的beforeResolve守卫

         9、导航被确认

         10、调用全局的afterEach守卫

         11、触发Dom更新

         12、用创建好的实例调用beforeRouteEnter守卫中传给next的回调

vue-Router 中 hash / history 两种模式有什么区别?

hash模式会在url上显示'#',而history模式没有

刷新页面时,hash模式可以正常加载到hash值对应的页面,history模式没有处理的话,会返回404,一般需要后端将所有页面都配置重定向到首页路由

兼容性上,hash模式可以支持低版本浏览器和IE

vue-router 中 hash / history 是如何实现的?

 1、hash模式

        #后面hash值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面,同时通过监听hashchange事件可以知道hash发生了哪些变化。根据hash变化来实现页面的局部更新

2、history模式

         history模式的实现,主要是Html5标准发布的两个Api(pushState和replaceState),这两个Api可以改变url,但是不会发送请求,这样就可以监听url的变化来实现局部更新

怎么定义 vue-router 的动态路由?怎么获取传过来的值

   1、动态路由的创建,主要是使用path属性过程中,使用动态路径参数,以冒号开头

{

    path:'/details/:id',

    name:'Details',

    components:Details

}

# 访问`details`前缀下的路径,例如`details/1`,`details/2`等,都会映射到`Details`这个组件

2、当匹配到/details下的路由时,参数值会被设置到this.$route.params下,所以通过这个属性可以获取动态参数

      this.$route.params.id

vue-router 传参方式有哪些?

      1、通过params

             只能用name,不能用path

            参数不会显示在url上

            浏览器强制刷新会清空参数

      2、通过query

              只能用path,不能用name

              name可以使用path路径

             参数会显示在url上

             浏览器刷新不清空参数

「About Vuex」


vuex有什么优缺点?

     A、优点: 

            解决了非父子组件的消息传递(将数据存放在state中)

            减少了Ajax请求次数,有些情景可以直接从内存中的State获取

     B、缺点:

            刷新浏览器,vuex中的State就会重新变回初始化状态

vuex有哪几种属性?

State:vuex的基本数据,用来存储变量

Getter:从基本数据state派生的数据,相当于state的计算属性

Mutation:提交更新数据的方法,必须是同步的(需要异步则使用action)。每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)

Action:和mutation的功能大致相同,不同在于

action提交的是mutation,而不是直接变更状态

action可以包含任意异步操作

Module:模块化vuex,可以让每一个模块拥有自己的state,mutation,action,getter,使得结构清晰,方便管理

vuex 中的 state 有什么特性?

vuex就是一个仓库,仓库里面放了很多对象,其中state就是数据源存放地

state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据改变,依赖这个数据的组件也会更新数据

它通过mapState把全局的state和getters映射到当前组件的computed计算属性中

vuex 中的 getters 有什么特性?

getters可以对state进行计算操作,可以把它看做store的computed计算属性

虽然在组件中也可以做计算属性,但getters可以在多个组件之间复用

如果一个状态只在一个组件内使用,是可以不用getters

Vue 中对 Ajax 请求代码应该写在组件的 methods 中还是 vuex 的 actions 中?

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

如果被其他地方复用,可以将请求放入action里,方便复用;如果不需要复用这个请求,直接写在Vue文件里会更方便.

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容