前端面试VUE

Webpack面试题

webpack打包原理、基本功能、构建过程

打包原理

将所有的依赖打包成一个bundle.js,通过代码分割成单元片段按需加载

基本功能

  • 代码转换:将ts转js,scss转css,
  • 文件优化:压缩js、css、html,代码,合并图片
  • 代码分割:提取多个页面的公共代码,提取首屏不需要执行的部分代码,让其异步加载
  • 模块合并:采用模块化的项目中,有很多模块很文件,需要构建功能吧模块分类合并成为一个文件
  • 自动刷新:坚挺本地源代码的变化,自动构建、刷新浏览器
  • 代码校验:代码提交到仓库前,检测代码是否符合规范,以及单元检测是否通过
  • 自动发布:更新完成代码后,自动构建出线上发布代码传输给发布系统

构建过程

  • 从entry里面配置的module开始递归解析entry依赖的所有module
  • 没找到一个module,就会根据配置的loader去找对应的规则
  • 对module进行转换,解析出当前module依赖的module
  • 这鞋模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk
  • 最后webpack会把所有的Chunk转换成文件输出

⚠️webpack会在恰当的时候执行plugin里的逻辑

常见loader

  • file-loader: 把文件输出到文件夹中
  • url-loader: 和file-loader类似,能在文件小的情况下以base64的方式把文件注入到代码中去
  • source-map-loader:加载额外的source map 文件,方便断掉调试
  • image- loader:加载并压缩图片文件
  • css-loader:加载css,支持模块化、压缩、文件导入等
  • style-loader:把css代码注入到js中,通过DOM操作去加载css
  • eslint-loader:通过eslint检查js代码
  • babel-loader:将ES5转为ES6

常见plugin

  • define-plugin:定义环境变量
  • commons-chunk-plugin:提取公共代码
  • uglifyjs-webpack-plugin:通过uglifyES压缩ES6代码
  • html-webpack-plugin 压缩html
  • clean-webpack-plugin 打包清理元目录文件,webpack打包器清理dist目录

什么是bundle,chunk,module?

  • bundle webpack打包出来的文件,
  • chunk webpack在进行模块的分析时,代码分割出来的代码块
  • module 开发中单个的模块

webpack热更新

  • 使用本地启动本地服务,当浏览器访问资源时对此作出响应,
  • 服务端和客户端使用websocket连接,
  • webpack监听原文件的变化,当文件保存时触发webpack的重新编译
    • 每次编译都会生成一个hash值,已改动的JSON文件,已改动的模块化代码
    • 编译完成后,通过websocket像客户端推送当前编译的hash戳
  • 客户端的websocket监听的文件改动推送来的hash戳,会和上一次做对比,
    • 一致则缓存
    • 不一致则通过ajax或jsonp向服务端获取最新的资源
  • 使用内存文件系统去掉患有修改的内容实现局部刷新

VUE面试题

MVC、MVP、MVVM的理解

MVC:model(模型)、view(视图)、controller(控制器);处理逻辑:view触发事件,controller响应并处理逻辑,调用model,model处理完成后发送给view;

MVP:model、view、present(发布层)理想模型,present为核心,从model获取数据,填充到view;

MVVM:model、view、VM(viewModel);view与VM保持同步,view绑定到VM的属性上,如果VM的数据变化,通过数据绑定的方式,view会自动更新视图,VM也会暴露在Model中,VM也就是new的Vue实例;

VUE生命周期函数

1)创建阶段

  • beforCreate:实例创建前,

  • created:实例创建好,data和methods创建好,可做数据请求;

2)挂载阶段

  • beforMount:DOM已经存在,
  • mounted:模版中的HTML渲染在页面中,可做Ajax请求,mounted只会执行一次;

3)更新

  • beforeUpdate:发生在数据更新之前,
  • undated:更新后,大多数情况应该避免此期间更改状态,因为这可能导致更新的无限循环。该钩子在服务器端渲染是不会被调用的

4)销毁

  • beforDestory:在此清楚定时器和绑定的事件;

  • destoryed:调用后所有事件监听器会被移除,所有的子实例也会被销毁

VUE路由

vue-router

vue的插件,含有router-link router-view 组件,

  • router-link:<router-link to="路由地址" tag="渲染为什么标签"></router-link>

  • active-class:router-link组件的属性,直接在路由中配置 linkActiveClass:'active',在router-link标签中写入exact<router-link to="" active-class="" exact></router-link>

vue-router的导航钩子

全局的:

  • beforEach.boforEach((to, from, next) => {})
  • afterEach.afterEach((to, from, next)v=>{})

单个路由独享:

  • beforEnter
  • beforLeave

组件的:

  • beforRouterEnter
  • beforRouterUpdate
  • beforRouterLeave
$router 和 $route区别
  • router为vue-router的实例,相当于一个全局路由器对象,包含很多对象和属性。

  • route相当于正在跳转的路由对象,可以从中获取参数

vue-router 传参
  • params方式传参

    // 传参
    this.$router.psuh({
      name: '',
      params: {
        id: id
      }
    });
    // 获取
    this.$route.params.id
    
  • query方式传参

