vue面试有哪些插件_VUE面试总结

1、组件间怎么传值,具体说说代码怎样实现

子传父:子向父是通过 events($emit);通过父链 / 子链也可以通信($parent / $children);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners

父传子:父向子传递数据是通过 props,

兄弟组件传值:bus,vuex

跨级父子通信:Bus;Vuex;provide / inject API、$attrs/$listeners

2、Vue双向绑定原理

采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

1、实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者 2、实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数 3、实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

3、Vue的生命周期和钩子函数

image.png

beforecreate : 举个栗子:可以在这加个loading事件 created :在这结束loading,还做一些初始化,实现函数自执行 mounted : 在这发起后端请求,拿回数据,配合路由钩子做一些事情 beforeDestroy: 你确认删除XX吗? destroyed :当前组件已被删除,清空相关内容

4、应该在vue的生命周期的什么阶段发出ajax请求,为什么

看实际情况,一般在 created 里面就可以,如果涉及到需要页面加载完成之后的话就用 mounted

5、vuex是什么?怎么使用?哪种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事务; 异步逻辑应该封装在action中。 在main.js引入store,注入。新建了一个目录store,….. export 。 场景有:单页应用中,组件之间的状态同步、音乐播放、登录状态、加入购物车

image.png

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) {

context.commit('increment')

}

}

})

modules 项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

const moduleA = {

state: { ... },

mutations: { ... },

actions: { ... },

getters: { ... }

}

const moduleB = {

state: { ... },

mutations: { ... },

actions: { ... }

}

const store = new Vuex.Store({

modules: {

a: moduleA,

b: moduleB

})

6、Vue路由守卫

路由跳转前做一些验证,比如登录验证,是网站中的普遍需求。对此,vue-route 提供的 beforeRouteUpdate 可以方便地实现导航守卫。

全局守卫

你可以使用 router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {

// ...

})

每个守卫方法接收三个参数:

to: Route: 即将要进入的目标 路由对象

from: Route: 当前导航正要离开的路由

next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数,确保要调用 next 方法,否则钩子就不会被 resolved

举一个例子:

列举需要判断登录状态的“路由集合”,当跳转至集合中的路由时,如果“未登录状态”,则跳转到登录页面LoginPage;

当直接进入登录页面LoginPage时,如果“已登录状态”,则跳转到首页HomePage;

7、常用的vue指令,Vue的自定义指令怎么做

常用的vue指令有v-if、v-show,v-for,v-model等等

创建局部指令

var app = new Vue({

el: '#app',

data: {

},

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

directives: {

// 指令名称

drag: {

inserted(el) {

// 指令中第一个参数是当前使用指令的DOM

console.log(el);

console.log(arguments);

// 对DOM进行操作

el.style.width = '200px';

el.style.height = '200px';

el.style.background = '#000';

}

}

}

})

全局指令

Vue.directive('dir2', {

inserted(el) {

console.log(el);

}

})

指令的使用

8、Vue登录流程?需要做什么验证

在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下:

第一次登录的时候,前端调后端的登陆接口,发送用户名和密码

后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token

前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面

前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面

每次调后端接口,都要在请求头中加token,我们常用axios的请求库中,添加全局拦截器,将token设置在请求头中。

后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401

如果前端拿到状态码为401,就清除token信息并跳转到登录页面

// http request 拦截器

axios.interceptors.request.use(

config => {

if (store.state.token) { // 判断是否存在token,如果存在的话,则每个http header都加上token

config.headers.Authorization = `token ${store.state.token}`;

}

return config;

},

err => {

return Promise.reject(err);

});

// http response 拦截器

axios.interceptors.response.use(

response => {

return response;

},

error => {

if (error.response) {

switch (error.response.status) {

case 401:

// 返回 401 清除token信息并跳转到登录页面

store.commit(types.LOGOUT);

router.replace({

path: 'login',

query: {redirect: router.currentRoute.fullPath}

})

}

}

return Promise.reject(error.response.data) // 返回接口返回的错误信息

});

9、讲一下MVVM中的vm工作流程

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 来统一管理。

10、Vue和react的区别?

react和vue都是做组件化的,整体的功能都类似,但是他们的设计思路是有很多不同的。使用react和vue,主要是理解他们的设计思路的不同

