1. v-if和v-show指令有什么区别?
v-if 是 条件渲染指令,控制的是 组件是否创建(渲染),值为true则渲染该组件,值为false则不渲染该组件,对应Html元素则不会存在于浏览器的html文档中,即 打开浏览器调试工具找不到该组件对应的渲染结果。
v-show控制的是 组件是否可见,并且是 通过css样式的display属性来控制组件的显示与隐藏,所以其值无论是true还是false,对应Html元素都会存在于浏览器的html文档中,即 打开浏览器调试工具都能够找到该组件对应的渲染结果,只不过值为false的时候, 会在该组件上添加style="display: none;";
需要注意的是,在vue组件开发的时候,即 在.vue中使用v-show的时候, 当给8. active-class是哪个组件的属性?
vue-router模块的 router-link组件9. Vue子组件调用父组件的方法?
子组件需要调用父组件的方法,那么可以通过 this.$parent获取到父组件实例,然后就可以调用父组件上的方法了。还有一种方法就是, 子组件向父组件emit一个事件, 父组件在子组件上监听到该事件后,就可以调用父组件上的方法了。10. vue中的 ref 是什么?
ref 被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上,即 类似于给组件或者DOM元素上添加一个标识id,然后通过这个标识id拿到对应的DOM元素或组件实例,如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。11. $route和$router的区别?
$route是" 路由信息对象",包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router是" 路由实例"对象包括了路由的跳转方法,钩子函数等。12. 怎么定义组件?
全局定义:调用Vue的component()方法创建, Vue.component(组件名, {template: 模板字符串})
局部定义:在 创建Vue实例时传递的options对象中的components对象中进行定义,components:{组件名: {template: 模板字符串}}
单文件组件:在 .vue文件中定义,包含template,script,style三部分。13. Vue-cli的src文件夹中有哪些文件?
assets文件夹是放 静态资源;
components是放 组件;
router是定义 路由相关的配置;
view 视图;
app.vue是一个 应用主组件;
main.js是 入口文件14. 对于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 来统一管理。15. vue等单页面应用及其优缺点?
优点:Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件,核心是一个响应的数据绑定系统。MVVM、数据驱动、组件化、轻量、简洁、高效、快速、模块友好。
缺点:不支持低版本的浏览器,最低只支持到IE9;不利于SEO的优化(如果要支持SEO,建议通过服务端来进行渲染组件);第一次加载首页耗时相对长一些;不可以使用浏览器的导航按钮需要自行实现前进、后退。16. 路由的跳转方式?
①router-link标签会渲染为标签,点击该a标签即可跳转到/home路由;
② 另一种是通过js跳转,即通过路由对象this.$router的push()方法进行跳转, 比如 router.push('/home')17. 计算属性(computed)、方法(methods)和侦听属性(watch)的区别与使用场景?
methods VS 计算属性
我们可以将同一函数定义为一个 method 而不是一个计算属性。对于最终的结果,两种方式确实是相同的。
然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
相比而言,只要发生重新渲染,method 调用总会执行该函数。总之,重新计算开销很大的话请选计算属性,不希望有缓存的请选methods。
watch VS 计算属性
当你在模板内使用了复杂逻辑的表达式时,你应当使用计算属性。
侦听属性是一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。
当你有一些数据需要随着其它数据变动而变动时,或者当需要在数据变化时执行异步或开销较大的操作时,你可以使用 watch。18. axios是什么?怎么使用?
axios是 基于Promise的,用于浏览器和nodeJS的http客户端,主要作用就是 向后台发送请求。其存在许多优点:
- 支持Promise
- 支持并发请求
- 提供拦截器
- 浏览器支持防止csrf(跨站请求伪造)
19. axios、fetch、ajax(jquery)的区别?
axios和fetch是基于Promise的,ajax是基于callback的形式。fetch脱离了xhr,是新的语法,默认是不传cookie的, 监听不到请求进度。20. vuex是什么?哪种功能场景使用它?
vuex是一个专门为vue构建的状态机管理机制,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,主要 解决组件间数据共享的问题,其实就是 采用类似全局对象的形式来管理所有组件的公共数据,其强调的是集中式管理,主要是为了便于维护、组件解耦,适合大型项目,有多个视图组件共同依赖一个状态的情况下使用,比如商城系统、外卖系统。
vuex的核心: state、 getters、 mutations、 actions、 modules。21. 说出4个vue当中常用的指令及其用法?
- v-if: 这是一个条件渲染指令,代表存在和销毁,用于控制组件的创建与否;
- v-bind: 这是一个绑定指令,用于绑定属性,可简写为冒号;
- v-on: 这是一个监听指令,用于监听事件,可简写为@;
- v-for: 这是一个循环指令,用于遍历数组;
22. 导航钩子有哪些?它们有哪些参数?
导航主要有三类钩子: 全局级路由钩子、 路由级路由钩子、 组件级路由钩子。主要参数有to(目标路由对象)、from(当前路由对象)、next(是一个函数,用于控制是否放行,即是否能通过当前守卫)。
- 全局级路由钩子: beforeEach和afterEach,每次路由跳转全局路由钩子都会执行,beforeEach(to, from, next)钩子有三个参数,但是afterEach是已经跳转结束了,所以其没有next参数,afterEach(to, from),全局路由钩子由router对象调用。
- 路由级路由钩子: 路由级钩子只有一个即beforeEnter,其是在配置路由表的时候配置,也是有to、from、next三个参数,只有进入该路由的时候才会执行,如果是动态路由之间的切换,那么则不会触发beforeEnter钩子,因为是同一个路由,只是参数不一样。
- 组件级路由钩子: beforeRouteEnter(路由进入该组件的时候执行)、beforeRouteUpdate(动态路由切换时候执行)、beforeRouteLeave(路由离开当前组件的时候执行),需要注意的是,路由钩子是优先于组件的生命周期的,也就是说路由钩子全部执行完毕之后才会开始组件的生命周期,所以其钩子执行顺序: beforeRouteLeave --> beforeEach --> beforeEnter --> beforeRouteEnter --> afterEach --> beforeCreate --> created --> mounted,beforeRouteUpdate只有动态路由切换的时候才会执行,即/user/1切换到/user/2才会执行。
23. v-model是什么?
v-model主要用于数据的双向绑定,其内部主要完成了两个操作: 通过v-bind绑定value属性值和 监听input事件,并更新数据,如:{{msg}}
24. 什么是路由懒加载?其原理是什么?
所谓路由懒加载,即在项目打包的时候,项目中通常会有多个路由,如果将所有路由对应的组件都打包到一个文件中,那么最终打包的文件就会变得非常大,会影响页面的加载性能,如果我们能把不同路由对应的组件 分割成不同的代码块,然后 当路由被访问的时候才异步加载出对应组件,这样就会变得更加高效。
所以其原理就是利用了 webpack的代码分割(按需加载)机制和 vue的异步组件功能,代码被分割后就会变成一个单独的文件,所以 路由被访问的时候需要向服务器发起请求加载该组件,这是一个 异步的过程,所以需要使用到vue的异步组件机制。异步组件?
异步组件,就是在注册组件的时候, 传入一个函数,然后这个函数返回一个Promise对象, resolve的值为这个组件对象,如:export default new Router({ routes: [ { path: '/about', name: 'about', component: () => { // 注册为一个异步组件 const About = require("./views/About.vue"); return Promise.resolve(About); } } ] });
或者在注册异步组件的时候传入resolve和reject,如:
export default new Router({ routes: [ { path: '/about', name: 'about', component: (resolve, reject) => { // 注册为一个异步组件 const About = require("./views/About.vue"); resolve(About); } } ] });
webpack提供的import()函数会返回一个Promise对象,并且会对引入的组件进行代码分割,所以可以通过import()同时实现代码分割和组件异步加载,即路由懒加载,如:
export default new Router({ routes: [ { path: '/about', name: 'about', component: () => import('./views/About.vue') // 等价于注册异步组件并返回一个Promise对象,分割代码的同时进行异步加载 } ] });
25. 用过插槽吗?用过哪些类型的插槽?
插槽其实就是 组件中提供的占位符,所以 插槽占位符在组件中使用,插槽有三种: 匿名插槽、 具名插槽、 作用域插槽。
- 匿名插槽:即没有名字的插槽,即
,使用组件的时候会将组件中的innerHTML插入到 位置上,相当于动态向组件内部传递数据。 // About.vue组件
// 使用About组件hello world
- 具名插槽: 即有名字的插槽,需要在
标签上添加一个name属性,指定 ,即的名称 ,同时使用组件的时候需要给其中的innerHTML添加slot属性,属性值为 的name属性值,如: // About.vue组件
// 使用About组件header
- 作用域插槽: 作用域插槽可以理解为组件向外输出数据,我们可以在组件的
标签上添加上一些属性,然后其中的属性值可以传到组件外使用,会将slot标签上的所以属性合并到一个对象对外输出,组件外通过slot-scope指定一个变量名来接收这个对象,如: // About.vue组件
// 使用About组件{{innerData.msg}} {{innerData.foo}}
26. 什么是vue-loader?
vue-loader就是 .vue组件的加载器, 可以将.vue组件转换为javascript模块,及 动态渲染一些数据,同时vue-loader还对.vue组件中的三个标签都进行了相应的优化。 标签中可以使用src属性引入一个组件,引入的组件可以直接使用当前组件中的数据,27. Vue中keep-alive 的作用以及用法?
keep-alive是vue中一个内置的组件,主要用于 缓存组件,其会在组件created的时候,将需要缓存的组件放到缓存中,然后再render的时候再根据name进行取出。主要配合路由进行使用,在配置路由的时候添加上meta元数据对象,里面添加上keepAlive属性,表示是否缓存该组件,然后将 放到 中,router-view通过v-if指令,从路由配置上的meta对象中取出keepAlive的值进行判断是否需要缓存,如:
// 路由配置
export default new Router({ routes: [ { path: '/', name: 'home', component: Home, meta: { keepAlive: true } }, { path: '/about', name: 'about', component: About, meta: { keepAlive: false } } ] });
组件缓存后就不会执行组件的beforeCreate、created和beforeMount、mounted钩子了,所以其提供了actived和deactived钩子, actived钩子主要用于承担原来created钩子中获取数据的任务。28. Vue 组件中 data 为什么必须是函数?
因为 组件是可以多次复用的,也就是说 会有多个组件实例同时存在,同时由于 对象是引用数据类型,如果所有组件实例都共用一个data数据对象,那么一个组件对data数据对象进行修改,那么 其他组件实例也会受到影响,所以需要使用函数返回data对象的独立拷贝, 使得每个组件实例都会拥有自己的data数据对象,相互之间独立,不会互相受影响,便于组件维护。29. Vue组件复用时,vue-router如何响应路由参数的变化?
当使用路由参数时,例如从 /user/lucy 导航到 /user/lily, 原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着 组件的生命周期钩子不会再被调用,复用组件时,想对路由参数的变化作出响应的话,有两种方式:
- 监听$route对象数据变化
export default { watch: { '$route': (to, from) =>{ console.log("route change");// 对路由变化作出响应... } } }
- 通过beforeRouteUpdate路由钩子
export default { beforeRouteUpdate(to, from ,next) { console.log("beforeRouteUpdate hook run."); next(); } }
30. 简述Vue的响应式原理?
当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。