=> 相同点: => 不同点: 只关心数据的流传,减少强耦合性。最关键的就是数据的双向绑定 SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。 优点: 缺点: 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。 额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。 有两种常见的试图改变一个 prop 的情形 : 运用场景: 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算; 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。 由于 JavaScript 的限制,Vue 不能检测到以下数组的变动: 为了解决第一个问题,Vue 提供了以下操作方法: 为了解决第二个问题,Vue 提供了以下操作方法: Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分: 加载渲染过程 子组件更新过程 父组件更新过程 销毁过程 可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点: 在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。vue 具体的生命周期示意图可以参见如下,理解了整个生命周期各个阶段的操作,关于生命周期相关的面试题就难不倒你了。 比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现: 以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示: 当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。 因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。 我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件: 以 input 表单元素为例: 如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示: Vue 组件间通信是面试常考的知识点之一,这题有点类似于开放题,你回答出越多方法当然越加分,表明你对 Vue 掌握的越熟练。Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信,下面我们分别介绍每种通信方式且会说明此种方法可适用于哪类组件间通信。 (1) (2) (3) (4) (5) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。 (1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 (2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。 主要包括以下几个模块: Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记”激活”为客户端上完全可交互的应用程序。 服务端渲染 SSR 的优缺点如下: (1)服务端渲染的优点: (2) 服务端渲染的缺点: vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示: 其中,3 种路由模式的说明如下: hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器; history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式; abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式. 早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’: hash 路由模式的实现主要是基于下面几个特性: HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示: history 路由模式的实现主要基于存在下面几个特性: 如果被问到 Vue 怎么实现数据双向绑定,大家肯定都会回答 通过 Object.defineProperty() 对数据进行劫持,但是 Object.defineProperty() 只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持,但是我们在使用 Vue 框架中都知道,Vue 能检测到对象和数组(部分方法的操作)的变化,那它是怎么实现的呢?我们查看相关代码如下: 通过以上 Vue 源码部分查看,我们就能知道 Vue 框架是通过遍历数组 和递归遍历对象,从而达到利用 Object.defineProperty() 也能对对象和数组(部分方法的操作)进行监听。 受现代 JavaScript 的限制 ,Vue 无法检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。但是 Vue 提供了 我们查看对应的 Vue 源码: 我们阅读以上源码可知,vm.$set 的实现原理是: 虚拟 DOM 的实现原理主要包括以下 3 部分: 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象; diff 算法 — 比较两棵虚拟 DOM 树的差异; pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。 key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速。Vue 的 diff 过程可以概括为:oldCh 和 newCh 各有两个头尾的变量 所以 Vue 中 key 的作用是:key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速 更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,源码如下: 如果没有对 Vue 项目没有进行过优化总结的同学,可以参考另一篇文章《 Vue 项目性能优化 — 实践指南 》,文章主要介绍从 3 个大方面,22 个小方面详细讲解如何进行 Vue 项目的优化。 在js中,一个模块就是实现特定功能的文件(js文件) 遵循模块的机制,想要什么就加载什么模块 模块化开发需要遵循规范 js实现模块化规范 解决的问题:1.命名冲突 2.文件依赖 3.模块的复用 4.统一规范和开发方式 Vue 3.0 正走在发布的路上,Vue 3.0 的目标是让 Vue 核心变得更小、更快、更强大,因此 Vue 3.0 增加以下这些新特性: 3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制: 只能监测属性,不能监测对象 检测属性的添加和删除; 检测数组索引和长度的变更; 支持 Map、Set、WeakMap 和 WeakSet。 新的 observer 还提供了以下特性: 模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。 同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。 vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。 此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。 vue3.0 的改变是全面的,上面只涉及到主要的 3 个方面,还有一些其他的更改: Vue使用了Mustache语法,即双大括号的语法。 模板引擎: 优点: Vue使用了Mustache语法,即双大括号的语法。 模板引擎: 优点: 第一种:挂载到Vue的prototype上。把全局方法写到一个文件里面,然后for循环挂载到Vue的prototype上,缺点是调用这个方法的时候没有提示 第二种:利用全局混入mixin,因为mixin里面的methods会和创建的每个单文件组件合并。这样做的优点是调用这个方法的时候有提示 设置assetsPublicPath将 assetsPublicPath: ‘/’ 改为 assetsPublicPath: ‘./’ 最新的vue-cli 需要在根目录下建一个vue.config.js 在里面配置publicPath即可
vue 面试题总结
1. vue和react的区别
1. 数据驱动页面,提供响应式的试图组件 2. 都有virtual DOM,组件化的开发,通过props参数进行父子之间组件传递数据,都实现了webComponents规范 3. 数据流动单向,都支持服务器的渲染SSR 4. 都有支持native的方法,react有React native, vue有wexx
1.数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的 2.数据渲染:大规模的数据渲染,react更快 3.使用场景:React配合Redux架构适合大规模多人协作复杂项目,Vue适合小快的项目 4.开发风格:react推荐做法jsx + inline style把html和css都写在js了 vue是采用webpack + vue-loader单文件组件格式,html, js, css同一个文件
2. 介绍下MVVM(数据的双向绑定
关键步骤: 1.实现数据监听器Observer,用object.defineProperty()重写数据的get/set。 值更新就在set中通知订阅者更新数据 2.实现模板编译compile,深度遍历dom树,对每个元素节点的指令模板替换数据以及订阅数据 3.实现watch用于连接Observer和compile,能够订阅并接受每一个属性的变动的通知, 执行指令绑定的相应的回调函数,从而更新数据 4.实现一个订阅器 Dep:订阅器采用 发布-订阅 设计模式, 用来收集订阅者 Watcher,对监听器 Observer 和 订阅者 Watcher 进行统一管理。
加载速度变慢,影响用户体验。和当 Model 频繁发生变化,开发者需要主动更新到View。3. 生命周期函数
new Vue(创建一个Vue对象)--> beforeCreate --> observer Data(开始监控data对象数据变化) --> init event(vue内部初始化事件) --> created() --> compile(编译模板,把data里面的数据和模板生成html) --> beforeMount(还没有生成HTML到元素上) --> mounted(挂载完成,也就是模板中的html渲染到了html页面中) --> beforeUpdate (Vritual Dom) --> updated --> beforeDestroy --> destroyed
如果你想每次进入组件都做一些事情的话,你可以放在activated进入缓存组件的钩子中4. 说说你对 SPA 单页面的理解,它的优缺点分别是什么?
基于上面一点,SPA 相对对服务器压力小;
前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。5. Vue的SPA 如何优化加载速度
1.减少入口文件体积 2.静态资源本地缓存 3.开启Gzip压缩 4.使用SSR,nuxt.js
6. v-show 与 v-if 有什么区别?
7. 怎样理解 Vue 的单向数据流?
props: ['initialCounter'], data: function () { return { counter: this.initialCounter } }
props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
8. computed 和 watch 的区别和运用的场景?
9. 直接给一个数组项赋值,Vue 能检测到变化吗?
vm.items[indexOfItem] = newValue
vm.items.length = newLength
// Vue.set Vue.set(vm.items, indexOfItem, newValue) // vm.$set,Vue.set的一个别名 vm.$set(vm.items, indexOfItem, newValue) // Array.prototype.splice vm.items.splice(indexOfItem, 1, newValue)
// Array.prototype.splice vm.items.splice(newLength)
10. Vue 的父组件和子组件生命周期钩子函数执行顺序?
父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父 beforeUpdate -> 父 updated
父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed11. 在哪个生命周期内调用异步请求?
12. 在什么阶段才能访问操作DOM?
13. 父组件可以监听到子组件的生命周期吗?
// Parent.vue <Child @mounted="doSomething"/> // Child.vue mounted() { this.$emit("mounted"); }
// Parent.vue <Child @hook:mounted="doSomething" ></Child> doSomething() { console.log('父组件监听到 mounted 钩子函数 ...'); }, // Child.vue mounted(){ console.log('子组件触发 mounted 钩子函数 ...'); }, // 以上输出顺序为: // 子组件触发 mounted 钩子函数 ... // 父组件监听到 mounted 钩子函数 ...
14. 为什么组件中的 data 必须是一个函数,然后 return 一个对象,而 new Vue 实例里,data 可以直接是一个对象?
// data data() { return { message: "子组件", childName:this.name } } // new Vue new Vue({ el: '#app', router, template: '<App/>', components: {App} })
15. v-model 的原理?
<input v-model='something'> 相当于 <input v-bind:value="something" v-on:input="something = $event.target.value">
父组件: <ModelChild v-model="message"></ModelChild> 子组件: <div>{{value}}</div> props:{ value: String }, methods: { test1(){ this.$emit('input', '小红') }, },
16. Vue 组件间通信有哪几种方式?
props / $emit
适用 父子组件通信
这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。ref 与 $parent / $children
适用 父子组件通信
ref
:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例$parent / $children
:访问父 / 子实例EventBus ($emit / $on)
适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。$attrs/$listeners
适用于 隔代组件通信
$attrs
:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop
时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过v-bind="$attrs"
传入内部组件。通常配合 inheritAttrs
选项一起使用。$listeners
:包含了父作用域中的 (不含 .native 修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件provide / inject
适用于 隔代组件通信
祖先组件中通过 provider
来提供变量,然后在子孙组件中通过 inject
来注入变量。 provide / inject API
主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(6)Vuex
适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
17. 你使用过 Vuex 吗?
18. 使用过 Vue SSR 吗?说说 SSR?
即:SSR大致的意思就是vue在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的html 片段直接返回给客户端这个过程就叫做服务端渲染。
19. vue-router 路由模式有几种?
switch (mode) { case 'history': this.history = new HTML5History(this, options.base) break case 'hash': this.history = new HashHistory(this, options.base, this.fallback) break case 'abstract': this.history = new AbstractHistory(this, options.base) break default: if (process.env.NODE_ENV !== 'production') { assert(false, `invalid mode: ${mode}`) } }
20. 能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?
(1)hash 模式的实现原理
https://www.word.com#search
hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;(2)history 模式的实现原理
window.history.pushState(null, null, path); window.history.replaceState(null, null, path);
21. Vue 框架怎么实现对象和数组的监听?
/** * Observe a list of Array items. */ observeArray (items: Array<any>) { for (let i = 0, l = items.length; i < l; i++) { observe(items[i]) // observe 功能为监测数据的变化 } } /** * 对属性进行递归遍历 */ let childOb = !shallow && observe(val) // observe 功能为监测数据的变化
22. Proxy 与 Object.defineProperty 优劣对比
Proxy 的优势如下:
Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;Object.defineProperty 的优势如下:
23. Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?
Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)
来实现为对象添加响应式属性,那框架本身是如何实现的呢?vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any { // target 为数组 if (Array.isArray(target) && isValidArrayIndex(key)) { // 修改数组的长度, 避免索引>数组长度导致splcie()执行有误 target.length = Math.max(target.length, key) // 利用数组的splice变异方法触发响应式 target.splice(key, 1, val) return val } // key 已经存在,直接修改属性值 if (key in target && !(key in Object.prototype)) { target[key] = val return val } const ob = (target: any).__ob__ // target 本身就不是响应式数据, 直接赋值 if (!ob) { target[key] = val return val } // 对属性进行响应式处理 defineReactive(ob.value, key, val) ob.dep.notify() return val }
24. 虚拟 DOM 的优缺点?
优点:
缺点:
25. 虚拟 DOM 实现原理?
26. v-html相关
27. Vue 中的 key 有什么作用?
oldStartIndex、oldEndIndex 和 newStartIndex、newEndIndex
,它们会新节点和旧节点会进行两两对比,即一共有4种比较方式:newStartIndex 和oldStartIndex 、newEndIndex 和 oldEndIndex 、newStartIndex 和 oldEndIndex 、newEndIndex 和 oldStartIndex
,如果以上 4 种比较都没匹配,如果设置了key,就会用 key 再进行比较,在比较的过程中,遍历会往中间靠,一旦 StartIdx > EndIdx 表明 oldCh 和 newCh 至少有一个已经遍历完了,就会结束比较。function createKeyToOldIdx (children, beginIdx, endIdx) { let i, key const map = {} for (i = beginIdx; i <= endIdx; ++i) { key = children[i].key if (isDef(key)) map[key] = i } return map }
28.你有对 Vue 项目进行哪些优化?
(1)代码层面的优化
(2)Webpack 层面的优化
(3)基础的 Web 技术的优化
29. 模块化
1.AMD 浏览器 requirejs 模块被异步加载, 模块加载不影响后面语句的运行 默认使用baseURL+ paths的路经解析方式 2.CommonJS nodejs 3.ES6的import/export 4.CMD 浏览器端
30. 谈谈Vue和React组件化的思想
31. 对于即将到来的 vue3.0 特性你有什么了解的吗?
(1)监测机制的改变
(2)模板
(3)对象式的组件声明方式
(4)其它方面的更改
32. 你知道vue的模板语法用的是哪个web模板引擎的吗?说说你对这模板引擎的理解
负责组装数据,以另外一种形式或外观展现数据。
32. 你知道vue的模板语法用的是哪个web模板引擎的吗?说说你对这模板引擎的理解
负责组装数据,以另外一种形式或外观展现数据。
33. 怎么给vue定义全局的方法?
Object.keys(tools).forEach(key => { Vue.prototype[key] = tools[key] })
Vue.mixin(mixin) new Vue({ store, router, render: h => h(App), }).$mount('#app') import tools from "./tools" import filters from "./filters" import Config from '../config' import CONSTANT from './const_var' export default { data() { return { CONFIG: Config, CONSTANT: CONSTANT } }, methods: { // //将tools里面的方法挂载到vue上,以方便调用,直接this.$xxx方法名就可以了 // Object.keys(tools).forEach(key => { // Vue.prototype[key] = tools[key] // }) //将tools里面的方法用对象展开符混入到mixin上,以方便调用,直接this.$xxx方法名就可以了 ...tools }, filters: { // //将filter里面的方法添加了vue的筛选器上 // Object.keys(filters).forEach(key => { // Vue.filter(key, filters[key]) // }) ...filters } }
34. vue2.0不再支持v-html中使用过滤器了怎么办?
htmlFilter(htmlString){ return htmlString.replace(/+s/g,'') }
35. 怎么解决vue打包后静态资源图片失效的问题?
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算