1、MVVM是什么?MVVM 与 MVC 的区别?它和其他框架(jquery)的区别是什么?哪些场景适合使用?
MVVM 是 Model-View-ViewModel 的缩写。
Model(模型层)代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。(axios data vuex(state))
View (视图层)代表UI组件,它负责将数据模型转化成UI展现出来。(template < /template>)
ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。(viewmodel是双向绑定实现的机制)
MVVM 与 MVC 的区别:
MVC 模型视图控制器,视图是可以直接访问模型,所以,视图里面会包含模型信息,mvc 关注的是模型不变,所以,在 mvc 中,模型不依赖视图,但是视图依赖模型。
MVVM 模型 视图和 VM,VM 是作为模型和视图的桥梁,当模型层数据改变,VM 会检测到并通知视图层进行相应的修改。
它和其他框架区别:MVVM 是通过数据来显示视图;jquery 是通过节点来操作的。
适用场景:适用于数据操作比较多的场景。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
2、vue 与 angular 的区别?vue 与 react 的区别,使用场景分别是什么?vue 的优点和缺点?vue 全家桶开发?什么是 vue 渐进式开发?
1、与AngularJS的区别
相同点:都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不同点:AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
2、与React的区别
相同点: 都有自己的脚手架工具;支持项目工程化;都是数据驱动视图的框架; 中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点: React 采用的 Virtual DOM 会对渲染出来的结果做脏检查。 Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作 DOM。 React:数据单向流,语法-jsx,在 React 中需要使用 setState() 方法去更新状态。 Vue:数据双向绑定,语法-HTML,state 对象并不是必须的,数据由 data 属性在 Vue 对象中进行管理。
优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。
vue 全家桶开发:指的是:vue-router,vuex, vue-resource
渐进式:引入 vue.js 部分功能,逐渐取代之前的原生js、jquery。
3、什么是虚拟DOM?为什么使用虚拟DOM?虚拟DOM的优缺点?vue怎么操作dom?vue2.x 和 vue3.x 渲染器的 diff 算法分别说一下
什么是虚拟DOM:
用 js 模拟一颗 dom 树,放在浏览器内存中,当你要变更时,虚拟 dom 使用 diff 算法进行新旧虚拟 dom 的比较,将变更放到变更队列中,反应到实际的dom树,减少了dom操作。 虚拟 DOM 将 DOM 树转换成一个 JS 对象树,diff 算法逐层比较、删除、添加操作;但是,如果有多个相同的元素,可能会浪费性能,所以,react 和 vue-for 引入 key 值进行区分。(让我们不用直接操作DOM元素,只操作数据便可以重新渲染页面)
为什么使用虚拟DOM
1、手动操作DOM比较麻烦,还需要考虑浏览器兼容性问题,虽然有jQuery等库简化DOM操作,但是随着项目的复杂DOM操作复杂提升
2、为了简化DOM的复杂操作于是出现了各种MVVM框架,MVVM框架解决了视图和状态的同步问题
3、为了简化视图的操作我们可以使用模板引擎,但是模板引擎没有解决跟踪状态变化的问题,于是Virtual DOM出现了. Vitual DOM的好处是当状态改变时不需要立即更新DOM,只需要创建一个虚拟树来描述DOM, Virtual DOM内部将弄清楚如何有效(if)的更新DOM
优点:
1、维护视图和状态的关系
2、复杂视图情况下提升渲染性能 3、除了渲染DOM以外,还可以实现SSR(Nuxt.js/Next.js)、 原生应用(Weex/React Native)、 小程序(mpvue/uni-app)等
4、虚拟DOM具有批处理和高效的Diff算法,最终表现在DOM上的修改只是变更的部分,可以保证非常高效的渲染,优化性能.
缺点:
首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。
vue怎么操作dom 设置:ref=’name’ 使用:this.\(refs.name</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>diff 算法</strong></p><p style="letter-spacing:.05em;">diff算法比较新旧虚拟 dom 的过程:</p><p style="letter-spacing:.05em;">如果节点类型相同,则比较数据,修改数据;</p><p style="letter-spacing:.05em;">如果节点不同,直接干掉节点及所有子节点,插入新的节点;</p><p style="letter-spacing:.05em;">如果给每个节点都设置了唯一的key,就可以准确的找到需要改变的内容,否则就会出现修改一个地方导致其他地方都改变的情况。</p><p style="letter-spacing:.05em;">比如A-B-C-D, 我要插入新节点A-B-M-C-D,实际上改变的了C和D。但是设置了key,就可以准确的找到B C并插入</p><p style="letter-spacing:.05em;">正常diff两个树的时间复杂度是0(n^3),但实际情况下我们很少会进行跨层级的移动DOM,所以vue将Diff进行了优化,从o(n^3)->0(n),只有当新旧 children都为多个子节点时才需要用核心的diff算法进行同层级比较。</p><p style="letter-spacing:.05em;">Vue2的核心diff算法采用了双端比较的算法,同时从新旧 children的两端开始进行比较,借助key值找到可复用的节点,再进行相关操作。相比React的diff算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。</p><p style="letter-spacing:.05em;">Vue3.x借鉴了算法 ivi和 inferno算法 在创建VNode时就确定其类型,以及在 mount/ patch的过程中采用位运算来判断一个VNode的类型,在这个基础之上再配合核心的diff算法,使得性能上较Vue2.x有了提升。(实际的实现可以结合vue3x源码看。)</p><p style="letter-spacing:.05em;">虚拟dom的作用:虚拟dom是为了解决浏览器性能问题而被设计出来的;当操作数据时,将改变的dom元素缓存起来,都计算完后再通过比较映射到真实的dom树上</p><p style="letter-spacing:.05em;"> </p>4、Vue 的生命周期<p style="letter-spacing:.05em;"><strong>创建前 beforeCreate:</strong> 在数据观测和初始化事件还未开始</p><p style="letter-spacing:.05em;"><strong>创建后 created</strong>: 完成数据观测,属性和方法的运算,初始化事件,\)el属性还没有显示出来
载入前 beforeMount: 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
载入后 mounted:在el 被新创建的 vm.\(el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。</p><p style="letter-spacing:.05em;"><strong>更新前 beforeUpdate</strong>: 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。</p><p style="letter-spacing:.05em;"><strong>更新后 updated</strong>: 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。</p><p style="letter-spacing:.05em;"><strong>销毁前 beforeDestroy</strong>: 在实例销毁之前调用。实例仍然完全可用。</p><p style="letter-spacing:.05em;"><strong>销毁后 destroyed</strong>:在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。</p><p style="letter-spacing:.05em;"><strong>什么是 vue 生命周期? </strong></p><p style="letter-spacing:.05em;">Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。</p><p style="letter-spacing:.05em;"><strong>vue 生命周期的作用是什么?</strong></p><p style="letter-spacing:.05em;">它的生命周期中有多个事件钩子,让我们在控制整个 Vue 实例的过程时更容易形成好的逻辑。</p><p style="letter-spacing:.05em;"><strong>vue 生命周期总共有几个阶段?</strong></p><p style="letter-spacing:.05em;">它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。</p><p style="letter-spacing:.05em;"><strong>第一次页面加载会触发哪几个钩子?</strong></p><p style="letter-spacing:.05em;"> 会触发这几个钩子: beforeCreate、created、beforeMount 和 mounted 。</p><p style="letter-spacing:.05em;"><strong>DOM 渲染在哪个周期中就已经完成? </strong>DOM 渲染在 mounted 中就已经完成了。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>vue 中生命周期钩子函数有哪些,请写出语法</strong></p><p style="letter-spacing:.05em;"> 创建前beforeCreate 创建后created、挂载前beforeMount 挂载后mounted、更新前beforeUpdate 更新后updated、销毁前beforeDestroy 销毁后destroyed、激活activated 未激活deactivated 未激活是啥</p><p style="letter-spacing:.05em;"><strong>什么时候触发激活和未激活生命周期钩子函数</strong></p><p style="letter-spacing:.05em;">当页面或者组件被缓存则激活 activated,未激活 deactivated 会取代创建和销毁</p><p style="letter-spacing:.05em;"><strong>挂载和创建之间的区别</strong>:</p><p style="letter-spacing:.05em;">创建之后只可以访问数据不可以操作dom 挂载之后可以访问数据可以操作dom</p><p style="letter-spacing:.05em;"> </p>5、Vue的模板编译原理,如何编译 template 模板?<p style="letter-spacing:.05em;">vue模板的编译过程分为3个阶段:</p><p style="letter-spacing:.05em;"> 第一步是将 模板字符串 转换成 element ASTs(解析器) 解析将模板字符串解析生成AST,生成的AST元素节点总共有3种类型,1为普通元素,2为表达式,3为纯文本</p><p style="letter-spacing:.05em;">第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器) vue模板中井不是所有数据都是响应式的,有很多数据是首次染后就永远不会变化的,那么这部分数据生成的DOM也不会变化,我们可以在 patch的过程跳过对他们的比对 此阶段会深度遍历生成的AST树,检测它的每一颗子树是不是静态节点,如果是静态节点则它们生成DOM永远不需要改变,这对运行时对模板的更新起到极大的优化作用。</p><p style="letter-spacing:.05em;">第三步是使用 element ASTs 生成 render 函数代码字符串(代码生成器) 生成代码:const code = generate(ast, options );通过 generate 方法,将 ast 生成 render 函数</p><p style="letter-spacing:.05em;"> </p>6、批量异步更新策略、nextTick 原理及 vue.nextTick 有什么作用?<p style="letter-spacing:.05em;">(1)批量异步策略 Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。</p><p style="letter-spacing:.05em;">(2)nextTick 在下次DOM更新循环结束后执行延迟回调,在修改数据之后立即使用 nextTick 来获取更新后的DOM。 数据更新是一个异步操作异步 dom,更新后使用 vue.nextTick 可以立即得到更新后的数据</p><p style="letter-spacing:.05em;">nextTick 对于 microtask 的实现,会先检测是否支持 Promise,不支持的话,直接指向 macrotask,而 macrotask的实现,优先检测是否支持 setTinmediat。(高版本IE和 Etage支持),不支持的再去检测是否支持 MessageChannel,如果仍不支持,最终降级为 setTimeout 0;默认的情况,会先以 microtask 方式执行,因为 microtask 可以在一次 tick 中全部执行完毕,在一些有重绘和动画的场景有更好的性能。</p><p style="letter-spacing:.05em;">但是由于 microtask 优先级较高,在某些情况下,可能会在事件冒泡过程中触发,导致一些问题,所以有些地方会强制使用 macrotask(如v-on)。</p><p style="letter-spacing:.05em;"> 注意:之所以将 nextTick 的回调函数放入到数组中一次性执行,而不是直接在 nextTick 中执行回调函数,是为了保证在同一个 tick 内多次执行了 nextTick,不会开启多个异步任务,而是把这些异步任务都压成一个同步任务,在下一个tick内执行完毕。</p><p style="letter-spacing:.05em;"> </p>7、数据渲染有几种方式,有什么区别?v-html 会导致什么问题<p style="letter-spacing:.05em;">插值表达式:{{}} 只会替换自己的这个占位符,不会把整个元素的内容清空</p><p style="letter-spacing:.05em;">v-html:只有v-html可以渲染HTML代码,会覆盖元素中原本的内容(相当于原生js中的innerHTML) 在网站上动态渲染任意HTML,很容易导致XSS攻击。所以只能在可信内容上使用v-html,且永远不能用于用户提交的内容上。</p><p style="letter-spacing:.05em;">v-text:完整地输出内容而不会转换标签</p><p style="letter-spacing:.05em;">闪烁:使用插值表达式 {{}},会造成界面闪烁。</p><p style="letter-spacing:.05em;">解决方式:</p><p style="letter-spacing:.05em;">使用 v-text</p><p style="letter-spacing:.05em;">使用 v-cloak 指令,v-cloak 指令和 css 规则如 [v-cloak]{display:none} 一起用</p>8、v-if 和 v-show 有什么区别,切换时组件触发哪些什么周期钩子函数?适用于哪些场景?<p style="letter-spacing:.05em;"><strong>区别:</strong></p><p style="letter-spacing:.05em;"> v-if 控制的是 dom 的销毁和创建</p><p style="letter-spacing:.05em;">v-show 只是控制 dom 的css中 display属性</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>触发的生命周期:</strong></p><p style="letter-spacing:.05em;"> v-if 显示、创建、挂载、隐藏和销毁</p><p style="letter-spacing:.05em;"> v-show 显示隐藏不触发生命周期钩子函数</p><p style="letter-spacing:.05em;">使用场景:</p><p style="letter-spacing:.05em;"> v-if 切换的开销更大,而 v-show 初始化渲染开销更大,在需要频繁切换或者切换的部分 dom 很复杂时,使用 v-show 更合适;渲染后很少切换的则使用 v-if 更合适。</p><p style="letter-spacing:.05em;"> </p>9、v-if 和 v-for 为什么不建议混合使用?<p style="letter-spacing:.05em;">原因:被渲染的 dom 会重复一个创建销毁的过程</p><p style="letter-spacing:.05em;">解决方法:</p><p style="letter-spacing:.05em;">使用计算属性 过滤数据</p><p style="letter-spacing:.05em;"> computed:{ showList:function(){ return this.list.filter(var,index)=>{ return var.isshow } } }</p><p style="letter-spacing:.05em;">当 v-for 和 v-if 处于同一个节点时,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中,如果要遍历的数组很大,而真正要展示的数据很少时,这将造成很大的性能浪费。这种场景建议使用 computed,先对数据进行过滤。</p><p style="letter-spacing:.05em;"> </p>10、key 主要是解决哪一类的问题(作用),为什么不建议用索引 index(重绘)<p style="letter-spacing:.05em;">(1)key 的作用主要是为了高效的更新虚拟 DOM</p><p style="letter-spacing:.05em;">(2)当以 index 为 key 值时,如果数组长度发生变化,会导致 key 的变化,比如删除其中某一项,那么 index 会相应变化。 所以用 index作为key和不加index没有什么区别,都不能提升性能。一般用每项数据的唯一值来作为key,就算数组长度变化,也不会影响到这个key</p><p style="letter-spacing:.05em;"> </p>11、v-on 可以监听多个方法吗?怎么实现?<p style="letter-spacing:.05em;">可以一次性绑定多个事件,写在对象中即可。</p><p style="letter-spacing:.05em;">实现:</p><p style="letter-spacing:.05em;"><button v-on="{mouseenter:onEnter, mouseleave:onLeave">鼠标进来1</button></p><p style="letter-spacing:.05em;"> <button @mouseenter="onEnter", @mouseleave="onLeave">鼠标进来2</button></p><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"> 一个事件绑定多个函数,按顺序执行,这里的分隔函数可以用逗号也可以用分号</p><p style="letter-spacing:.05em;"> <button @click="a(), b()">点我ab</button></p><p style="letter-spacing:.05em;"> <button @click="one()">点我one</button></p><p style="letter-spacing:.05em;"> </p>12、vue 实现双向数据绑定的原理是什么?你用过哪些 v-model 修饰符?<p style="letter-spacing:.05em;">当一个vue实例创建后vue会遍历data选项的属性,用object.definproperty将它转化为getter或者setter,并且内部追踪相关依赖,在属性访问和修改时通知变化每一个组件实例化都有相应的watcher程序实例,他会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时会通知watcher重新计算,从而使得它相关的组件的以更新</p><p style="letter-spacing:.05em;"><strong>Vue实现数据双向绑定的原理:Object.defineProperty()</strong></p><p style="letter-spacing:.05em;">vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。</p><p style="letter-spacing:.05em;">vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>修饰符:</strong></p><p style="letter-spacing:.05em;"> .lazy文本框失去焦点后在更新数据 </p><p style="letter-spacing:.05em;">.trim清除前后空格的 </p><p style="letter-spacing:.05em;">.number从字符中获取数字</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>v-model 是如何实现双向绑定的? </strong></p><p style="letter-spacing:.05em;">vue2.0:v-model是用来在表单控件或者组件上创建双向绑定的,他的本质是v-bind和v-on的语法糖,在个组件上使用v-mode1,默认会为组件绑定名为 value的prop和名为 input的事件。 </p><p style="letter-spacing:.05em;"> Vue3.0:在3X中,自定义组件上的v-mode1相当于传递了 modelValueprop并接收抛出的update: modelValue事件 </p><p style="letter-spacing:.05em;"> </p>13、计算属性和实例方法有什么区别、computed 和 watch 有什么区别? 什么是 vue 的计算属性,computed 是如何实现的?vue 怎么监听数据的变化,怎么监听一个对象属性的变化?<p style="letter-spacing:.05em;"><strong>计算属性和实例方法有什么区别</strong>(computed,methods )</p><p style="letter-spacing:.05em;">实例方法指的是对象能调用的函数,对象里所有可以调用的函数全叫实例方法。</p><p style="letter-spacing:.05em;">答:计算属性有缓存,实例方法没有缓存 计算属性调用时 total 不可以传参 实例方法调用时 total()可以传参</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>computed 和 watch 的区别:</strong></p><p style="letter-spacing:.05em;"><strong>computed</strong> 1、computed是计算属性,也就是依赖某个值或者props通过计算得来得数据; 2、 computed的值是在getter执行之后进行缓存的,只有在它依赖的数据发生变化,会重新调用getter来计算; 3、 不支持异步,当computed内有异步操作时无效,无法监听数据的变化; </p><p style="letter-spacing:.05em;"><strong>watch</strong> 1、watch是监听器,可以监听某一个数据,然后执行相应的操作; 2、不支持缓存,数据变直接会触发相应的操作; 3、监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值; 4、支持异步操作;</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>什么时候用computed 什么时候用watch 比较合适?</strong></p><p style="letter-spacing:.05em;">当多个属性影响一个属性的时候,建议用computed(computed适合在模板渲染中,某个值是依赖了其他的响应式对象甚至是计算属性计算而来)</p><p style="letter-spacing:.05em;">当一个值发生变化之后,会引起一系列的操作,这种情况就适合用watch(watch适合监听某个值的变化去完成一段复杂的业务逻辑)</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>vue 的计算属性:</strong></p><p style="letter-spacing:.05em;">在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。 </p><p style="letter-spacing:.05em;">好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>computed 的实现:</strong> </p><p style="letter-spacing:.05em;">流程总结如下: </p><p style="letter-spacing:.05em;">1、当组件初始化的时候, computed和data会分别建立各自的响应系统, Observer遍历data中每个属性设置get/set数据拦截 </p><p style="letter-spacing:.05em;">2、初始化 computed会调用 initComputed 函数 </p><p style="letter-spacing:.05em;">2.1、注册一个 watcher实例,并在内实例化一个Dep消息订阅器用作后续收集依赖(比如渲染函数的 watcher或者其他观察该计算属性变化的watcher) 2.2、调用计算属性时会触发其 Object.defimeProperty的get访问器函数 </p><p style="letter-spacing:.05em;">2.3、调用 watcher.depend()方法向自身的消息订间器dep的subs中添加其他属性的watcher </p><p style="letter-spacing:.05em;">2.4、调用 watcher的 evaluate方法(进而调用 watcher的get方法)让自身成为其他watcher的消息订阅器的订阅者,首先将watcher赋给dep.target,然后执行 getter求值函数,当访问求值函数里面的属性(比如来自data、prope或其他 computed)时,会同样触发它们的get访问器函数从而将该计算属性的 watcher添加到求值函数中属性的watcher的消息订阅器dep中,当这些操作完成,最后关闭dep.target赋为 null 并返回求值函数结果 </p><p style="letter-spacing:.05em;">3、当某个属性发生变化,触发set拦截函数,然后调用自身消息订阅器dep的 notify方法,遍历当前dep中保存着所有订阅者 wather的subs数组,并逐个调用 watcher的 update方法,完成响应更新</p><p style="letter-spacing:.05em;"><strong>vue 怎么监听数据的变化,怎么监听一个对象属性的变化</strong> </p><p style="letter-spacing:.05em;">用 watch 监听数据的变化 监听对象属性,先在 computed 中声明中间件: computed:{ newage:function(){ return this.person.age } } watch:{ num:function(newdata,olddata){ console.log(newdata,olddata) }, newage:function(){ console.log("生日快乐!") } } </p> 14、vue 的父组件和子组件生命周期钩子执行顺序是什么?<p style="letter-spacing:.05em;"><strong>渲染过程</strong>:</p><p style="letter-spacing:.05em;"> 父组件挂载完成一定是等子组件都挂载完成后,才算是父组件挂载完,所以父组件的 mounted在子组件 mouted之后 </p><p style="letter-spacing:.05em;">父beforeCreate → 父created → 父beforeMount → 子beforeCreate → 子created →子 beforeMount →子mounted->父 mounted</p><p style="letter-spacing:.05em;"><strong>子组件更新过程:</strong></p><p style="letter-spacing:.05em;"> 1.影响到父组件:父 beforeUpdate→>子 beforeUpdate->子 updated->父 updated </p><p style="letter-spacing:.05em;">2.不影响父组件:子 beforeUpdate>子 updated</p><p style="letter-spacing:.05em;"><strong>父组件更新过程:</strong></p><p style="letter-spacing:.05em;"> 1.影响到子组件:父 beforeUpdate→>子 beforeUpdate->子 updated->父 updated </p><p style="letter-spacing:.05em;">2.不影响子组件:父 beforeUpdate→>父 updated</p><p style="letter-spacing:.05em;"><strong>销毁过程:</strong></p><p style="letter-spacing:.05em;">父 beforeDestroy → 子 beforeDestroy → 子 destroyed → 父 destroyed</p><p style="letter-spacing:.05em;">不管是哪种情况,都一定是父组件等待子组件完成后,才会执行自己对应完成的钩子。</p><p style="letter-spacing:.05em;"> </p>15、Vue2.0 组件通信方式有哪些? vue 父子组件怎样实现通讯?vue 组件的参数传递,vue 中子组件调用父组件的方法?vue 中怎么实现组件之间的嵌套?<p style="letter-spacing:.05em;">1、父子组件通信</p><p style="letter-spacing:.05em;"> props 和 event、v-model、.sync、ref、\)parent 和 \(children、\)emit
2、 非父子组件
\(attr 和 \)listeners 、provide 和 inject、eventBus、通过实例 \(root 访问、vuex、dispath 和 brodcast</p><p style="letter-spacing:.05em;"><strong>实现通讯:</strong></p><p style="letter-spacing:.05em;"> 父传子:父组件:<mydiv:list='list'> </mydiv> 子组件:props[‘list’] </p><p style="letter-spacing:.05em;">子传父:子组件:this.\)emit(‘子组件事件名’,参数) 父组件:<mydiv @子组件事件名=‘父组件事件名’>
参数传递:
1、父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件:\(emit方法传递参数 </p><p style="letter-spacing:.05em;">2、非父子组件间的数据传递,兄弟组件传值 eventBus,</p><p style="letter-spacing:.05em;">就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。兄弟组件可以父传子 子传父;Vuex也可以实现数据共享 项目比较小时,用这个比较合适。(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道。)</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>子组件调父组件的方法:</strong> </p><p style="letter-spacing:.05em;">第一种方法是直接在子组件中通过 this.\)parent.event 来调用父组件的方法
第二种方法是在子组件里用 \(emit 向父组件触发一个事件,父组件监听这个事件。 </p><p style="letter-spacing:.05em;">第三种是父组件把方法传入子组件中,在子组件里直接调用这个方法</p><p style="letter-spacing:.05em;"> </p>16、怎样使用 props 限定传递的数据,有哪些属性?非 props 属性有什么特点?如何解决 props 层级过深的问题?<p style="letter-spacing:.05em;"><strong>props 限定传递的数据</strong></p><p style="letter-spacing:.05em;">type //限定传递的数据类型</p><p style="letter-spacing:.05em;"> Required:true false //是否必传</p><p style="letter-spacing:.05em;"> Default:false //指定默认值 </p><p style="letter-spacing:.05em;">Validator:function(){ //自定义规则 }</p><p style="letter-spacing:.05em;"><strong>非 props 属性的特点:</strong> </p><p style="letter-spacing:.05em;">①会显示在解析之后的标签上 ②子组件不能使用该属性</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>解决props层级过深:</strong> </p><p style="letter-spacing:.05em;">(1)使用vuex </p><p style="letter-spacing:.05em;">(2)传递数据,使用以下接收(均不含被props接收的数据) this.\)attrs 接收属性 this.\(listeners 接收事件(不含被 .native 修饰符的事件)</p><p style="letter-spacing:.05em;"><strong>组件之间的嵌套:</strong>组件之间的嵌套使用,可以借助插槽,让插槽接受子组件中的内容</p><p style="letter-spacing:.05em;"> </p>17、如果子组件直接修改父组件的值会发生什么?怎么解决,要修改多个数据怎么办?解释 VUE 中单向数据流的概念?<p style="letter-spacing:.05em;">如果修改的不是引用类型的值时会报错,告诉我们不能直接修改父组件的值。</p><p style="letter-spacing:.05em;"> (1)可以使用.sync修饰符来修改值,对一个 prop 进行“双向绑定”。(注意.sync 修饰符的 v-bind 不能和表达式一起使用)</p><p style="letter-spacing:.05em;"> (2)父组件将改变值的方法传递给子组件</p><p style="letter-spacing:.05em;"><strong>单向数据流的概念:</strong> 子组件不可以直接修改父组件传过来的参数,如果直接修改会报错,只能声明成自己的才可以修改</p><p style="letter-spacing:.05em;"> </p>18、怎样声明全局组件,怎样使用全局组件?怎样声明局部组件,怎样使用局部组件?<p style="letter-spacing:.05em;"><strong>声明全局组件:</strong> vue.component(‘myheader’,{ Template:<div>全局组件</div> })</p><p style="letter-spacing:.05em;"><strong>使用全局组件:</strong> <myheader></myheader></p><p style="letter-spacing:.05em;"><strong>声明局部:</strong> 声明成 *.vue文件中模板在中。</p><p style="letter-spacing:.05em;"><strong>使用局部组件:</strong></p><p style="letter-spacing:.05em;"> Js模块化导出 <script></script></p><p style="letter-spacing:.05em;">css定义 <style scoped></style> </p><p style="letter-spacing:.05em;"> import 引入,注册 components 调用</p> 19、多个组件之间如何拆分各自的 state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块?<p style="letter-spacing:.05em;">(1)公共的数据部分可以提升至和他们最近的父组件,由父组件派发 </p><p style="letter-spacing:.05em;">(2)公共数据可以放到vuex中统一管理,各组件分别获取</p><p style="letter-spacing:.05em;"> </p>20、vue 中如何编写可复用的组件?<p style="letter-spacing:.05em;">(1)以组件功能命名 </p><p style="letter-spacing:.05em;">(2)只负责ui的展示和交互动画,不要在组件里与服务器打交道(获取异步数据等) </p><p style="letter-spacing:.05em;">(3)可复用组件不会因组件使用的位置、场景而变化。尽量减少对外部条件的依赖。</p><p style="letter-spacing:.05em;"> </p>21、vue 组件中的 data 为什么必须是一个函数?vue中组件 data 为什么是 return ー个对象的函数,而不是直接是个对象?<p style="letter-spacing:.05em;"><strong>函数:</strong></p><p style="letter-spacing:.05em;">对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。</p><p style="letter-spacing:.05em;"><strong>对象:</strong> </p><p style="letter-spacing:.05em;">当data定义为对象后,这就表示所有的组件实例共用了一份data数据,因此,无论在哪个组件实例中修改了data,都会影响到所有的组件实例。组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据;而单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果。</p><p style="letter-spacing:.05em;"> </p>22、什么是插槽,怎么使用,什么是具名插槽,如何使用?什么是作用域插槽?<p style="letter-spacing:.05em;"><strong>插槽</strong>,也就是slot,是组件的一块 HTML 模板,这块模板显示不显示、以及怎样显示由父组件来决定。</p><p style="letter-spacing:.05em;"> 由于插槽是一块模板,所以,对于任何一个组件,从模板种类的角度来分,其实都可以分为非插槽模板和插槽模板两大类。 非插槽模板指的是 html 模板,比如‘div、span、ul、table’这些;非插槽模板的显示与隐藏以及怎样显示由组件自身控制;插槽模板是 slot,它是一个空壳子,因为它的显示与隐藏以及最后用什么样的html模板显示由父组件控制;但是插槽显示的位置却由子组件自身决定,slot 写在组件 template 的什么位置,父组件传过来的模板将来就显示在什么位置。</p><p style="letter-spacing:.05em;"><strong>目的:</strong>内容不确定,以后谁来调用记得填</p><p style="letter-spacing:.05em;"><strong>设计思路:</strong>子组件定义插槽,父组件提供内容去填补插槽</p><p style="letter-spacing:.05em;"><strong>单个插槽 | 默认插槽 | 匿名插槽</strong> </p><p style="letter-spacing:.05em;">单个插槽是 vue 的官方叫法,但是其实也可以叫它默认插槽,或者与具名插槽相对,我们可以叫它匿名插槽。因为它不用设置name属性。</p><p style="letter-spacing:.05em;"> 单个插槽可以放置在组件的任意位置,但是就像它的名字一样,一个组件中只能有一个该类插槽。相对应的,具名插槽就可以有很多个,只要名字(name属性)不同就可以了。</p><p style="letter-spacing:.05em;"><strong>使用:</strong> </p><p style="letter-spacing:.05em;">父组件:在 <template></template> 里面任意写入 HTML 代码 </p><p style="letter-spacing:.05em;">子组件:在需要展示的位置放置 即可展示</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>具名插槽</strong> </p><p style="letter-spacing:.05em;">匿名插槽没有 name 属性,所以是匿名插槽,那么,插槽加了 name 属性,就变成了具名插槽。 </p><p style="letter-spacing:.05em;">具名插槽可以在一个组件中出现 N 次,出现在不同的位置。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>作用域插槽 | 带数据的插槽</strong> </p><p style="letter-spacing:.05em;">官方叫它作用域插槽,实际上,对比前面两种插槽,我们可以叫它带数据的插槽。什么意思呢,就是前面两种,都是在组件的template里面写;但是作用域插槽要求,在slot上面绑定数据。 插槽获取子组件的数据 需要属性传递 结合作用域插槽语法,代码如下 设置:Slot-scope=‘自定义名字’ 使用: 自定义名字 {{scope}} </p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>作用域插槽跟单个插槽和具名插槽的区别:</strong> </p><p style="letter-spacing:.05em;">因为单个插槽和具名插槽不绑定数据,所以父组件提供的模板一般要既包括样式又包括内容,而作用域插槽,父组件只需要提供一套样式(在确实用作用域插槽绑定的数据的前提下)。</p><p style="letter-spacing:.05em;"> </p>23、对 keep-alive 的了解?keep-alive 组件有什么作用?keep-alive 组件有哪些属性?<p style="letter-spacing:.05em;">理解:每次切换界面组件都会重新初始化,离开页面就会集体销毁;keep-alive是用来保活,相当于缓存,即使你离开页面,组件也不销毁</p><p style="letter-spacing:.05em;">keep-alive本身注册了全局,而且不参与离开销毁等生命周期,组件写在他的里面,自然不受外界影响;正常切换组件的时候,都会通知子组件,生命周期结束了,然后每个组件都冒泡调用销毁;而keep-alive组件直接就不执行销毁,也不通知子组件销毁,下次进入组件还可以组件复用</p><p style="letter-spacing:.05em;">keep-alive是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。</p><p style="letter-spacing:.05em;">在vue 2.1.0 版本之后,keep-alive新加入了两个属性: include(包含的组件缓存) 与 exclude(排除的组件不缓存,优先级大于include) 。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>使用方法</strong>: </p><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"><br /></p><div></div><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>参数解释:</strong></p><p style="letter-spacing:.05em;"> include - 字符串或正则表达式,只有名称匹配的组件会被缓存</p><p style="letter-spacing:.05em;"> exclude - 字符串或正则表达式,任何名称匹配的组件都不会被缓存 include 和 exclude 的属性允许组件有条件地缓存。二者都可以用“,”分隔字符串、正则表达式、数组。当使用正则或者是数组时,要记得使用 v-bind 。</p><p style="letter-spacing:.05em;">作用:缓存组件缓存页面(router-view)</p><p style="letter-spacing:.05em;">属性:include 声明需要被缓存的组件页面 exclude 声明不需要被缓存的组件页面</p><p style="letter-spacing:.05em;">使用场景:商品分类页面(每次进入会发ajax,这根本没有必要,直接保活keep-alive就相当于缓存,保持活着的状态,避免反复的销毁创建)等等</p><p style="letter-spacing:.05em;"> </p>24、如何自定义事件?你知道哪些事件修饰符?什么是 vue 全局事件解绑?<p style="letter-spacing:.05em;"><strong>自定义事件:</strong></p><p style="letter-spacing:.05em;">每个Vue创建的实例都会出现一个事件接口:var vm = new Vue({el: '#app'})</p><p style="letter-spacing:.05em;">自定义事件的定义(发布):vm.\)on(自定义事件的名称,自定义事件的事件处理程序) vm.\(on( 'aa', function () {console.log( 'aa' )})</p><p style="letter-spacing:.05em;">自定义事件的触发 ( 订阅 ):vm.\)emit( 自定义事件的名称,自定义事件处理程序需要的参数1,参数2,参数3) vm.\(emit( 'aa' )</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>事件修饰符:</strong></p><p style="letter-spacing:.05em;">.stop 阻止事件冒泡 .once 只执行一次,一次性事件 .self 阻止事件冒泡和事件捕获</p><p style="letter-spacing:.05em;">.captrue 事件捕获阶段触发 .prevent 阻止浏览器默认行为 .native 触发原生事件</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>vue 全局事件解绑:</strong></p><p style="letter-spacing:.05em;">在vue中,写在 methods 里面的方法,在页面切换时一般就自动销毁了,但是写在 window 上的事件,需要我们手动解绑,这也是为了提高代码执行效率,使用生命周期函数 destroy,在页面离开时执行解绑。</p><p style="letter-spacing:.05em;">(例子看文件)</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"> </p>25、vue中常用的指令有哪些?vue 中如何自定义指令(全局和局部)?自定义指令接受哪些生命钩子函数?<p style="letter-spacing:.05em;"><strong>vue中常用的指令:</strong></p><p style="letter-spacing:.05em;">V-text:主要用来更新textContent,可以等同于JS的text属性</p><p style="letter-spacing:.05em;">V-html:双大括号的方式会将数据解释为纯文本,而非HTML。为了输出真正的HTML,可以用v-html指令。它等同于JS的innerHtml属性。</p><p style="letter-spacing:.05em;">V-show:用于根据条件展示元素。</p><p style="letter-spacing:.05em;"><strong>V-if:</strong>可以实现条件渲染,Vue会根据表达式的值的真假条件来渲染元素。 V-else-if:充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。</p><p style="letter-spacing:.05em;">V-else:是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。</p><p style="letter-spacing:.05em;"><strong>V-on</strong>:主要用来监听dom事件,以便执行一些代码块。表达式可以是一个方法名。</p><p style="letter-spacing:.05em;"><strong>V-bind</strong>:用来动态的绑定一个或者多个特性。没有参数时,可以绑定到一个包含键值对的对象。常用于动态绑定class和style。以及href等。</p><p style="letter-spacing:.05em;"><strong>v-for:</strong>用v-for指令根据遍历数组来进行渲染</p><p style="letter-spacing:.05em;"><strong>V-model:</strong>这个指令用于在表单上创建双向数据绑定</p><p style="letter-spacing:.05em;">V-slot</p><p style="letter-spacing:.05em;">V-pre:主要用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签。跳过大量没有指令的节点加快编译。</p><p style="letter-spacing:.05em;">V-cloak:这个指令是用来保持在元素上直到关联实例结束时进行编译。</p><p style="letter-spacing:.05em;">V-once:v-once关联的实例,只会渲染一次。之后的重新渲染,实例极其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。</p><p style="letter-spacing:.05em;"><strong> </strong></p><p style="letter-spacing:.05em;"><strong>自定义全局指令:</strong></p><p style="letter-spacing:.05em;">Vue.directive('color', function(obj,arg){ //obj,第一个参数,指令调用位置的 dom 对象 //arg,指令对象,和指令相关的信息 obj.style.backgroundColor=arg.value })</p><p style="letter-spacing:.05em;"><strong>自定义局部指令:</strong></p><p style="letter-spacing:.05em;">directive: { color: function(obj,arg){ //obj,第一个参数,指令调用位置的 dom 对象 //arg,指令对象,和指令相关的信息 obj.style.backgroundColor=arg.value } }</p><p style="letter-spacing:.05em;"><strong>生命钩子函数:</strong></p><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"><br /></p><div></div><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"> </p>26、如何声明一个过滤器(全局和局部)?你常用的自定义过滤器有哪些?<p style="letter-spacing:.05em;">过滤器:用于一些常见的文本格式化。</p><p style="letter-spacing:.05em;"><strong>全局过滤器:</strong></p><p style="letter-spacing:.05em;"> vue.filter(‘gettime’,function(date){ </p><p style="letter-spacing:.05em;">Var time=new date(date) </p><p style="letter-spacing:.05em;">return time.getFullyear()+’/’+time.getMonth()+1’/’+getDate() }</p><p style="letter-spacing:.05em;">)</p><p style="letter-spacing:.05em;"><strong>局部过滤器:</strong></p><p style="letter-spacing:.05em;"> Filters:{ Gettime(date){</p><p style="letter-spacing:.05em;"> Var time=new date(date) Return time.getFullyear()+’/’+time.getMonth()+1’/’+getDate() }</p><p style="letter-spacing:.05em;"> }</p><p style="letter-spacing:.05em;"><strong>常用的自定义过滤器:</strong></p><p style="letter-spacing:.05em;">(1) 去除空格、(2)时间转换、(3)大小写转换、(4)字符串替换、</p><p style="letter-spacing:.05em;">(5)金额字符转金额/数字转金额字符、(6)保留两位小数、(7)判断字符串长度并省略</p><p style="letter-spacing:.05em;">根据自己常用的来说。</p> 27、完整的 vue-router 导航解析流程<p style="letter-spacing:.05em;">(1)导航被触发。</p><p style="letter-spacing:.05em;">(2)在失活的组件里调用离开守卫。</p><p style="letter-spacing:.05em;">(3)调用全局的 beforeEach 守卫。</p><p style="letter-spacing:.05em;">(4)在重用的组件里调用 beforeRouteUpdate 守卫</p><p style="letter-spacing:.05em;">(5)在路由配置里调用 beforeEnter。</p><p style="letter-spacing:.05em;">(6)解析异步路由组件。</p><p style="letter-spacing:.05em;">(7)在被激活的组件里调用 beforeRouteEnter。</p><p style="letter-spacing:.05em;">(8)调用全局的 beforeResolve 守卫</p><p style="letter-spacing:.05em;">(9)导航被确认。</p><p style="letter-spacing:.05em;">(10)调用全局的 afterEach 钩子。</p><p style="letter-spacing:.05em;">(11)触发 DOM 更新。</p><p style="letter-spacing:.05em;">(12)用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。</p><p style="letter-spacing:.05em;"> </p>28、vue 路由的钩子函数<p style="letter-spacing:.05em;">vue-router一共给我们提供了三大类钩子函数来实现路由守卫:</p><p style="letter-spacing:.05em;"> 1、全局钩子函数(beforeEach、afterEach)</p><p style="letter-spacing:.05em;"> 2、路由独享的钩子函数(beforeEnter)</p><p style="letter-spacing:.05em;"> 3、组件内钩子函数(beforeRouterEnter、beforeRouterUpdate、beforeRouterLeave)</p><p style="letter-spacing:.05em;"> </p>29、vue-router路由的两种模式?如何实现?有什么区别?如何定义 vue-router 的动态路由? 怎么获取传过来的值?<p style="letter-spacing:.05em;">vue-router中<strong>默认使用的是hash模式</strong></p><p style="letter-spacing:.05em;"><strong>(1)hash模式</strong></p><p style="letter-spacing:.05em;"> http://localhost:8080/#/pageA hash 的值为 #/pageA</p><p style="letter-spacing:.05em;"> 在浏览器中符号“#”,# 以及 # 后面的字符称之为hash,用window.location.hash读取。</p><p style="letter-spacing:.05em;"> 改变hash,浏览器本身不会有任何请求服务器动作的,但是页面状态和url已经关联起来了。</p><p style="letter-spacing:.05em;">后面hash值的变化,不会导致浏览器向服务器发出请求,浏览器不发出请求,就不会刷新页面;同时通过监听 hashchange事件可以知道hash发生了哪些变化,然后根据hash变化来实现更新页面部分内容的操作。</p><p style="letter-spacing:.05em;"><strong>特点:</strong></p><p style="letter-spacing:.05em;">hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。</p><p style="letter-spacing:.05em;">hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>(2)history模式</strong></p><p style="letter-spacing:.05em;"> http://localhost:8080/ 正常的路径,并没有#</p><p style="letter-spacing:.05em;">history模式的实现,主要是HTML5标准发布的两个API, pushState和replaceState,这两个API可以改变url,但是不会发送请求。这样就可以监听url变化来实现更新页面部分内容的操作。</p><p style="letter-spacing:.05em;"> history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。</p><p style="letter-spacing:.05em;"> history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如:http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>区别:</strong></p><p style="letter-spacing:.05em;">(1 )在 url 显示: hash 有 # ; history 无 # 对 seo 比较友好</p><p style="letter-spacing:.05em;">(2)刷新页面时: hash 可以加载到hash值对应页面; history 没有处理的话,会返回404,一般需要后端将所有页面都配置重定向到首页路由</p><p style="letter-spacing:.05em;">(3 )兼容性: hash 支持低版本浏览器和IE浏览器 ; history (HTML5新推出的API)不支持ie低版本</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>定义:</strong>在 router 目录下的 index.js 文件中,对 path 属性加上 /,后面是跳转的地址</p><p style="letter-spacing:.05em;"><strong>获取传过来的值:</strong>在 router 目录下的 index.js 文件中,对 path 属性加上 /:id,使用 router 对象的 params.id 获取。</p><p style="letter-spacing:.05em;"> </p>30、路由显示区域和路由跳转分别是哪个组件?\)route 和 \(router 有什么区别? 路由懒加载怎么实现,有什么意义?<p style="letter-spacing:.05em;">显示:router-view 跳转 router-link</p><p style="letter-spacing:.05em;"><strong> </strong></p><p style="letter-spacing:.05em;"><strong>\)route 和 \(router 的区别:</strong></p><p style="letter-spacing:.05em;">\)route是路由信息对象”,包括path, params, hash, query, matched, name 等路由信息参数。
\(router是“路由实例"对象包括了路由的跳转方法,钩子函数等</p><p style="letter-spacing:.05em;"><strong> </strong></p><p style="letter-spacing:.05em;"><strong>路由懒加载的实现:</strong>let Addclass = resolve =>require([' @/views/ Addclass' ] ,resolve )</p><p style="letter-spacing:.05em;"> <strong>路由懒加载的意义:</strong>为给客户更好的客户体验,首屏组件加载速度更快一些,解决白屏问题。</p><p style="letter-spacing:.05em;"> </p>31、vue-router的几种实例方法以及参数传递?<p style="letter-spacing:.05em;"><strong>vue-router传递参数分为两大类:</strong></p><p style="letter-spacing:.05em;">(1)编程式的导航 router.push</p><p style="letter-spacing:.05em;">(2)声明式的导航 <router-link></router-link></p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>传递参数的方式:</strong></p><p style="letter-spacing:.05em;">编程式导航传递参数有两种类型:字符串、对象。</p><p style="letter-spacing:.05em;">声明式的导航和编程式的导航传递参数的方式一样</p><p style="letter-spacing:.05em;">路由传递参数和传统传递参数是一样的,命名路由类似表单提交而查询就是url传递,(在vue项目中基本上掌握了这两种传递参数就能应付大部分应用了)</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>总结:</strong></p><p style="letter-spacing:.05em;"> 1.命名路由搭配params,刷新页面参数会丢失</p><p style="letter-spacing:.05em;">2.查询参数搭配query,刷新页面数据不会丢失</p><p style="letter-spacing:.05em;"> 3.接受参数使用this.\)router后面就是搭配路由的名称就能获取到参数的值
32、router的meta有什么用?怎样给路由添加 active-class?
meta 的作用:在meta对象中可以设置一些状态,通常设置标题或是否需要缓存。
路由添加 active-class: 配置文件中linkActiveClass 默认的是router- link- active 可以直接在标签中使用active-class
33、vue2.x 的响应式原理?vue3.x响应式原理?
vue2.x 的响应式原理:
vue的响应式是通过 Object.defineProperty 对数据进行动持,并结合观察者模式实现。 vue 利用 object.detineProperty 创建一个 observe 来劫持监听所有的属性,把这些属性全部转为 getter 和 setter。Vue 中每个组件实例都会对应一个 watcher 实例,它会在组件渲染的过程中把使用过的数据属性通过 getter 收集为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。
Object.defineProperty有哪些缺点?(无法检测到对象属性的新增或删除)
1、Object.defineProperty只能劫持对象的属性,而 Proxy 是直接代理对象 由于 Object.defineProperty只能对属性进行劫持,需要遍历对象的每个属性,而 Proxy可以直接代理对象。
2、Object.defineProperty 对新增属性需要手动进行 observe,由于Object.defineProperty劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持,也正是因为这个原因,使用 vue 给 data 中的数组或对象新增属性时,需要使用vm.\(set才能保证新增的属性也是响应式的</p><p style="letter-spacing:.05em;">3、Proxy支持13种拦截操作,这是 defineProperty 所不具有的。</p><p style="letter-spacing:.05em;"> 4、新标准性能红利 Proxy 作为新标准,长远来看,JS引擎会继续优化 Proxy,但 getter 和 setter 基本不会再有针对性优化 5、Proxy 兼容性差目前并没有一个完整支持 Proxy 所有拦截方法的 Polyfill 方案</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>vue3.x响应式原理:</strong></p><p style="letter-spacing:.05em;"> vue3.x改用 Proxy 替代 object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达13种拦截方法。井且作为新标准将受到浏览器厂商重点持续的性能优化。</p><p style="letter-spacing:.05em;">Poxy只会代理对象的第一层,那么vue3又是怎样处理这个问题的呢?</p><p style="letter-spacing:.05em;"> 判断当前 Reflect.get的返回值是否为 Object,如果是则再通过 reactive 方法做代理,这样就实现了深度观测。</p><p style="letter-spacing:.05em;">监测数组的时候可能触发多次 get/set,那么如何防止触发多次呢? 我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行 trigger。</p><p style="letter-spacing:.05em;"> </p>34、vuex 是什么?什么是“状态管理模式”?vuex 有哪些核心的属性?Vuex 和单纯的全局对象有什么区别?<p style="letter-spacing:.05em;">官方:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension (opens new window),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。</p><p style="letter-spacing:.05em;"> <strong>简单的说:</strong>Vuex 是 vue 框架中状态管理。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>状态管理模式:</strong></p><p style="letter-spacing:.05em;">把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为,这就是“状态管理模式”。 应用场景有:单页应用中,组件之间的数据状态。</p><p style="letter-spacing:.05em;">应用实例:</p><p style="letter-spacing:.05em;">1、购物车功能(数据的存储);</p><p style="letter-spacing:.05em;">2、下单页面有选择优惠券按钮,点击进入优惠券页面,选择后返回到下单页,数据会绑定回来,显示已选择的优惠券;</p><p style="letter-spacing:.05em;">3、登录状态(用户信息的存储);</p><p style="letter-spacing:.05em;">4、音乐播放 等等</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"><strong>核心属性:</strong> state、mutations、getters、action 和 modules。</p><p style="letter-spacing:.05em;">state:Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。</p><p style="letter-spacing:.05em;">mutations:mutations定义的方法动态修改 Vuex 的 store 中的状态或数据。</p><p style="letter-spacing:.05em;">getters:类似 vue 的计算属性,主要用来过滤一些数据。</p><p style="letter-spacing:.05em;"> action:actions 可以理解为通过将 mutations 里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。</p><p style="letter-spacing:.05em;">modules:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;">state => 基本数据(只用来读取的状态集中放在 store 中)</p><p style="letter-spacing:.05em;">getters => 从基本数据派生的数据</p><p style="letter-spacing:.05em;">mutations => 修改数据,同步(改变状态的方式是在 mutations 中)</p><p style="letter-spacing:.05em;">actions => 修改数据,异步(异步逻辑应该封装在 action 中)</p><p style="letter-spacing:.05em;">modules => 模块化Vuex</p><p style="letter-spacing:.05em;"><strong> </strong></p><p style="letter-spacing:.05em;"><strong> </strong></p><p style="letter-spacing:.05em;"><strong>vuex和全局对象主要有两大区别:</strong></p><p style="letter-spacing:.05em;">1、vuex的状态存储是响应式的。当vue组件从 store中读取状态的时候,若 store中的状态发生变化,那么相应的组件也会相应地得到高效更新。</p><p style="letter-spacing:.05em;"> 2、不能直接改变 store中的状态。改变 store中的状态的唯一途径就是显式地提交( commit)mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。</p><p style="letter-spacing:.05em;"> </p>35、vue中proxy代理?<p style="letter-spacing:.05em;">Vue 框架开发的时候,会遇到跨域的问题,可在config/index.js 里配置proxyTable内容,使用proxy代理。</p><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"><br /></p><div></div><p style="letter-spacing:.05em;"><br /></p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"> </p>36、vue中对象更改检测的注意事项<p style="letter-spacing:.05em;">由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除;</p><p style="letter-spacing:.05em;">对于已经创建的实例,Vue 不能动态添加根级别的响应式属性;但是,可以使用 Vue.set(object, key, value)方法向嵌套对象添加响应式属性; 还可以使用 vm.\)set实例方法添加,它只是全局Vue.set 的别名;
有时可能需要为已有对象赋予多个新属性,比如使用 Object.assign()或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。
37、Vue.js 全局运行机制

流程分析:
1、初始化以及挂载init, mount
2、在进行模板编译compile,将template编译为渲染函数render function
3、执行render function生成Virtual DOM, render function => VNode tree
4、再进行响应式依赖收集,render function => getter, setter => Watcher.update => patch。以及使用队列进行异步更新的策略。
5、通过diff算法后进行patch更新视图
38、vue 如何优化首屏加载速度?vue 弹窗后如何禁止滚动条滚动?
vue优化首屏加载速度:
(1)按需加载组件,不一次性加载所有组件
(2)减少打包js,如果打包后的js文件过大,会阻塞加载。
(3)关闭sourcemap,开启压缩代码 vue.config.js文件中配置:productionSourceMap: false,
(4)加个好看的loading效果
vue弹窗后禁止滚动条滚动:
39、vue 开发命令 npm run dev 输入后的执行过程
(1)npm run dev是执行配置在package.json中的脚本
(2)调用了webpack配置文件
(3)配置文件中调用了main.js
(4)main.js用到了一个html元素#app,引用路由等开始vue的模板编译
40、devDependencies 和 dependencies 的区别
(1)devDependencies:用于本地开发,打包时生产环境不会打包这些依赖。
(2)dependencies:开发环境能用,生产环境也能用。生产环境会被打包。
41、依赖版本 ~ 和 ^ 的区别
(1)~:会匹配最近的小版本依赖包,比如~1.2.3会匹配所有1.2.x版本,但是不包括1.3.0
(2)^:会匹配最新的大版本依赖包,比如^1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0
42、Vue项目性能优化编码阶段:
代码减少对服务器请求次数,减小对服务器请求代码的体积

尽量减少data中的数据,data中的数据都会增加 getter 和 setter,会收集对应的 watcher
v-if 和v-for 不能连用、在更多的情况下,使用v-if替代 v-show
如果需要使用 v-for 给每项元素绑定事件时使用事件代理,key保证唯一
SPA页面采用 keep-alive 缓存组件
使用路由懒加载、异步组件、图片懒加载、css精灵图字体图标
防抖、节流、第三方模块按需导入、长列表滚动到可视区域动态加载、全局事件解绑
SEO优化: 预渲染、服务端染SSR
打包优化: 压缩代码、使用cdn加载第三方模块、多线程打包 happypack、splitChunks抽离公共文件、sourceMap优化、Tree Shaking/Scope Hoisting
用户体验: 骨架屏、PWA、使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩
webpack
封装axios 请求超时时间, baseurl设置, 请求头设置 (token 的设置) 错误的处理 (未登录) token过期 404 (算也不算优化,这都是正常开发的功能,如果说这样可以优化结构复用也合理)
参考这篇文章: https://www.cnblogs.com/chaoyuehedy/p/9931146.html
43、vue3.0 相对于 vue2.x 有哪些变化?
监测机制的改变( Object.defineProperty-> Proxy)、模板、对象式的组件声明方式(class)、使用 ts
其它方面的更改:支持自定义渲染器、支持 Fragment(多个根节点)和 Protal(在dom其他部分渲染组建内容)组件、基于 treeshaking优化,提供了更多的内置功能
44、vue2.0 中如何检测数组变化?
Vue的 Observer对数组做了单独的处理,对数组的方法进行编译,并赋值给数组属性的 proto 属性上,因为原型链的机制,找到对应的方法就不会继续往上找了。编译方法中会对一些会增加索引的方法(push, unshift, splice)进行手动 observe。
45、插件
插件:插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制;(插件按照vue格式编写的js代码,可以通过use注册,然后使用)
一般有下面几种:
添加全局方法或者 property。如:vue-custom-element
添加全局资源:指令/过滤器/过渡等。如 vue-touch
通过全局混入来添加一些组件选项。如 vue-router
添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
怎么注册插件: (看原稿)
使用全局方法Vue.use()
Vue.use( MyPlugin )
vue 如何兼容 IE
vue本身不支持旧版本 ie ,而旧版 js 也不支持属性监听,所以 vue 不支持兼容 ie。
如果要兼容低版本,建议使用 jquery 系列技术
react 如何兼容 ie ?加上polyfill可以兼容IE8。
Vue项目中如何区分开发环境和生产环境
用webpack定义两个配置文件,分别代表开发环境和生产环境即可
区分环境的问题,就是写两个配置文件运行的时候,用不同的文件就行了
如何让 css 只在当前组件起作用? 在style标签中写入scoped即可
vue.js 的两个核心是什么? 数据驱动、组件系统
$set 方法有什么用?有什么特点?添加响应式的属性
暂时到这里,后续有的话在再继续补进去!有问题的话麻烦指出来,好让我修改!
</p><p style="letter-spacing:.05em;"> </p><p style="letter-spacing:.05em;"> </p>
讯享网

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/175862.html