// 传参
this.$router.psuh({
  path: '',
  query: {
    id: id
  }
});
// 获取
this.$route.query.id

⚠️query相当于get,参数会拼接在url上,params相当于post

vue-router的两种模式(hash history)
  • hash模式

    原理是window.onhashchange事件,hash值就是#后面的值

  • history模式

    H5中History Interface 中新增的pushState()和replaceState()方法,需要后端配置支持,没有正确配置访问时就会返回404,丢弃了不好看的#,但是如果服务器没有正确的响应或资源,就会出现404,所以history不怕前进后端,就怕刷新

vue-router实现路由懒加载

为了好的用户体验,首屏组件加载更快,解决白屏问题,将页面划分为需要的时候再加载,减少首页加载压力。

常用的懒加载方法:

  • ES提出的import 方法(最常用)

    const 路由组件名 = () => import(需要加载的模块地址)

    const Holle = () => import('@...')

  • VUE异步组件实现

    component: resolve => (require(['需要加载的路由地址']), resolve)

    routes: [
    	{
    		path: '/',
    		name: 'Holle',
    		component: resolve => (require(["@/component/HelloWord"], resolve))
    	}
    ]
    

VUE 组件传值

  • 父组件传值给子组件

    使用props

    • props为数组,直接传递[data, flag]
    • props为对象,直接对象类型或者给一个默认值
  • 子组件传值给父组件

    • 子组件使用this.$emit('自定义事件名', 参数)

    • 父组件<parent-component @自定义事件="方法"></parent-component>,此时方法不能加()。传值为子组件传的值

  • 兄弟组件传值

    • 中央事件总线,eventBus
    const bus = new Vue();
    bus.$emit(自定义事件名, 传递的数据);
    // 接收数据的地方
    bus.$on(自定义事件名, function (val) {})
    
    • 使用VueX
  • 父组件访问子组件中的方法

    组件上添加ref属性,给组件设置一个ID,然后通过this.$ref.id名.方法/值

  • 使用依赖注入

    父组件通过provide(函数)注入,所有的子组件通过inject(数组)引用,

    // 父组件
    provide: function () {
      return { 
        getName: this.getName
      }
    }
    // 子组件
    inject: ['getName']
    
  • p a r e n t , t h i s . parent,this. parent,this.parent 可以直接访问到组件上的data数据和方法

  • sessionStorage传值

vue中computed和watch、method区别

  • methods: 定义function的区域
  • computed: 一定程度和methods差不多,不过计算属性基于属性的,属性的变化跟着变化,不变化就不会调用computed;具有getset两个方法
  • watch: 侦听属性。监听某个值的变化,
    • 回调handler(newVal, oldVal),
    • deep: true ; 深度监听
    • Immediate: true;立即执行,场景:组件创建的时候立即获取一次列表数据,同时监听框,每当发生变化的时候重新获取一次筛选后的数据列表

VUE双向数据绑定的原理

Vue 采用数据劫持 + 发布订阅模式。通过Object.defineProperty()方法为组件中每个data添加getset方法

原理:通过Object.defineProperty()劫持各个属性中的getter、setter,在数据变化时,发布消息给订阅者,触发相应的监听回调来渲染视图

  • 需要Observer(观察者)对数据对象进行递归遍历,给每个属性都加上getter、setter
  • 模板解析器complie解析模板指令,将模板中每个变量替换为数据,然后初始化渲染页面视图,并给每个指令对应的几点更新函数,添加数据的监听者,一旦数据变化,收到通知,改变视图
  • watcher订阅者,在observer和complie之间做中介,

VUEX

集中组件状态管理

  • state,基本数据
  • getters,从state中派生的数据
  • mutation,跟新store唯一途径,
  • action,提交mutation以改变store
  • module,将store模块化

VUE插槽

<slot></slot>

单向数据流

组件之间的数据传递是具有单向下行绑定的,从父组件流向子组件。是不能在子组件直接改传过来的props的值的。

子组件需要改变传过来的值为自己所用?

  • 定义一个局部变量来接收props传来的值
  • 使用计算属性,修改父组件传来的数据

子组件修改父组件中的数据?

  • 使用async修饰符,他会被扩展为一个自动更新父组件属性的v-on监听器,被移除

    // 父组件
    <Hello :message.async></Hello>
    // 子组件
    props: ['message'],
    methods: {
      change () {
        this.$emit('update.message', 修改的值)
      }
    }
    
  • 将父组件中的数据包装成对象或数组,子组件中直接修改对象的属性。

s e t 、 set、 setforceUpdate?

data数据为数组或者对象的时候,直接给某个对象添加属性,页面识别不到。

  • 使用this.$forceUpdate 强制刷新;
  • 使用this.$set 设置对象的值

JS面试题

面向对象

把事物分解成为一个个对象,然后对对象之间的分工合作。分析出对象只能够的属性和方法,按照步骤编程器。

浏览器缓存

  • 强缓存

    • expires

      请求头设置时间,

    • cache-control

  • 协商缓存

虚拟列表