react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流,

而vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom

react的性能优化需要手动去做,而vue的性能优化是自动的,但是vue的响应式机制也有问题,就是当state特别多的时候,Watcher也会很多,会导致卡顿

react是类式的写法,api很少,而vue是声明式的写法,通过传入各种options,api和参数都很多

react可以通过高阶组件(Higher Order Components--HOC)来扩展,而vue需要通过mixins来扩展

总结:react整体的思路就是函数式,所以推崇纯组件,数据不可变,单向数据流,当然需要双向的地方也可以做到,比如结合redux-form,而vue是基于可变数据的,支持双向绑定。react组件的扩展一般是通过高阶组件,而vue组件会使用mixin。vue内置了很多功能,而react做的很少,很多都是由社区来完成的,vue追求的是开发的简单,而react更在乎方式是否正确。

11、Vue里面的插槽

是组件的一块HTML模板,父组件决定这块模板显不显示以及怎么显示。

位置由子组件自身决定(slot现在组件template的什么位置,父组件传过来的模板将来就显示在什么位置)

匿名插槽:只能有一个,可以放在组件的任何位置

12、Vue-cli2.0和Vue-cli3.0的区别

用vue-cli3.0版本创建的项目与2.0版本相比较,我们会发现,文件目录少了很多 eg:build、config,那么如何像vue-cli 2.* 之前关于端口号的配置、打包之后的路径的配置、图片的配置等,到哪里配置呢??vue-cli 3.0 可以在项目的根目录下新建一个 vue.config.js 文件,之前繁琐的配置都可以在这里直接配置

3.0能直接运行单个组件

3.0有一个UI管理界面

安装了2.0版本,要先卸载

13、Vue的路由实现 || vue-router的原理

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取; 特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。 hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。 history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

14、vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

beforeEach主要有3个参数to,from,next:

to:route即将进入的目标路由对象,

from:route当前导航正要离开的路由

next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。

15、对keep-alive 的了解

是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。

包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。

与 相似,只是一个抽象组件,它不会在DOM树中渲染(真实或者虚拟都不会),也不在父组件链中存在,比如:你永远在 this.$parent 中找不到 keep-alive 。

keep-alive生命周期钩子函数:activated、deactivated

使用会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在activated阶段获取数据,承担原来created钩子中获取数据的任务。

被包含在 中创建的组件,会多出两个生命周期的钩子: activated 与 deactivated

activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。

deactivated:在组件被停用时调用。

注意:只有组件被 keep-alive 包裹时,这两个生命周期才会被调用,如果作为正常组件使用,是不会被调用,以及在 2.1.0 版本之后,使用 exclude 排除之后,就算被包裹在 keep-alive 中,这两个钩子依然不会被调用!另外在服务端渲染时此钩子也不会被调用的。

什么时候获取数据?

当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated。

16、DOM 和虚拟DOM的区别 以及你对于他们了解

DOM的本质:DOM是浏览器概念,浏览器从服务器端读取html页面,浏览器将html解析成一棵元素嵌套关系的dom树,用对象来表示页面上的元素,并提供操作dom对象的api。

虚拟DOM:框架概念,程序员用js对象来模拟页面上dom元素的嵌套关系( 本质 ),为了实现页面元素的高效更新( 目的 )

虚拟DOM是真实DOM结构的映射,即一个数据集合

// 对于这个Html 文件

Hello, the world!

Hello, the code!

// 它对应的虚拟DOM就是

let nodesData = {

tag: 'div',

attr: []

children: [

{

tag: 'p',

children: [

{

tag: 'span',

children: [

{

tag: '#text',

text: 'Hello, the world!'

}

]

}

]

},

{

tag: 'span',

children: [

{

tag: '#text',

text: 'Hello, the code!'

}

]

}

]

}

// 或这种写法

let vNodes = v('div', [

v('p', [

v('span', [ v('#text', 'Hello, the world!') ] )

]

),

v('span', [

v('#text', 'Hello, the code!')

])

]

)

虚拟DOM的核心就是一个diff算法:使用一个render()方法就可以将上面vNodes还原成真实的Html页面

17、vue指令的生命周期

自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind

bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。

inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。

update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

componentUpdated:被绑定元素所在模板完成一次更新周期时调用。

unbind:只调用一次,指令与元素解绑时调用。

18、vue封装公共组件(通用组件)需要考虑到什么

开发通用组件是很基础且重要的工作,通用组件必须具备高性能、低耦合的特性

一、数据从父组件传入

为了解耦,子组件本身就不能生成数据。即使生成了,也只能在组件内部运作,不能传递出去。

父对子传参,就需要用到 props,但是通用组件的的应用场景比较复杂,对 props 传递的参数应该添加一些验证规则

二、在父组件处理事件

在通用组件中,通常会需要有各种事件,

比如复选框的 change 事件,或者组件中某个按钮的 click 事件

这些事件的处理方法应当尽量放到父组件中,通用组件本身只作为一个中转

三、记得留一个 slot

一个通用组件,往往不能够完美的适应所有应用场景

所以在封装组件的时候,只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决

四、不要依赖 Vuex

父子组件之间是通过 props 和 自定义事件 来传参,非父子组件通常会采用 Vuex 传参

但是 Vuex 的设计初衷是用来管理组件状态,虽然可以用来传参,但并不推荐

因为 Vuex 类似于一个全局变量,会一直占用内存

在写入数据庞大的 state 的时候,就会产生内存泄露

五、合理运用 scoped 编写 CSS

在编写组件的时候,可以在

但是一味的使用 scoped,肯定会产生大量的重复代码

所以在开发的时候,应该避免在组件中写样式

当全局样式写好之后,再针对每个组件,通过 scoped 属性添加组件样式

19、父组件怎么调用子组件里的方法

在父组件中:首先要引入子组件 import Child from './child';

是在父组件中为子组件添加一个占位,ref="mychild"是子组件在父组件中的名字

父组件中 components: {  是声明子组件在父组件中的名字}

在父组件的方法中调用子组件的方法,很重要 this.$refs.mychild.parentHandleclick("嘿嘿嘿"); parentHandleclick是子组件中的方法

20、css只在当前组件起作用

答:在style标签中写入scoped即可 例如:

21、v-if 和 v-show 区别

答:v-if按照条件是否渲染,v-show是display的block或none;

22、

router的区别

答:

router是“路由实例”对象包括了路由的跳转方法,钩子函数等。

23、vue.js的两个核心是什么?

答:数据驱动、组件系统

24、vue常用的修饰符?

答:.prevent: 提交事件不再重载页面;.stop: 阻止单击事件冒泡;.self: 当事件发生在该元素本身而不是子元素的时候会触发;.capture: 事件侦听,事件发生的时候会调用

25、v-on 可以绑定多个方法吗?

答:可以

26、vue中 key 值的作用?

答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。

27、什么是vue的计算属性?

答:在模板中放入太多的逻辑会让模板过重且难以维护,在需要对数据进行复杂处理,且可能多次使用的情况下,尽量采取计算属性的方式。好处:①使得数据处理结构清晰;②依赖于数据,数据更新,处理结果自动更新;③计算属性内部this指向vm实例;④在template调用时,直接写计算属性名即可;⑤常用的是getter方法,获取数据,也可以使用set方法改变数据;⑥相较于methods,不管依赖的数据变不变,methods都会重新计算,但是依赖数据不变的时候computed从缓存中获取,不会重新计算。

计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新。

原始字符:{{msg}}

计算属性翻转字符:{{reverseMsg}}

new Vue({

el:'#app',

data:{

msg:'Hello'

},

//vue的计算属性

computed:{

reverseMsg(){

//返回翻转后的字符串,当msg变化后reverseMsg会跟着变化

return this.msg.split('').reverse().join('')

}

}

})

28、vue等单页面应用及其优缺点

答:优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。 缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。

29、路由之间跳转

声明式(标签跳转) 编程式( js跳转)

通过router-link实现跳转

img

通过js的编程的方式

img

30、Vue中怎么实现跨域

使用http-proxy-middleware 代理解决(项目使用vue-cli脚手架搭建)

例如请求的url:“http://aa.com/demo.json“

1、打开config/index.js,在proxyTable中添写如下代码:

proxyTable: {

'/api': { //使用"/api"来代替"http://aa.com"

target: 'http://aa.com', //源地址

changeOrigin: true, //改变源

secure:false // 是否使用https

pathRewrite: {

'^/api': '/api' //路径重写

}

}

2、使用axios请求数据时直接使用“/api”

getData () {

axios.get('/api/demo.json', function (res) {

console.log(res)

})

以上配置只是在开发环境(dev)中解决跨域。要解决生产环境的跨域问题,则在config/dev.env.js和config/prod.env.js里也就是开发/生产环境下分别配置一下请求的地址API_HOST,开发环境中我们用上面配置的代理地址api,生产环境下用正常的接口地址

module.exports = merge(prodEnv, {

NODE_ENV: '"development"',

API_HOST:"/api/"

})

'use strict'

module.exports = {

NODE_ENV: '"production"',

API_HOST:"http://aa.com"

}

31、Vue首屏加载过慢的解决方法有哪些

vue首屏加载过慢的原因

网速慢肯定会导致首屏加载过慢,但是在这里我们不做讨论

vue项目作为一个单页面应用,如果不对路由进行处理,在加载首页的时候,就会将所有组件全部加载,并向服务器请求数据,这必将拖慢加载速度;

通过查看Network,发现整个网站加载试讲长达10几秒,加载时间最长的就是js、css文件和媒体文件及图片

解决方案

vue-router 路由懒加载

在项目开发中,我们会用到很多第三方库,如果可以按需引入,我们可以只引入自己需要的组件,来减少所占空间,但也会有一些不能按需引入,我们可以采用CDN外部加载,在index.html中从CDN引入组件,去掉其他页面的组件import,

关闭sourcemap,sourcemap是为了方便线上调试用的,因为线上代码都是压缩过的,导致调试极为不便,而有了sourcemap,就等于加了个索引字典,出了问题可以定位到源代码的位置。 但是,这个玩意是每个js都带一个sourcemap,有时sourcemap会很大,拖累了整个项目加载速度,为了节省加载时间,我们将其关闭掉

开启gzip压缩,这个优化是两方面的,前端将文件打包成.gz文件,然后通过nginx的配置,让浏览器直接解析.gz文件。

加个loading效果:首页加个好看的loading阻塞一下,让用户别等的那么心焦。

如果首页真的有瓶颈,可以考虑用node单独做服务端渲染,而下面的子页面仍用spa单页的方式交互。

32、vue如何实现按需加载组件

33、 请说下封装 vue 插件封装过程

34、vue项目的多语言处理

Vue已经有了这个多语种的插件,vue-i18n

35、vue中的watch介绍和场景

监听并处理data属性的更新,对data属性的监听,说明属性是在data中声明过的 属性更新时调用监听函数,可选参数分别为新值和旧值,对属性重新设置值,只要跟原来的值相等就不会触发函数调用,这一点跟计算属性是相似的,

// 基础用法

watch: {

activeTab(newValue, oldValue) {

console.log(newValue, oldValue);

this.getList();

}

}

// 函数体调用Vue实例的方法可简写

watch: {

activeTab: 'getList'

}

属性初始化的值默认不会触发监听,解决办法添加说明immediate:true,表示监听初始值,此时使用handler写法

// 基础用法

watch: {

activeTab(newValue, oldValue) {

console.log(newValue, oldValue);

this.getList();

}

}

// 函数体调用Vue实例的方法可简写

watch: {

activeTab: 'getList'

}

当被监听的属性为对象时,默认不会监听对象内部属性的变化,而是只监听属性被赋值时的变化,解决办法添加说明deep:true(默认为false),此时监听器会深度遍历给对象的每一个属性都带上监听器,更新写法

// 监听对象的所有属性

// 监听对象的所有属性

watch: {

activeTab: {

handler(newValue, oldValue) {

console.log(newValue, oldValue);

this.getList();

},

// 深度监听

deep: true

}

}

// 监听对象的某些属性

watch: {

'activeTab.index': {

handler(newValue, oldValue) {

console.log(newValue, oldValue);

this.getList();

}

}

}

另外组件中的监听器会随组建的注销而注销,不会造成内存溢出,但如果使用命令式的( vm.$watch)全局的监听器需要手动注销才行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值