前端面试中常见Vue知识点整理
vue高阶面试题
vue高阶面试题1. Vue实现响应式数据的原理是什么?Vue实现响应式数据的原理是通过Object.defineProperty方法对数据属性进行劫持,当数据属性值改变时,Vue会自动更新视图。
2. Vue的生命周期有哪些?它们的执行顺序是怎样的?Vue的生命周期包括:创建前、创建后、挂载前、挂载后、更新前、更新后、销毁前、销毁后。
它们的执行顺序是创建前 -> 创建后 -> 挂载前 -> 挂载后 -> 更新前 -> 更新后 -> 销毁前 -> 销毁后。
3. 什么是Vue组件?如何定义一个Vue组件?```。
//组件选项。
})。
```。
5. 什么是v-model指令?如何使用v-model指令?v-model指令是Vue中用于双向数据绑定的指令,可以将表单元素的值与Vue实例中的数据属性进行绑定。
使用v-model指令需要在表单元素上添加v-model属性,并将其绑定到Vue实例中的数据属性,例如:```。
<input v-model="message" />。
```。
指令是Vue中用于将属性值绑定到DOM元素上的特殊属性,常用的指令有v-if、v-for、v-bind、v-on、v-show、v-model等。
7. 什么是Vue的路由?Vue中常用的路由有哪些?Vue的路由是用于处理前端路由的插件,可以使用户在应用内部实现跳转,同时也实现了SPA的功能。
Vue中常用的路由插件包括vue-router、vue-navigation、vue-router-tab等。
8. 什么是Vue-mixins?如何使用Vue-mixins?Vue-mixins是Vue中用于组件复用的一种方法,可以将组件的公共逻辑抽取出来,并将其作为一个混入对象引入到一个或多个组件中。
使用Vue-mixins需要在组件选项中使用mixins选项,指定要引入的混入对象,例如:```。
vue面试常被问到的问题整理
vue⾯试常被问到的问题整理1、Vue的双向数据绑定原理是什么?答: vue是采⽤数据劫持,并且使⽤发布-订阅者的开发模式。
原理是观察者observer通过Object.defineProperty()来劫持到各个属性的getter setter,在数据变动的时候,会被observer观察到,会通过Dep通知数据的订阅者watcher,之后进⾏相应的视图上⾯的变化具体实现步骤,感兴趣的可以看看第⼀步:需要observe的数据对象进⾏递归遍历,包括⼦属性对象的属性,都加上 setter和getter这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化第⼆步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页⾯视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,⼀旦数据有变动,收到通知,更新视图第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:1、在⾃⾝实例化时往属性订阅器(dep)⾥⾯添加⾃⼰2、⾃⾝必须有⼀个update()⽅法3、待属性变动dep.notice()通知时,能调⽤⾃⾝的update()⽅法,并触发Compile中绑定的回调,则功成⾝退。
第四步:MVVM作为数据绑定的⼊⼝,整合Observer、Compile和Watcher三者,通过Observer来监听⾃⼰的model数据变化,通过Compile 来解析编译模板指令,最终利⽤Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果2、请详细说下你对vue⽣命周期的理解?答:创建前/后,DOM渲染前/后,更新前/后,销毁前/后;对于各个周期的理解:创建前/后:beforeCreated:此时的vue实例还没有挂载元素$el,数据对象data也是undefiend;created:vue实例的数据对象data有了,但是$el还没有载⼊前/后:beforeMount:vue的实例的$el和data都初始化了,但还是挂载在之前虚拟的DOM节点上⾯,data.message还未替换mounted :vue实例挂载完成,data.message成功渲染。
前端使用面试知识点
前端使用面试知识点一、知识概述《前端使用面试知识点》①基本定义:前端开发在面试时会涉及到的一些知识内容,包括但不限于编程语言(如JavaScript、HTML、CSS)的掌握,框架(像Vue、React等)的使用,以及前端性能优化、页面布局、交互逻辑等多方面的知识,这是为了考察求职者是否具备前端开发的能力和经验。
②重要程度:这是进入前端开发岗位必须跨越的一道坎,就像钥匙对于锁一样重要。
如果在面试中对这些知识点不熟悉,很难得到工作机会,在整个前端开发行业里,这是求职的必经之路。
③前置知识:需要提前掌握基本的计算机操作知识,了解网络的基本原理,比如HTTP协议等。
还有一些基础的数学知识也很有帮助,像在布局计算的时候。
④应用价值:在实际开发工作中,这些知识是完成项目的基础。
例如在构建网站或者Web应用时,HTML负责构建页面结构,CSS负责样式设计,JavaScript负责交互逻辑,前端框架可以提高开发效率,性能优化知识能让用户体验更好。
二、知识体系①知识图谱:前端使用面试知识点涵盖了从基础语法到高级框架应用、性能优化等全方位知识,是前端开发知识体系中最关键的部分用于对接外部筛选和检验。
②关联知识:它与后端开发知识有关联,例如前端向后端发送请求获取数据。
与设计知识也相关,前端开发要把设计师的想法用代码实现。
③重难点分析:重难点在于JavaScript的高级特性理解和熟练运用,像闭包、原型链等。
框架的原理和生命周期也是难度比较大的部分,关键在于不断的实践和深入底层原理学习。
④考点分析:在面试考试中非常重要,大多会通过问答、现场编码等形式考查,会让写出某种功能的代码实现或者解释某种前端现象的原理。
三、详细讲解【理论概念类】①概念辨析:- JavaScript:是一种脚本语言,能让网页有交互性。
就好比是网页的大脑,指挥着网页进行各种动态的活动。
- HTML(超文本标记语言):用来构建网页结构,像是房子的框架,把网页各部分像一个个房间一样规划好。
vue高级面试题目及答案
vue高级面试题目及答案Vue是一个流行的JavaScript框架,用于构建用户界面。
它具有简单易用的API、双向数据绑定和组件化开发的特性,因此在前端开发中得到广泛应用。
在Vue的高级面试中,可能会涉及到一些复杂的概念和问题。
本文将介绍一些常见的Vue高级面试题目及其答案。
一、Vue核心概念题1. 什么是Vue的响应式系统?答:Vue的响应式系统是指Vue如何追踪数据的变化,并使界面中的内容自动更新以反映这些变化。
当一个Vue实例被创建时,Vue会将所有的data属性转换为getter/setter,并利用这些属性的setter来监听变化。
每当数据发生改变时,Vue会通知所有依赖该数据的地方更新视图。
2. 什么是Vue的虚拟DOM?答:Vue的虚拟DOM是一种将界面表示为JavaScript对象的技术。
它允许Vue在内存中维护一个虚拟的DOM树,并通过比较虚拟DOM 树的差异来快速更新真实的DOM。
这样可以避免直接操作真实DOM 所带来的性能损耗,并提高更新的效率。
3. 什么是Vue的computed属性?答:Vue中的computed属性是一种基于依赖关系自动更新的属性。
它接收一个函数作为参数,该函数的返回值会被缓存起来,并在依赖的数据发生变化时自动更新。
computed属性通常用于根据其他数据进行计算,并将计算结果作为属性暴露给模板使用。
4. 什么是Vue的watch属性?答:Vue的watch属性用于监听一个特定的数据,并在该数据发生变化时执行相应的回调函数。
它可以用于监听单个数据、深度监听对象或数组的变化,并可以进行异步操作或控制流程。
二、Vue组件开发题1. 请描述Vue组件的生命周期及其钩子函数。
答:Vue组件的生命周期可以分为实例化、挂载、更新和销毁四个阶段。
每个阶段都有对应的钩子函数,可以在特定的时机执行特定的代码。
- 实例化阶段:beforeCreate、created- 挂载阶段:beforeMount、mounted- 更新阶段:beforeUpdate、updated- 销毁阶段:beforeDestroy、destroyed2. 如何在Vue组件之间进行通信?答:Vue组件之间可以通过属性(prop)、自定义事件和中央事件总线等方式进行通信。
vue面试题目及答案
vue面试题目及答案Vue是一款用于构建用户界面的渐进式框架,它易于学习和使用,因此在前端开发中得到了广泛的应用。
在面试中,经常会涉及到Vue 相关的问题。
本文将为你介绍一些常见的Vue面试题目及答案。
1. 什么是Vue.js?Vue.js是一款用于构建交互式用户界面的开源JavaScript框架。
它采用组件化的开发方式,通过组件的组合来构建复杂的应用。
2. Vue.js相比其他框架或库有哪些优点?- 简洁轻量:Vue.js的文件大小较小,加载速度快。
- 易学易用:Vue.js的API简单易懂,上手门槛低。
- 双向数据绑定:Vue.js采用了数据驱动的思想,实现了数据与视图的自动同步更新。
- 组件化开发:Vue.js支持组件化开发,能够提高代码的可维护性和复用性。
- 生态丰富:Vue.js拥有庞大的插件生态系统,可以方便地集成其他库或工具。
3. Vue的生命周期是什么?Vue实例有以下几个生命周期钩子:- beforeCreate:实例刚在内存中创建,数据观测(data observer)和事件配置之前。
- created:实例已经创建完成,属性计算、数据观测(data observer)和事件配置已完成。
- beforeMount:在挂载之前被调用,相关的render函数首次被调用。
- mounted:实例已经挂载到DOM上,进行DOM操作的最佳时机。
- beforeUpdate:数据更新时调用,例如在虚拟DOM重新渲染之前。
- updated:数据更新后调用,用于操作更新后的DOM。
- beforeDestroy:实例销毁之前调用,可以进行一些清理工作。
- destroyed:实例已经销毁,清理工作已完成。
4. Vue组件之间如何通信?Vue组件之间可以使用props和events进行父子组件之间的通信。
父组件通过props向子组件传递数据,子组件通过事件向父组件发送消息。
5. Vue中的computed和watch有什么区别?computed是一种属性,依赖于其他响应式数据,并且计算结果会被缓存。
VUE面试题精选
Vue常见面试题知识点(一)第一讲对于Vue是一套渐进式框架的理解问题一:vue.js的两个核心是什么?1、数据驱动,也叫双向数据绑定。
Vue.js数据观测原理在技术实现上,利用的是ES5Object.defineProperty和存储器属性:getter和setter(所以只兼容IE9及以上版本),可称为基于依赖收集的观测机制。
核心是VM,即ViewModel,保证数据和视图的一致性。
2、组件系统。
.vue组件的核心选项:1、模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
2、初始数据(data):一个组件的初始数据状态。
对于可复用的组件来说,这通常是私有的状态。
3、接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。
4、方法(methods):对数据的改动操作一般都在组件的方法内进行。
5、生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。
6、私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。
一个组件可以声明自己的私有资源。
私有资源只有该组件和它的子组件可以调用。
等等。
问题二:对于Vue是一套构建用户界面的渐进式框架的理解渐进式代表的含义是:没有多做职责之外的事。
vue.js只提供了vue-cli生态中最核心的组件系统和双向数据绑定。
像vuex、vue-router都属于围绕vue.js开发的库。
比如说,你要使用Angular,必须接受以下东西:必须使用它的模块机制必须使用它的依赖注入-必须使用它的特殊形式定义组件(这一点每个视图框架都有,难以避免)所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西集成,这些主张会带来一些困扰。
比如说,你要使用React,你必须理解:∙函数式编程的理念,∙需要知道什么是副作用,∙什么是纯函数,∙如何隔离副作用∙它的侵入性看似没有Angular那么强,主要因为它是软性侵入。
常见的Vue面试题及答案
常见的Vue面试题及答案1.Vue是什么?答:Vue是一种前端JavaScript框架,用于构建用户界面。
它采用MVVM架构,使用数据驱动的方式来实现界面更新。
2.Vue有哪些特点?答:Vue的特点包括:易学易用、响应式数据绑定、组件化开发、插件化体系、良好的性能表现等。
3.Vue的工作流程是怎样的?答:Vue的工作流程包括以下几个步骤:初始化:创建Vue实例,并传入一个数据对象。
编译模板:将HTML模板编译成虚拟DOM。
挂载:将虚拟DOM挂载到页面上。
更新:当数据变化时,Vue会自动更新虚拟DOM,并在下一次渲染前对比新旧虚拟DOM,然后更新页面。
4.Vue中的指令有哪些?答:Vue中的指令包括:v-bind、v-model、v-if、v-for、v-show、v-html、v-text等。
5.Vue中的组件是什么?答:Vue中的组件是自定义元素,它可以封装一个特定的功能或UI组件,并具有独立的数据、方法和模板。
6.如何使用Vue的组件化体系?答:Vue的组件化体系可以让开发者将界面划分为多个独立的组件,每个组件具有自己的数据、方法、模板等。
使用组件可以通过定义组件标签、编写组件的模板、使用组件的选项等方式来实现。
7.Vue中的事件处理是怎样的?答:Vue中的事件处理可以使用v-on指令来绑定事件。
例如:v-on:click="handleClick"。
其中,handleClick是Vue实例中定义的方法,用于处理事件。
8.Vue中的路由是什么?答:Vue中的路由是用来管理页面跳转的。
它可以使用Vue Router来实现,可以定义路由配置,指定页面的路径和组件等。
9.Vue中的状态管理是什么?答:Vue中的状态管理是用来管理应用的状态,包括全局状态和局部状态。
它可以使用Vuex来实现,将状态存储在一个中央存储库中,并通过getter和setter方法来进行访问和修改。
10.Vue中的生命周期钩子有哪些?答:Vue中的生命周期钩子包括:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed等。
vue知识点总结
vue知识点总结一、Vue的基本概念1. 数据驱动Vue采用的是数据驱动的开发模式,它通过简单的数据绑定来驱动应用程序的UI。
这意味着当数据发生变化时,UI会自动更新,无需手动干预。
这种方法大大简化了开发过程,并减少了出错的可能性。
2. 组件化Vue是一个组件化的框架,它将应用程序划分为一系列小型、独立的组件。
每个组件都有自己的HTML模板、CSS样式和JavaScript逻辑,可以轻松地在不同的页面重用和组合。
这种组件化的开发方式使得代码更加模块化、可维护性更高。
3. 生命周期钩子Vue组件具有一系列的生命周期钩子函数,它们允许我们在组件的不同阶段执行自定义的逻辑。
比如在组件创建之前、更新之后或销毁之前执行一些操作。
这为我们提供了更多的控制和定制能力。
4. 响应式系统Vue的核心是其响应式系统,它可以监测数据的变化并自动更新DOM。
这样用户只需要关注数据的改变,而不需要手动更新UI。
在这一点上,Vue与其他框架有所不同,它的响应式系统更加高效、灵活和易于使用。
二、Vue的基本语法1. 模板语法Vue使用了一种类似于Moustache的模板语法,可以将数据绑定到DOM中。
比如使用双大括号`{{}}`来绑定变量,使用`v-bind`来绑定DOM属性,使用`v-for`来进行列表渲染等等。
2. 指令Vue提供了一系列的指令,用于实现一些特定的DOM操作。
比如`v-if`用来条件性地渲染一个元素,`v-on`用来绑定事件监听器,`v-model`用来实现双向数据绑定等等。
3. 计算属性Vue允许我们在模板中使用计算属性,这些属性会在依赖的数据发生变化时自动更新。
这可以极大地简化模板中的逻辑,使得代码更加清晰和可维护。
4. 组件Vue的组件是一种独立的、可复用的UI单元,它将相关的HTML、CSS和JavaScript封装在一起。
组件可以嵌套使用,可以传递数据和事件。
通过组件,我们可以将复杂的UI拆分为简单的部分,提高了代码的复用性和可维护性。
vue面试题及答案
vue面试题及答案Vue.js是一种用于构建用户界面的渐进式JavaScript框架。
它易学易用,同时也非常强大。
在面试中,Vue.js常常是前端开发岗位的热门话题。
下面是一些常见的Vue面试题及其答案,希望对你的面试有所帮助。
1. 请解释什么是Vue.js?Vue.js是一种用于构建用户界面的开源JavaScript框架。
它采用了MVVM模式,可以轻松地与现有项目集成,同时具备响应式数据绑定和组件化的特性。
2. Vue.js与React和Angular相比有什么优势?Vue.js相比React和Angular具有以下优势:- 学习曲线较低:Vue.js的语法简洁明了,易于学习和上手。
- 性能优化:Vue.js采用虚拟DOM技术,在数据更新时只更新出现变化的部分,提高了性能。
- 灵活性:Vue.js支持组件化开发,可以灵活地组织和复用代码。
- 生态系统:Vue.js有丰富的插件和库,可以满足不同项目的需求。
- 社区支持:Vue.js拥有庞大的社区支持,可以轻松找到解决问题的方案。
3. 请解释什么是双向数据绑定?双向数据绑定是Vue.js最重要的特性之一。
它指的是数据模型和视图之间的同步更新。
当数据模型发生变化时,视图会相应地更新;反之亦然。
这种机制使得开发者无需手动操作DOM,大大简化了开发过程。
4. 请解释什么是Vue组件?Vue组件是Vue.js中用于封装可重用代码的基本单位。
每个Vue组件包含了HTML、CSS和JavaScript,并且可以嵌套使用。
通过组件化开发,可以提高代码的可维护性和复用性。
5. 请解释什么是Vue的生命周期钩子函数?Vue的生命周期钩子函数是在Vue实例在不同阶段执行的回调函数。
常用的生命周期钩子函数包括:- beforeCreate:实例初始化前的钩子函数。
- created:实例创建完成后的钩子函数。
- beforeMount:在模板挂载到DOM之前执行的钩子函数。
前端知识点总结 vue
前端知识点总结 vue在这篇文章中,我们将对Vue.js的主要知识点进行总结,包括基本概念、核心特性、常用指令、组件化开发、状态管理、路由等方面,希望能够帮助读者更好地掌握Vue.js的知识。
一、基本概念1. MVVM模式MVVM是Model-View-ViewModel的缩写,是一种软件架构模式,它将用户界面分为三个部分:Model表示数据模型,View表示视图层,ViewModel则是将Model和View连接起来的中间层。
在Vue.js中,数据模型是响应式的,当数据发生变化时,视图自动更新,这正是MVVM模式的核心特点。
2. 响应式响应式指的是当数据发生变化时,视图能够自动更新。
在Vue.js中,数据是响应式的,当数据发生变化时,与之相关的视图将会自动更新。
这是通过Vue.js的响应式系统实现的,它能够监听数据的变化,从而及时更新视图。
3. 双向数据绑定双向数据绑定是Vue.js的一个重要特性,它让数据的变化能够自动更新视图,同时也能够让视图中的输入框等元素的变化同步到数据中。
这可以使开发者更加方便地管理数据和视图之间的关系,提高开发效率。
4. 组件化在Vue.js中,一切皆组件。
组件是Vue.js的重要概念,它可以将一个页面切分为若干个独立的、可复用的组件,每个组件都有自己的数据、模板和方法,可以使代码结构更加清晰,方便维护和复用。
5. 虚拟DOM虚拟DOM是Vue.js的另一个重要特性,它能够减少真实DOM的操作,提高性能。
在Vue.js中,数据变化时,Vue会创建一个虚拟DOM树,然后通过diff算法比较新旧虚拟DOM,找出最小的变化,然后只更新真实DOM中需要更新的部分,这一过程称为虚拟DOM的重新渲染。
二、核心特性1. 模板在Vue.js中,模板用来定义视图层,它使用基于HTML的模板语法,可以直接在模板中使用数据和表达式,从而实现动态绑定。
Vue.js的模板语法非常简单和灵活,类似于Angular.js和Handlebars等框架的模板语法,但功能更强大。
vue基本知识
vue基本知识
Vue是一种流行的JavaScript框架,用于构建交互式Web界面。
它使用模板语法和组件化架构来使开发人员能够轻松地构建可重用和可维护的代码。
以下是Vue的一些基本概念和语法:
1. 数据绑定:Vue使用双向数据绑定来自动同步视图和数据。
当数据发生变化时,视图也会同步更新,反之亦然。
2. 组件化:Vue将每个页面拆分成多个小组件,并允许开发人员将它们重用在多个页面中。
组件可以包含自己的HTML、CSS和JavaScript代码,使其更易于维护和扩展。
3. 生命周期:Vue组件具有一系列生命周期钩子函数,可以在组件被创建、更新、销毁等不同的阶段执行自定义代码。
4. 模板语法:Vue使用类似HTML的模板语法来编写组件的视图部分。
它支持插值、指令、事件处理程序等,使开发人员可以轻松地创建动态的Web界面。
5. 计算属性:Vue允许开发人员定义计算属性,这些属性根据其他属性的值进行计算。
它们可以与模板语法一起使用,使数据处理更加简单和高效。
6. 组件通信:Vue提供了多种组件通信方式,包括props、事件和中央事件总线。
开发人员可以根据需要选择适合自己的方法。
以上是Vue的一些基本知识,掌握这些概念和语法可以让开发人员更加轻松地构建高质量的Web应用程序。
- 1 -。
前端面试题整理—Vue篇
前端⾯试题整理—Vue篇1、对vue的理解,有什么特点,vue为什么不能兼容IE8及以下浏览器 vue是⼀套⽤于构建⽤户界⾯的渐进式框架,核⼼是⼀个响应的数据绑定系统 vue是⼀款MVVM框架,基于双向绑定数据,当数据发⽣变化时候,vue⾃⾝会进⾏⼀些运算 特点:简洁轻量、数据驱动、组件化、模块友好 vue.js使⽤了IE8⽆法模拟的 ECMAScript 5 特性,没有替代⽅案2、简述Vue双向数据绑定的原理 主要是通过Object对象的defineProperty属性,重写data的set和get函数来实现的 vue是通过数据劫持的⽅式来做数据绑定,最核⼼的⽅法就是通过Object.defineProperty()来实现对属性的劫持 在设置或者获取的时候我们就可以在get或者set⽅法⾥加⼊其他的触发函数,达到监听数据变动的⽬的3、什么是MVVM,和MVC的区别 MVVM是Model-View-ViewModel的缩写 Model层代表数据模型 View代表组件视图,负责将数据模型转化成UI展现出来 ViewModel是⼀个同步 View 和 Model 的对象(双向绑定) 在MVVM中,View和Model之间并没有直接的联系,⽽是通过ViewModel进⾏交互, Model和ViewModel之间的交互是双向的,因此通过视图操作数据,也能通过数据操作视图 MVC是Model-View- Controller的简写。
即模型-视图-控制器,使⽤MVC的⽬的是为了将M和V相分离 MVVM与MVC最⼤的区别就是实现了View和Model的⾃动同步,也就是当Model的属性改变时 我们不⽤再⼿动操作Dom来改变View,⽽是改变后该属性对应View层会⾃动改变4、vue.js的两个核⼼是什么 数据驱动和组件化思想5、vue与angular的区别 vue的双向邦定是基于ES5中getter/setter来实现的,⽽angular是由⾃⼰实现⼀套模版编译规则,需要进⾏所谓的“脏值”检查,vue则不需要 vue需要提供⼀个el对象进⾏实例化,后续的所有作⽤范围也是在el对象之下,⽽angular⽽是整个html页⾯6、说下vue的底层原理 Vue的模式是m-v-vm模式,即(model-view-modelView),通过modelView作为中间层,进⾏双向数据的绑定与变化 1)通过建⽴虚拟dom树document.createDocumentFragment(),⽅法创建虚拟dom树 2)⼀旦被监测的数据改变,会通过Object.defineProperty定义的数据拦截,截取到数据的变化 3)截取到的数据变化,从⽽通过订阅——发布者模式,触发Watcher(观察者),从⽽改变虚拟dom的中的具体数据 4)最后通过更新虚拟dom的元素值,从⽽改变最后渲染dom树的值,完成双向绑定7、简述vue等单页⾯应⽤及优缺点 单页⾯应⽤,⽤户所有的操作都在⼀个页⾯完成 优点:⽆刷新,⽤户体验好,共享资源只需要请求⼀次即可,采⽤组件化的思想,代码结构更加规范化,便于修改和调整 缺点:对搜索引擎不友好、低版本不⽀持,第⼀次加载⾸页耗时相对较长,不能使⽤浏览器导航按钮,需要⾃⾏实现前进后退8、React与Vue对⽐ 相同点: 都⽀持服务器端渲染、数据驱动视图,状态管理 都有虚拟DOM、组件化开发、通过props参数进⾏⽗⼦组件数据的传递 不同点: React严格上只针对MVC的C层,Vue则是MVVM模式 虚拟DOM⽅⾯ vue会跟踪每⼀个组件的依赖关系,不需要重新渲染整个组件树,⽽React每当应⽤的状态被改变时,全部组件都会重新渲染 视图渲染⽅⾯ React采⽤JSX渲染到DOM,vue使⽤的是template模板 数据绑定⽅⾯ vue实现了数据的双向绑定,react数据流动是单向的 state对象⽅⾯ react应⽤中不可变的,需要使⽤setState⽅法更新状态 vue中,state对象不是必须的,数据由data属性在vue对象中管理9、前端组件化有什么优势 1)提⾼开发效率 2)⽅便重复使⽤ 3)便于协同开发 4)更容易管理维护10、说⼀下vue的⽣命周期,当使⽤keep-alive属性时,会增加哪两个⽣命周期 创建前/后beforeCreate/created: 在beforeCreated阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。
前端vue面试题
前端vue面试题Vue.js是一种用于构建用户界面的渐进式JavaScript框架,它以其简洁易用和高效灵活而备受开发者和企业的青睐。
对于前端开发人员来说,了解和掌握Vue.js是非常重要的。
下面是一些常见的前端Vue 面试题,希望能帮助你在面试中取得好的成绩。
1. 请简述Vue.js的特点和优势。
Vue.js具有以下特点和优势:- 渐进式框架:Vue.js的核心库只关注视图层,可以逐步应用到项目中,也可以作为现有项目的一部分引入。
- 数据驱动:Vue.js采用了一种响应式的数据绑定机制,通过数据驱动视图的更新,使得开发更加简单高效。
- 组件化开发:Vue.js将UI组件抽象为独立、可复用的模块,使得代码的分工和重用更加清晰明了。
- 高性能:Vue.js采用了虚拟DOM和异步渲染策略,优化了渲染性能,提升了用户体验。
- 生态丰富:Vue.js拥有庞大的社区和丰富的插件生态系统,可以很方便地扩展功能和解决问题。
2. 请解释Vue实例的生命周期及钩子函数。
Vue实例的生命周期指的是Vue实例从创建、挂载、更新到销毁的整个过程。
而钩子函数则是在不同生命周期阶段执行的特定函数。
- beforeCreate:Vue实例刚被创建时触发,此时数据观测、属性和方法的初始化尚未开始。
- created:Vue实例创建完成后触发,此时可以访问到data和methods等属性。
- beforeMount:Vue实例挂载之前触发,此时模板编译已完成,但尚未将模板渲染到真实DOM中。
- mounted:Vue实例挂载到真实DOM之后触发,此时可以访问到DOM元素。
- beforeUpdate:响应式数据更新时触发,但尚未重新渲染DOM。
- updated:DOM重新渲染和数据更新完成后触发。
- beforeDestroy:Vue实例销毁之前触发,此时Vue实例仍然完全可用。
- destroyed:Vue实例销毁后触发,此时Vue实例的所有事件监听器和子组件都被移除。
前端面试 vue中知识点 diff 整理
面试官:你了解vue的diff算法吗?说说看一、是什么diff算法是一种通过同层的树节点进行比较的高效算法其有两个特点: - 比较只会在同层级进行, 不会跨层级比较 - 在diff比较的过程中,循环从两边向中间比较diff算法的在很多场景下都有应用,在vue中,作用于虚拟dom渲染成真实dom 的新旧VNode节点比较二、比较方式diff整体策略为:深度优先,同层比较1.比较只会在同层级进行, 不会跨层级比较2.比较的过程中,循环从两边向中间收拢下面举个vue通过diff算法更新的例子:新旧VNode节点如下图所示:第一次循环后,发现旧节点D与新节点D相同,直接复用旧节点D作为diff后的第一个真实节点,同时旧节点endIndex移动到C,新节点的startIndex移动到了 C第二次循环后,同样是旧节点的末尾和新节点的开头(都是 C)相同,同理,diff后创建了 C 的真实节点插入到第一次创建的 B 节点后面。
同时旧节点的endIndex移动到了 B,新节点的startIndex移动到了 E第三次循环中,发现E没有找到,这时候只能直接创建新的真实节点 E,插入到第二次创建的 C 节点之后。
同时新节点的startIndex移动到了 A。
旧节点的startIndex和endIndex都保持不动第四次循环中,发现了新旧节点的开头(都是 A)相同,于是diff后创建了 A 的真实节点,插入到前一次创建的E 节点后面。
同时旧节点的startIndex移动到了B,新节点的startIndex移动到了 B第五次循环中,情形同第四次循环一样,因此diff后创建了 B 真实节点插入到前一次创建的 A 节点后面。
同时旧节点的startIndex移动到了 C,新节点的startIndex 移动到了 F新节点的startIndex已经大于endIndex了,需要创建newStartIdx和newEndIdx 之间的所有节点,也就是节点F,直接创建 F 节点对应的真实节点放到 B 节点后面三、原理分析当数据发生改变时,set方法会调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图源码位置:src/core/vdom/patch.jsfunction patch(oldVnode, vnode, hydrating, removeOnly) {if (isUndef(vnode)) { // 没有新节点,直接执行destory钩子函数if (isDef(oldVnode)) invokeDestroyHook(oldVnode)return}let isInitialPatch =falseconst insertedVnodeQueue = []if (isUndef(oldVnode)) {isInitialPatch =truecreateElm(vnode, insertedVnodeQueue) // 没有旧节点,直接用新节点生成dom元素} else {const isRealElement =isDef(oldVnode.nodeType)if (!isRealElement &&sameVnode(oldVnode, vnode)) {// 判断旧节点和新节点自身一样,一致执行patchVnodepatchVnode(oldVnode, vnode, insertedVnodeQueue,null,null, removeOnly)} else {// 否则直接销毁及旧节点,根据新节点生成dom元素if (isRealElement) {if (oldVnode.nodeType===1&& oldVnode.hasAttribute(SS R_ATTR)) {oldVnode.removeAttribute(SSR_ATTR)hydrating =true}if (isTrue(hydrating)) {if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {invokeInsertHook(vnode, insertedVnodeQueue,tru e)return oldVnode}}oldVnode =emptyNodeAt(oldVnode)}return vnode.elm}}}patch函数前两个参数位为oldVnode和Vnode,分别代表新的节点和之前的旧节点,主要做了四个判断:•没有新节点,直接触发旧节点的destory钩子•没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全是新建,所以只调用createElm•旧节点和新节点自身一样,通过sameVnode判断节点是否一样,一样时,直接调用patchVnode去处理这两个节点•旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点下面主要讲的是patchVnode部分function patchVnode (oldVnode, vnode, insertedVnodeQueue, removeOnly) { // 如果新旧节点一致,什么都不做if (oldVnode === vnode) {return}// 让vnode.el引用到现在的真实dom,当el修改时,vnode.el会同步变化const elm = vnode.elm= oldVnode.elm// 异步占位符if (isTrue(oldVnode.isAsyncPlaceholder)) {if (isDef(vnode.asyncFactory.resolved)) {hydrate(oldVnode.elm, vnode, insertedVnodeQueue)} else {vnode.isAsyncPlaceholder=true}return}// 如果新旧都是静态节点,并且具有相同的key// 当vnode是克隆节点或是v-once指令控制的节点时,只需要把oldVnode.elm和oldVnode.child都复制到vnode上// 也不用再有其他操作if (isTrue(vnode.isStatic) &&isTrue(oldVnode.isStatic) &&vnode.key=== oldVnode.key&&(isTrue(vnode.isCloned) ||isTrue(vnode.isOnce))) {ponentInstance= ponentInstancereturn}let iconst data = vnode.dataif (isDef(data) &&isDef(i = data.hook) &&isDef(i = i.prepatch)) { i(oldVnode, vnode)}const oldCh = oldVnode.childrenconst ch = vnode.childrenif (isDef(data) &&isPatchable(vnode)) {for (i =0; i < cbs.update.length;++i) cbs.update[i](oldVnode, v node)if (isDef(i = data.hook) &&isDef(i = i.update)) i(oldVnode, vnod e)}// 如果vnode不是文本节点或者注释节点if (isUndef(vnode.text)) {// 并且都有子节点if (isDef(oldCh) &&isDef(ch)) {// 并且子节点不完全一致,则调用updateChildrenif (oldCh !== ch) updateChildren(elm, oldCh, ch, insertedVnodeQ ueue, removeOnly)// 如果只有新的vnode有子节点} else if (isDef(ch)) {if (isDef(oldVnode.text)) nodeOps.setTextContent(elm,'')// elm已经引用了老的dom节点,在老的dom节点上添加子节点addVnodes(elm,null, ch,0, ch.length-1, insertedVnodeQueue)// 如果新vnode没有子节点,而vnode有子节点,直接删除老的oldCh} else if (isDef(oldCh)) {removeVnodes(elm, oldCh,0, oldCh.length-1)// 如果老节点是文本节点} else if (isDef(oldVnode.text)) {nodeOps.setTextContent(elm,'')}// 如果新vnode和老vnode是文本节点或注释节点// 但是vnode.text != oldVnode.text时,只需要更新vnode.elm的文本内容就可以} else if (oldVnode.text!== vnode.text) {nodeOps.setTextContent(elm, vnode.text)}if (isDef(data)) {if (isDef(i = data.hook) &&isDef(i = i.postpatch)) i(oldVnode, v node)}}patchVnode主要做了几个判断:•新节点是否是文本节点,如果是,则直接更新dom的文本内容为新节点的文本内容•新节点和旧节点如果都有子节点,则处理比较更新子节点•只有新节点有子节点,旧节点没有,那么不用比较了,所有节点都是全新的,所以直接全部新建就好了,新建是指创建出所有新DOM,并且添加进父节点•只有旧节点有子节点而新节点没有,说明更新后的页面,旧节点全部都不见了,那么要做的,就是把所有的旧节点删除,也就是直接把DOM删除子节点不完全一致,则调用updateChildrenfunction updateChildren (parentElm, oldCh, newCh, insertedVnodeQueue, r emoveOnly) {let oldStartIdx =0// 旧头索引let newStartIdx =0// 新头索引let oldEndIdx = oldCh.length-1// 旧尾索引let newEndIdx = newCh.length-1// 新尾索引let oldStartVnode = oldCh[0] // oldVnode的第一个childlet oldEndVnode = oldCh[oldEndIdx] // oldVnode的最后一个childlet newStartVnode = newCh[0] // newVnode的第一个childlet newEndVnode = newCh[newEndIdx] // newVnode的最后一个childlet oldKeyToIdx, idxInOld, vnodeToMove, refElm// removeOnly is a special flag used only by <transition-group>// to ensure removed elements stay in correct relative positions// during leaving transitionsconst canMove =!removeOnly// 如果oldStartVnode和oldEndVnode重合,并且新的也都重合了,证明diff完了,循环结束while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {// 如果oldVnode的第一个child不存在if (isUndef(oldStartVnode)) {// oldStart索引右移oldStartVnode = oldCh[++oldStartIdx] // Vnode has been moved le ft// 如果oldVnode的最后一个child不存在} else if (isUndef(oldEndVnode)) {// oldEnd索引左移oldEndVnode = oldCh[--oldEndIdx]// oldStartVnode和newStartVnode是同一个节点} else if (sameVnode(oldStartVnode, newStartVnode)) {// patch oldStartVnode和newStartVnode,索引左移,继续循环patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue)oldStartVnode = oldCh[++oldStartIdx]newStartVnode = newCh[++newStartIdx]// oldEndVnode和newEndVnode是同一个节点} else if (sameVnode(oldEndVnode, newEndVnode)) {// patch oldEndVnode和newEndVnode,索引右移,继续循环patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue)oldEndVnode = oldCh[--oldEndIdx]newEndVnode = newCh[--newEndIdx]// oldStartVnode和newEndVnode是同一个节点} else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode move d right// patch oldStartVnode和newEndVnodepatchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue)// 如果removeOnly是false,则将oldStartVnode.eml移动到oldEndVno de.elm之后canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, n odeOps.nextSibling(oldEndVnode.elm))// oldStart索引右移,newEnd索引左移oldStartVnode = oldCh[++oldStartIdx]newEndVnode = newCh[--newEndIdx]// 如果oldEndVnode和newStartVnode是同一个节点} else if (sameVnode(oldEndVnode, newStartVnode)) { // Vnode move d left// patch oldEndVnode和newStartVnodepatchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue)// 如果removeOnly是false,则将oldEndVnode.elm移动到oldStartVno de.elm之前canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, old StartVnode.elm)// oldEnd索引左移,newStart索引右移oldEndVnode = oldCh[--oldEndIdx]newStartVnode = newCh[++newStartIdx]// 如果都不匹配} else {if (isUndef(oldKeyToIdx)) oldKeyToIdx =createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)// 尝试在oldChildren中寻找和newStartVnode的具有相同的key的Vnod eidxInOld =isDef(newStartVnode.key)? oldKeyToIdx[newStartVnode.key]:findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)// 如果未找到,说明newStartVnode是一个新的节点if (isUndef(idxInOld)) { // New element// 创建一个新VnodecreateElm(newStartVnode, insertedVnodeQueue, parentElm, oldSt artVnode.elm)// 如果找到了和newStartVnodej具有相同的key的Vnode,叫vnodeToMov e} else {vnodeToMove = oldCh[idxInOld]/* istanbul ignore if */if (process.env.NODE_ENV!=='production'&&!vnodeToMove) {warn('It seems there are duplicate keys that is causing an upd ate error. '+'Make sure each v-for item has a unique key.')}// 比较两个具有相同的key的新节点是否是同一个节点//不设key,newCh和oldCh只会进行头尾两端的相互比较,设key后,除了头尾两端的比较外,还会从用key生成的对象oldKeyToIdx中查找匹配的节点,所以为节点设置key可以更高效的利用dom。
前端面试 vue中知识点 structure 整理
面试官:说下你的vue项目的目录结构,如果是大型项目你该怎么划分结构和划分组件呢?一、为什么要划分使用vue构建项目,项目结构清晰会提高开发效率,熟悉项目的各种配置同样会让开发效率更高在划分项目结构的时候,需要遵循一些基本的原则:•文件夹和文件夹内部文件的语义一致性•单一入口/出口•就近原则,紧耦合的文件应该放到一起,且应以相对路径引用•公共的文件应该以绝对路径的方式从根目录引用•/src外的文件不应该被引入文件夹和文件夹内部文件的语义一致性我们的目录结构都会有一个文件夹是按照路由模块来划分的,如pages文件夹,这个文件夹里面应该包含我们项目所有的路由模块,并且仅应该包含路由模块,而不应该有别的其他的非路由模块的文件夹这样做的好处在于一眼就从pages文件夹看出这个项目的路由有哪些单一入口/出口举个例子,在pages文件夹里面存在一个seller文件夹,这时候seller文件夹应该作为一个独立的模块由外部引入,并且seller/index.js应该作为外部引入seller 模块的唯一入口// 错误用法import sellerReducer from 'src/pages/seller/reducer'// 正确用法import { reducer as sellerReducer } from 'src/pages/seller'这样做的好处在于,无论你的模块文件夹内部有多乱,外部引用的时候,都是从一个入口文件引入,这样就很好的实现了隔离,如果后续有重构需求,你就会发现这种方式的优点就近原则,紧耦合的文件应该放到一起,且应以相对路径引用使用相对路径可以保证模块内部的独立性// 正确用法import styles from './index.module.scss'// 错误用法import styles from 'src/pages/seller/index.module.scss'举个例子假设我们现在的 seller 目录是在src/pages/seller,如果我们后续发生了路由变更,需要加一个层级,变成src/pages/user/seller。
前端面试 vue中知识点 modifier 整理
面试官:Vue常用的修饰符有哪些有什么应用场景一、修饰符是什么在程序世界里,修饰符是用于限定类型以及类型成员的声明的一种符号在Vue中,修饰符处理了许多DOM事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理vue中修饰符分为以下五种:•表单修饰符•事件修饰符•鼠标按键修饰符•键值修饰符•v-bind修饰符二、修饰符的作用表单修饰符在我们填写表单的时候用得最多的是input标签,指令用得最多的是v-model关于表单的修饰符有如下:•lazy•trim•numberlazy在我们填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change事件之后再进行信息同步<input type="text" zy="value"><p>{{value}}</p>trim自动过滤用户输入的首空格字符,而中间的空格不会过滤<input type="text" v-model.trim="value">number自动将用户的输入值转为数值类型,但如果这个值无法被parseFloat解析,则会返回原来的值<input v-model.number="age" type="number">事件修饰符事件修饰符是对事件捕获以及目标进行了处理,有如下修饰符:•stop•prevent•self•once•capture•passive•nativestop阻止了事件冒泡,相当于调用了event.stopPropagation方法<div @click="shout(2)"><button @click.stop="shout(1)">ok</button></div>//只输出1prevent阻止了事件的默认行为,相当于调用了event.preventDefault方法<form v-on:submit.prevent="onSubmit"></form>self只当在event.target是当前元素自身时触发处理函数<div v-on:click.self="doThat">...</div>使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。
前端面试 vue中知识点 error 整理
面试官:你是怎么处理vue项目中的错误的?一、错误类型任何一个框架,对于错误的处理都是一种必备的能力在Vue中,则是定义了一套对应的错误处理规则给到使用者,且在源代码级别,对部分必要的过程做了一定的错误处理。
主要的错误来源包括:•后端接口错误•代码中本身逻辑错误二、如何处理后端接口错误通过axios的interceptor实现网络请求的response先进行一层拦截e(response => {return response;},error => {if (error.response.status==401) {router.push({ name:"Login" });} else {message.error("出错了");return Promise.reject(error);}});代码逻辑问题全局设置错误处理设置全局错误处理函数Vue.config.errorHandler=function (err, vm, info) {// handle error// `info` 是 Vue 特定的错误信息,比如错误所在的生命周期钩子// 只在 2.2.0+ 可用}errorHandler指定组件的渲染和观察期间未捕获错误的处理函数。
这个处理函数被调用时,可获取错误信息和Vue实例不过值得注意的是,在不同Vue版本中,该全局API作用的范围会有所不同:从 2.2.0 起,这个钩子也会捕获组件生命周期钩子里的错误。
同样的,当这个钩子是undefined时,被捕获的错误会通过console.error输出而避免应用崩从 2.4.0 起,这个钩子也会捕获 Vue 自定义事件处理函数内部的错误了从2.6.0 起,这个钩子也会捕获v-on DOM 监听器内部抛出的错误。
另外,如果任何被覆盖的钩子或处理函数返回一个 Promise 链 (例如 async 函数),则来自其 Promise 链的错误也会被处理生命周期钩子errorCaptured是 2.5.0 新增的一个生命钩子函数,当捕获到一个来自子孙组件的错误时被调用基本类型(err: Error, vm: Component, info: string) =>?boolean此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。
前端面试 vue中知识点 permission 整理
面试官:vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?一、是什么权限是对特定资源的访问许可,所谓权限控制,也就是确保用户只能访问到被分配的资源而前端权限归根结底是请求的发起权,请求的发起可能有下面两种形式触发•页面加载触发•页面上的按钮点击触发总的来说,所有的请求发起都触发自前端路由或视图所以我们可以从这两方面入手,对触发权限的源头进行控制,最终要实现的目标是:•路由方面,用户登录后只能看到自己有权访问的导航菜单,也只能访问自己有权访问的路由地址,否则将跳转4xx提示页•视图方面,用户只能看到自己有权浏览的内容和有权操作的控件•最后再加上请求控制作为最后一道防线,路由可能配置失误,按钮可能忘了加权限,这种时候请求控制可以用来兜底,越权请求将在前端被拦截二、如何做前端权限控制可以分为四个方面:•接口权限•按钮权限•菜单权限•路由权限接口权限接口权限目前一般采用jwt的形式来验证,没有通过的话一般返回401,跳转到登录页面重新进行登录登录完拿到token,将token存起来,通过axios请求拦截器进行拦截,每次请求的时候头部携带tokene(config => {config.headers['token'] = cookie.get('token')return config})e(res=>{},{response}=>{if (response.data.code===40099|| response.data.code===40098) { //token过期或者错误router.push('/login')}})路由权限控制方案一初始化即挂载全部路由,并且在路由上标记相应的权限信息,每次路由跳转前做校验const routerMap = [{path:'/permission',component: Layout,redirect:'/permission/index',alwaysShow:true,// will always show the root menumeta: {title:'permission',icon:'lock',roles: ['admin','editor'] // you can set roles in root nav},children: [{path:'page',component: () => import('@/views/permission/page'),name:'pagePermission',meta: {title:'pagePermission',roles: ['admin'] // or you can only set roles in sub nav}}, {path:'directive',component: () => import('@/views/permission/directive'),name:'directivePermission',meta: {title:'directivePermission'// if do not set roles, means: this page does not require permi ssion}}]}]这种方式存在以下四种缺点:•加载所有的路由,如果路由很多,而用户并不是所有的路由都有权限访问,对性能会有影响。
前端面试 vue3中知识点 modal_component 整理
面试官:用Vue3.0 写过组件吗?如果想实现一个 Modal你会怎么设计?一、组件设计组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念(组件)来实现开发的模式现在有一个场景,点击新增与编辑都弹框出来进行填写,功能上大同小异,可能只是标题内容或者是显示的主体内容稍微不同这时候就没必要写两个组件,只需要根据传入的参数不同,组件显示不同内容即可这样,下次开发相同界面程序时就可以写更少的代码,意义着更高的开发效率,更少的Bug和更少的程序体积二、需求分析实现一个Modal组件,首先确定需要完成的内容:•遮罩层•标题内容•主体内容•确定和取消按钮主体内容需要灵活,所以可以是字符串,也可以是一段html代码特点是它们在当前vue实例之外独立存在,通常挂载于body之上除了通过引入import的形式,我们还可通过API的形式进行组件的调用还可以包括配置全局样式、国际化、与typeScript结合三、实现流程首先看看大致流程:•目录结构•组件内容•实现 API 形式•事件处理•其他完善目录结构Modal组件相关的目录结构├── plugins│ └── modal│ ├── Content.tsx // 维护 Modal 的内容,用于 h 函数和 jsx 语法│ ├── Modal.vue // 基础组件│ ├── config.ts // 全局默认配置│ ├── index.ts // 入口│ ├── locale // 国际化相关│ │ ├── index.ts│ │ └── lang│ │ ├── en-US.ts│ │ ├── zh-CN.ts│ │ └── zh-TW.ts│ └── modal.type.ts // ts类型声明相关因为 Modal 会被e(Modal)调用作为一个插件,所以都放在plugins目录下组件内容首先实现modal.vue的主体显示内容大致如下<Teleport to="body":disabled="!isTeleport"><div v-if="modelValue"class="modal"><divclass="mask":style="style"@click="maskClose && !loading && handleCancel()"></div><div class="modal__main"><div class="modal__title line line--b"><span>{{ title || t("r.title") }}</span><spanv-if="close":title="t('r.close')"class="close"@click="!loading && handleCancel()">✕</span></div><div class="modal__content"><Content v-if="typeof content === 'function'":render=" content"/><slot v-else>{{ content }}</slot></div><div class="modal__btns line line--t"><button:disabled="loading"@click="handleConfirm"><span class="loading"v-if="loading">❍</span>{{ t ("r.confirm") }}</button><button@click="!loading && handleCancel()">{{ t("r.cancel") }}</button></div></div></div></Teleport>最外层上通过Vue3 Teleport内置组件进行包裹,其相当于传送门,将里面的内容传送至body之上并且从DOM结构上来看,把modal该有的内容(遮罩层、标题、内容、底部按钮)都实现了关于主体内容<div class="modal__content"><Content v-if="typeof content==='function'":render="content"/><slot v-else>{{content}}</slot></div>可以看到根据传入content的类型不同,对应显示不同得到内容最常见的则是通过调用字符串和默认插槽的形式// 默认插槽<Modal v-model="show"title="演示 slot"><div>hello world~</div></Modal>// 字符串<Modal v-model="show"title="演示 content"content="hello world~"/>通过 API 形式调用Modal组件的时候,content可以使用下面两种•h 函数$modal.show({title:'演示 h 函数',content(h) {return h('div',{style:'color:red;',onClick: ($event: Event) => console.log('clicked', $event.targe t)},'hello world ~');}});•JSX$modal.show({title:'演示 jsx 语法',content() {return (<divonClick={($event: Event) => console.log('clicked', $event.targe t)}>hello world ~</div>);}});实现 API 形式那么组件如何实现API形式调用Modal组件呢?在Vue2中,我们可以借助Vue实例以及Vue.extend的方式获得组件实例,然后挂载到body上import Modal from './Modal.vue';const ComponentClass = Vue.extend(Modal);const instance =new ComponentClass({ el: document.createElement("div") });document.body.appendChild(instance.$el);虽然Vue3移除了Vue.extend方法,但可以通过createVNode实现import Modal from './Modal.vue';const container = document.createElement('div');const vnode =createVNode(Modal);render(vnode, container);const instance = ponent;document.body.appendChild(container);在Vue2中,可以通过this的形式调用全局 APIexport default {install(vue) {vue.prototype.$create= create}}而在 Vue3 的setup中已经没有this概念了,需要调用app.config.globalProperties挂载到全局export default {install(app) {app.config.globalProperties.$create= create}}事件处理下面再看看看Modal组件内部是如何处理「确定」「取消」事件的,既然是Vue3,当然采用Compositon API形式// Modal.vuesetup(props, ctx) {let instance =getCurrentInstance();// 获得当前组件实例onBeforeMount(() => {instance._hub= {'on-cancel': () => {},'on-confirm': () => {}};});const handleConfirm = () => {ctx.emit('on-confirm');instance._hub['on-confirm']();};const handleCancel = () => {ctx.emit('on-cancel');ctx.emit('update:modelValue',false);instance._hub['on-cancel']();};return {handleConfirm,handleCancel};}在上面代码中,可以看得到除了使用传统emit的形式使父组件监听,还可通过_hub属性中添加on-cancel,on-confirm方法实现在API中进行监听app.config.globalProperties.$modal= {show({}) {/* 监听确定、取消事件 */}}下面再来目睹下_hub是如何实现// index.tsapp.config.globalProperties.$modal= {show({/* 其他选项 */onConfirm,onCancel}) {/* ... */const { props, _hub } = instance;const _closeModal = () => {props.modelValue=false;container.parentNode!.removeChild(container);};// 往 _hub 新增事件的具体实现Object.assign(_hub, {async'on-confirm'() {if (onConfirm) {const fn =onConfirm();// 当方法返回为 Promiseif (fn && fn.then) {try {props.loading=true;await fn;props.loading=false;_closeModal();} catch (err) {// 发生错误时,不关闭弹框console.error(err);props.loading=false;}} else {_closeModal();}} else {_closeModal();}},'on-cancel'() {onCancel &&onCancel();_closeModal();}});}};其他完善关于组件实现国际化、与typsScript结合,大家可以根据自身情况在此基础上进行更改。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
看看面试题,只是为了查漏补缺,看看自己那些方面还不懂。
切记不要以为背了面试题,就万事大吉了,最好是理解背后的原理,这样面试的时候才能侃侃而谈。
不然,稍微有水平的面试官一看就能看出,是否有真才实学还是刚好背中了这道面试题。
一、对于MVVM的理解?MVVM 是Model-View-ViewModel 的缩写。
∙Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
∙View代表UI 组件,它负责将数据模型转化成UI 展现出来。
∙ViewModel监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和Model的对象,连接Model和View。
在MVVM架构下,View 和Model 之间并没有直接的联系,而是通过ViewModel 进行交互,Model 和ViewModel 之间的交互是双向的,因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel通过双向数据绑定把View 层和Model 层连接了起来,而View 和Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM,不需要关注数据状态的同步问题,复杂的数据状态维护完全由MVVM 来统一管理。
二、Vue的生命周期beforeCreate(创建前),在数据观测和初始化事件还未开始created(创建后),完成数据观测,属性和方法的运算,初始化事件,$el 属性还没有显示出来beforeMount(载入前),在挂载开始之前被调用,相关的render函数首次被调用。
实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。
注意此时还没有挂载html到页面上。
mounted(载入后),在el 被新创建的vm.$el 替换,并挂载到实例上去之后调用。
实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM 对象。
完成模板中的html渲染到html页面中。
此过程中进行ajax交互。
beforeUpdate(更新前),在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。
可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后),在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。
调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。
然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。
该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前),在实例销毁之前调用。
实例仍然完全可用。
destroyed(销毁后),在实例销毁之后调用。
调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
1、什么是vue生命周期?答:Vue 实例从创建到销毁的过程,就是生命周期。
从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为Vue 的生命周期。
2、vue生命周期的作用是什么?答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3、vue生命周期总共有几个阶段?答:它可以总共分为8个阶段:创建前/后、载入前/后、更新前/后、销毁前/销毁后。
4、第一次页面加载会触发哪几个钩子?答:会触发下面这几个beforeCreate、created、beforeMount、mounted 。
5、DOM 渲染在哪个周期中就已经完成?答:DOM 渲染在mounted 中就已经完成了。
三、Vue实现数据双向绑定的原理:Object.defineProperty()vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。
当把一个普通Java 对象传给Vue 实例来作为它的data 选项时,Vue 将遍历它的属性,用Object.defineProperty()将它们转为getter/setter。
用户看不到getter/setter,但是在内部它们让Vue 追踪依赖,在属性被访问和修改时通知变化。
vue的数据双向绑定将MVVM作为数据绑定的入口,整合Observer,Compile 和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile 来解析编译模板指令(vue中是用来解析{{}}),最终利用watcher搭起observer 和Compile之间的通信桥梁,达到数据变化—>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
js实现简单的双向绑定:.<body>..<div..id.=."app".>..<input..type.=."text"..id.=."txt".>..<p..id.=."show".></p>.</div>.</body>.<..type.=."text/java".>..var. obj = {}..Object..defineProperty(obj,.'txt'., {..get.:.function. () {..return. obj. },..set.:.function. (newValue) {. document.getElementById( .'txt'.).value = newValue. document.getElementById( .'show'.).innerHTML = newValue. }. }). document.addEventListener( .'keyup'.,.function. (e) {. obj.txt = e.target.value. }).</>四、Vue组件间的参数传递1、父组件与子组件传值父组件传给子组件:子组件通过props方法接受数据;子组件传给父组件:$emit 方法传递参数2、非父子组件间的数据传递,兄弟组件传值eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。
项目比较小时,用这个比较合适(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。
技术只是手段,目的达到才是王道)。
五、Vue的路由实现:hash模式和history模式hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash 读取。
特点:hash虽然在URL中,但不被包括在HTTP 请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState 事件的监听到状态变更。
六、Vue与Angular以及React的区别?版本在不断更新,以下的区别有可能不是很正确。
我工作中只用到vue,对angular和react不怎么熟。
1、与AngularJS的区别相同点:都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
不同点:AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观;在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢;Vue.js使用基于依赖追踪的观察并且使用异步队列更新,所有的数据都是独立触发的。
2、与React的区别相同点:React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用;中心思想相同:一切都是组件,组件实例之间可以嵌套;都提供合理的钩子函数,可以让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。
不同点:React采用的Virtual DOM会对渲染出来的结果做脏检查;Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作Virtual DOM。
七、vue路由的钩子函数首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。
一些需要登录才能调整页面的重定向功能。
∙beforeEach主要有3个参数to,from,next。
∙to:route即将进入的目标路由对象。
∙from:route当前导航正要离开的路由。
∙next:function一定要调用该方法resolve这个钩子。
执行效果依赖next 方法的调用参数。
可以控制网页的跳转。
八、vuex是什么?怎么使用?哪种功能场景使用它?只用来读取的状态集中放在store中;改变状态的方式是提交mutations,这是个同步的事物;异步逻辑应该封装在action中。
在main.js引入store,注入。
新建了一个目录store,… export 。
场景有:单页应用中,组件之间的状态、音乐播放、登录状态、加入购物车state:Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。
存放的数据状态,不可以直接修改里面的数据。
mutations:mutations定义的方法动态修改Vuex 的store 中的状态或数据。
getters:类似vue的计算属性,主要用来过滤一些数据。
action:actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。
view 层通过store.dispath 来分发action。
.const. store =.new..Vuex...Store.({.//store实例. state: {. count:.0. },. mutations: {. increment (state) {. state.count++. }. },. actions: {. increment (context) {. mit(.'increment'.). }. }.})modules:项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。