前端处理数据,防止页面卡顿,根据显示窗口计算出现实条数,然后头部和底部使用空白(padding-top,padding-bottom)填充滚动区域

事件委托的原理

通过冒泡,e.target来判断是谁触发

判断数组的方法?

  • instanceof,用法arr instanceof Array

    主要是判断某个实例是否属于某个对象

  • constructor, 用法arr.constoructor === Array

    Object的每个实例都有构造函数constructor,用于保存创建当前对象的函数

  • Array.isArray()

  • Array原型链上的isPrototypeOf,Array.prototype.isPrototypeOf(arr)

  • Object.getPrototypeOf, 用法Object.getPrototypeOf(arr) === Array.proptotype

  • Object.prototype.toString(),用法Object.prototype.toString.call(arr) === 'object Array'

判断对象的方法?

  • toString,

    Object.prototype.toString.call(obj) === '[object Object]'

  • constructor

    obj.constructor === Object

  • instanceof

    obj instanceof Object

  • typeof 不是很准确

    typeof obj === Object

数组去重

  • 使用indexOf,

    function unique (arr) {
    	let brr = [];
    	
    	for (let i = 0; i < arr.length; i++) {
    		let item = arr[i];
    		if (brr.indexOf(item) === -1) {
    			brr.push(item)
    		}
    	}
    	
    	return brr;
    }
    
  • set

    // 一:
    let arr = [...new Set(arr)]
    // 二
    function unique (arr) {
      return Array.from(new Set(arr))
    }
    
  • Map

    function unique (arr) {
    	const res = new Map();
    	
    	return arr.filter((a) => !res.has(a) && res.set(a, 1))
    }
    

事件循环

同步完成后执行异步程序,

顺序:同步——异步——process.nextTick——异步——setImmediate(当前事件循环后执行)

同步代码放入运行栈,异步放入任务队列中,

事件循环就是检查任务队列中是否有任务等待执行,

宏任务、微任务

微任务:promise.then、Object.observe、MutationObser

宏任务:script(整体代码)、setTimeout、setInterval、I/O、UI Rendering、计时器、ajax、读取文件

优先级:process.nextTick > promise.then > setTimeout > setImmediate

顺序:

1、同步程序

2、process.nextTick

3、微任务

4、宏任务

5、setImmediate

process.nextTick

同步执行完成后异步开始之前执行

setImmediate

异步完成之后在执行

函数截流函数防抖

函数截流:一定时间内只执行一次

function throttle (fn, threshold, scope) {
  let timer;
  return function () {
    let context = scope || this, args = angument;
    if (!timer) {
      timer = setTimeout(function () {
        fn.apply(context, args)
      }, threshold)
    }
  }
}

函数防抖:一定的事件操作,只执行最后一次操作

function debounce (fn, delay, scope) {
  let timer = null;
  
  return function () {
    let context = scope || this, args = arguments;
    
    clearTimeout(timer);
    timer = setTimeout(function () {
      fn.apply(context, args);
    }, delay)
  }
}

New 关键字做了什么

创建了一个对象,将构造函数的this指向创建出来的对象

promise、async

promise的原理就是发布订阅模式,通过两个队列缓存的成功回调(onResolve)和失败的回调(onReject)。promise的状态有三种,pending、rejected、fulfilled,状态改变只能是pending --> fulfilled 或者 pending --> rejected。

链式调用

then中创建的promise,。当一个promise的状态被fulfilled的之后,会还行回调函数,回调函数返回的结果会被当作value,返回给下一个Promise(then中的promise),下一个promise也会被改变(执行resolve或reject),然后又执行其回调,以此类推,就形成了链式

前端优化

重绘和回流(重排)

回流: 重新布局当元素的规模尺寸、布局、隐藏等改变而需要重新构建页面。

重绘: 一些属性的更新,影响元素的外观,风格但是不会影响布局。如background-color

回流一定会重绘,重绘不一定回流

解决方案:

  • 将需要多次重排的元素,position设置为absolute或者fixed,脱离文档流,不会影响其他元素的布局。

深拷贝浅拷贝

Object.assign()只能实现一维对象的深拷贝

垃圾回收

  • 引用计数:声明一个变量时,给他赋值时就引用计数1次,去另一个值时,就计数减去1,为0 的就清除;

    注意:遇到循环调用的,会形成引用次数永远为2

  • 标记清除:运行时,垃圾回收器给所有的变量加标记,进入环境的时候加标记,出去的时候去掉

跨域问题

同原策略:域名、协议、端口

  • cors资源共享跨域

    后台加上相应头来允许域请求

  • Jsonp跨域

  • document.domin,(iframe和cookie跨域)

    处理Cookie和iframe,两个二级域名不一致的,通过共享cookie

  • 通过websocket进行跨域,同源策略对其不生效

  • 图片ping

instanceof 、typeof、constructor区别

  • instaceof,检测狗站函数的prototype属性是否出现在某个实例对象的原型上
  • typeof,只能检测简单数据类型,不能应用于复杂数据类型
  • constructor,每一个js函数都有一个原型对象,原型对象里有一个constructor指向属性的构造器(fn)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值