前端面试题vue

1. Vue的双向数据绑定原理是什么?

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

具体步骤:

第一步:需要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生命周期的理解

答案:
总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

创建前/后: 在beforeCreated阶段,vue实例的挂载元素 e l d a t a u n d e f i n e d c r e a t e d v u e d a t a el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了, el还没有。

载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。

更新前/后:当data变化时,会触发beforeUpdate和updated方法。

销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在

3. 封装 vue 组件的过程

答案:
首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。

然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

4. mvc与mvvm

答案:
MVC
模型-视图-控制器(Model-View-Controller)
Model和View永远不能相互通信,只能通过Controller传递。
Controller可以直接与Model对话(读写调用Model),Model通过Notification和KVO机制与Controller间接通信。
Controller可以直接与View对话,通过outlet,直接操作View,outlet直接对应到View中的控件,View通过action向Controller报告事件的发生(如用户Touch我了)。Controller是View的直接数据源(数据很可能是Controller从Model中取得并经过加工了)。Controller是View的代理(delegate),以同步View与Controller。
MVVM
Model -ViewModel - View
什么是 MVVM:一个 MVC 的增强版,我们正式连接了视图和控制器,并将表示逻辑从 Controller 移出放到一个新的对象里,即 View Model。MVVM 听起来很复杂,但它本质上就是一个精心优化的 MVC 架构
Model层是少不了的了,我们得有东西充当DTO(数据传输对象),当然,用字典也是可以的,编程么,要灵活一些。Model层是比较薄的一层,如果学过Java的小伙伴的话,对JavaBean应该不陌生吧。
ViewModel层,就是View和Model层的粘合剂,他是一个放置用户输入验证逻辑,视图显示逻辑,发起网络请求和其他各种各样的代码的极好的地方。说白了,就是把原来ViewController层的业务逻辑和页面逻辑等剥离出来放到ViewModel层。
View层,就是ViewController层,他的任务就是从ViewModel层获取数据,然后显示。

5. Vue首屏加载非常慢,如何解决?

答案:
Vue首屏加载非常慢
原因: 当打包应用时,将所有JavaScript代码打包在一个文件中,导致js代码非常庞大,严重影响页面加载速度。
解决:

  1. 配置打包工具,将组件分别打包到不同的js代码块中
 build/webpack.base.conf.js
   output:{
     path: config.build.assetsRoot,
	  filename:[name].js’,
     //新增
chunkFilename:[name].js”,
publicPath: process.env.NODE_ENV===”production”
  ?config.build.assetsPublicPath
  :config.dev.assetsPublicPath
}
  1. 当路由请求到该组件时,才动态加载组件的内容
    路由字典中,路由配置和以前完全一样
    但是在引入组件对象时:
  import Index from ‘@/views/Index.vue’
  改为
  const Index=()=>import(‘@/views/Index.vue’)//仅定义函数
                                       //暂未执行
                                //暂时不引入Index.vue

当用户在vue中请求当前组件对应的路由地址时,由vue-router自动调用加载函数,动态请求Index.vue组件对象

6. 实现订阅/发布者模式?

答案:
	var ublisher = {};
// 定义发布者
publisher.list =[];
// 缓存列表 存放订阅者回调函数
// 增加订阅者
publisher.listen =function(fn){
    publisher.list.push(fn);
// 订阅消息添加到缓存列表
}
// 发布消息
publisher.trigger =function(){    
for(vari = 0,fn; fn = this.list[i++];){
        var that =this
    	fn.apply(null,arguments);
}
}

7. 什么是虚拟DOM树:

答案:
什么是: 仅包含可能变化的节点和可能变化的属性的树结构

 <body>
<div id=”app”>
     <img src=”logo.png”> alt  title id  ….
     <h1>{{uname}}</h1>id   class     title    name
     <hr>
     <h2>{{score}}</h2>
   </div>
{
  el:”#app”,
  children:[
{el:”h1”, innerText:uname},
{el:”h2”,innerText:score}
]
}

为什么: 内容少,便于快速遍历比较不同
如何发挥作用:
当data中模型变量改变时,会通知虚拟DOM树
虚拟DOM树先缓存本次的修改在元素对象上
将一批修改生成新的DOM子树和原虚拟DOM树做对比。
一旦发现不同的元素或内容,就只更新有修改的元素
虚拟DOM树中,封装了传统DOM API: createElement() appendChild() .innerHTML,避免了程序员编写大量重复的代码。

8. Vue 如何去除url中的

答案:
vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history
new Router({
  mode: 'history',
  routes: [ ]
})

需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面

9. Vue组件间如何通信:

答案:
组件通信
父组件向子组件通信

子组件通过 props 属性,绑定父组件数据,实现双方通信

子组件向父组件通信

将父组件的事件在子组件中通过 $emit 触发

非父子组件、兄弟组件之间的数据传递

/*新建一个Vue实例作为中央事件总嫌*/
let event = new Vue();

/*监听事件*/
event.$on('eventName', (val) => {
    //......do something
});

/*触发事件*/
event.$emit('eventName', 'this is a message.')

猜你喜欢

转载自blog.csdn.net/AyayaOVO/article/details/106954172