欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

web面试题必问的题

程序员文章站 2022-06-24 10:36:52
vue双向数据绑定原理vue是采用数据劫持结合发布-订阅的方式,通过object.defineProperty()来劫持各个属性的setter,getter,在数据发生变动时发布消息给订阅者,触发相应的监听回调来渲染视图第一步:需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上setter,getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据变化简单来说就是实现一个数据监听器Observer,它能够对数据对象的所以属性进行监听,如果有变动.....

1. vue双向数据绑定原理

vue是采用数据劫持结合发布-订阅的方式,通过object.defineProperty()来劫持各个属性的setter,getter,在数据发生变动时发布消息给订阅者,触发相应的监听回调来渲染视图
第一步:
需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上setter,getter,这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到数据变化
简单来说就是实现一个数据监听器Observer,它能够对数据对象的所以属性进行监听,如果有变动就可以拿到最新的值并通知订阅者

第二步:
compile解析模块指令,讲模块中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
简单来说就是实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,替换数据,绑定更新函数
第三步:
Watcher订阅者时ObserverCompile之间的通讯桥梁,主要做的事情是:
1.在自身实例化时往属性订阅器(dep)里面添加自己
2.自身必须有一个update()方法
3.待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中的绑定回调
简单来说就是实现一个Watcher,作为Observer和Compile的桥梁,能够收到每个属性变动的通知,绑定相应的回调函数,从而更新视图
第四步:
MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭建起Observer和Compile之间的通信桥梁,达到数据变化->视图更新; 视图交互变化->数据model变更的双向绑定效果

MVVM就是实现Vue双向数据绑定的根本,MVVM本质上是MVC的改进版,即模型-视图-视图模型,【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】MVVM的核心,他是连接view和model的桥梁。它有两个方向: 一个是将【模型】转换成【视图】,即后端传递的数据转换成所看到的页面:实现方式是:数据绑定。第二个是【视图】转化成【模型】,即将所看到的页面转换成后端的数据:实现方式是:DOM事件监听。这两个方向都实现的话,我们称之为数据的双向绑定

2.vue虚拟dom,diff算法

虚拟DOM就是为了解决游览器性能问题而被设计出来的。

就是用对象来模拟dom元素和嵌套关系,指的就是用js对象的形式,来模拟页面上的DOM嵌套关系

目的:实现页面元素的高效更新,避免大量无谓的计算(若一次操作中有10次更新DOM的动作,虚拟DOM不会立即去操作DOM,而是将10次更新的diff内容保存到本地一个JS对象中,最终将这个JS对象一个姓attch到DOM树上,再进行后续操作)

作用:用来比较两次DOM结构

web界面由DOM树(树的意思就是数据结构)来搭建,当其中一部分发生变化时,其实就时对应某个DOM节点发生了变化

diff算法是作为DOM的加速器,改进优化了页面渲染的基础和性能保障

用js对象表示dom树结构,用这个树建立一个真正的dom树,插入到文档中,状态更新,重新构造一棵新树,两树比较差异,把差异应用到真的dom树上,更新视图

3. 组件 通讯

1.父传子
父组件是通过props属性给子组件通信的
父组件代码:

<template>
	<div>
		<h2>{{msg}}</h2>
		<Son :faMsg="msg"></Son>
	</div>
</template>
	
 <script>
	import Son from "./Son";
	export default {
		name:"HelloWorld",
		data(){
			return{
				msg:"父组件"
			}
		},
		components:{Son}
	}
 </script>

子组件代码:

<template>
	<div>
		<h2>{{sonMsg}}</h2>
		<p>子组件接收到的内容是:{{faMsg}}</p>
	</div>
</template>
	
 <script>
	export default {
		name:"Son",
		data(){
			return{
				sonMsg:"子组件"
			}
		},
		props:['faMsg'], //接收faMsg值
		//还可以这样,上面的不是很严谨
		props:{
			faMsg:{
				type:String,
				default:"123"
			}
		}
	}
 </script>

在父组件中给子组件标签上绑定一个属性, 属性上挂载需要传递的值
在子组件通过props:[“自定义属性名”]来接收数据

子传父:
(1) 在父组件中给子组件标签绑定一个自定义事件,给这个事件挂载需要调用的方法
(2) 在子组件的方法通过this.$emit(‘自定义事件名’)来调用这个方法

父组件代码:

<template>
   <div>
     <h2>{{ msg }}</h2>
     <p>父组件接手到的内容:{{ username }}</p>
     <son psMsg="我是你爸爸" @transfer="getUser"></son> 
      <!-- 监听子组件触发的transfer事件,然后调用getUser方法 -->
   </div>
 </template>
 <script>
 import son from './Son'
 export default {
   name: 'HelloWorld',
   data () {
     return {
       msg: '父组件',
       username:'',
     }
   },
   components:{son},
   methods:{
     getUser(msg){
       this.username= msg
     }
   }
 }
 </script>

子组件代码:

	 <template>
   <div class="son">
     <p>{{ sonMsg }}</p>
     <p>子组件接收到内容:{{ psMsg }}</p>
     <!--<input type="text" v-model="user" @change="setUser">-->
     <button @click="setUser">传值</button>
   </div>
 </template>
 <script>
 export default {
   name: "son",
   data(){
     return {
       sonMsg:'子组件',
       user:'子传父的内容'
     }
   },
   props:['psMsg'],
   methods:{
     setUser:function(){
       this.$emit('transfer',this.user)//触发transfer方法,this.user 为向父组件传递的数据
     }
   }
 }
 </script>

兄弟通信: 比如说vuex 就可以说是一个兄弟通信

4. vuex

首先我们要知道Vuex是一个专为vue.js应用程序开发的状态管理模式,它由五部分组成:
分别是:state,actions,mutations,getters,modules
web面试题必问的题
vuex的五部分分别是:

  • state:存储状态
  • actions:可以包含异步操作
  • getters:类似vue组件中的计算属性,会对state数据进行计算(会被缓存)
  • mutations:唯一可以对state数据修改的场所
  • modules:模块化管理仓库,每个模块都拥有自己的 state,actions,mutations,getters,modules

Vuex一般用来存储在vue.js中大量出现的数据,比如说token,我们就可以把token存放在Vuex中,当然购物车也是要用到Vuex的.

数据持久化
问题:存储在vuex中的状态,刷新页面会丢失。
为了解决刷新页面数据丢失,才有了数据持久化。
最简单的做法就是利用插件 vuex-persistedState
1.安装
cnpm i vuex-persistedState -S
备注:
-S 是 --save的简写,意思是:把插件安装到dependencies(生成环境依赖)中
-D 是 --save-dev的简写,意思是:把插件安装到devDependencies(开发环境依赖)中
2.使用

import createPersistedState from 'vuex-persistedstate'

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters,
  plugins: [createPersistedState({
    storage: sessionStorage,
    key: "token"
  })]//会自动保存创建的状态。刷新还在
})

参数:
storage:存储方式。(sessionStorage,localStarage) key:定义本地存储中的key

模块化管理数据(modules)
1.什么时候需要用到模块管理vuex数据

项目庞大,数据信息量特别大的时候,我们可以考虑分模块形式管理数据,比如user模块管理用户信息数据,cart模块管理购物车数据,shop模块管理商品信息数据

5. vue-router(路由原理,路由守卫,路由传参)

路由实现原理:

概念:
通过改变URL,在不重新请求页面的情况下,更新页面视图。
实现方式:
vue-router通过hashHistory interface两种方式实现前端路由,更新视图但不重新请求页面”是前端路由原理的核心之一,目前在浏览器环境中这一功能的实现主要有两种方式:
1.hash ---- 利用URL中的hash(’#’);
2.利用History interface在HTML5中的新增方法

6. vue生命周期

简单粗暴:
答: 总共分为8个阶段。创建前/后 , 挂载前/后 , 更新前/后 , 销毁前/后
创建前/后: beforeCreated创建前,vue实例的挂载元素$el和数据对象data都是undefined,还未初始化。在created阶段/创建后,vue实例的数据对象data有了,$el还没有。
挂载前/后: beforeMount挂载前,vue实例的eldata都初始化了,但是还没有挂载html 到页面上。在Mounted阶段/挂载后,模板中的 HTML 渲染到 HTML 页面中,此时一般可以做一些 ajax 操作,mounted 只会执行一次。
更新前/后: 当data变化时,会触发beforeUpdateupdated方法
销毁前/后:destroy阶段/销毁前,对data的改变不会再触发周期函数,说明此时vue实列已经解除了事件监听和dom绑定,但是dom结构依然存在。destroyed阶段,组件销毁
web面试题必问的题

7. 自定义指令,自定义过滤器

8. 自定义组件

9. 常用的指令,修饰符

10. vue2.0和vue3.0的区别

11. keep-alive

概念:
是Vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
keep-alive是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现的父组件链中。
作用:
在组件切换的过程中,把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载事件以及性能消耗,提高用户体验性
原理:
created钩子函数调用时将需要缓存的 VNode 节点保存在 this.cache 中/在 render(页面渲染) 时,如果VNodename 符合缓存条件(可以用 include 以及 exclude 控制),则会从 this.cache 中取出之前缓存的 VNode实例进行渲染
VNode: 虚拟DOM,其实就是一个JS对象
参数:

  • include - 字符串或者正则表达式。只有匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。然后匹配的组件都不会缓存。
  • max - 数字。最多可以缓存多少组件实例

对生命周期函数变化:
被包含在keep-alive中的组件,会多出来两个生命周期的钩子函数,activateddeactiveated
1.activated
在keep-alive组件激活时调用
2.deactivated
在keep-alive组件离开时调用

//正常的生命周期:beforeRouterEnter --> created -->mounted --> updated --> destroyed


//使用keepAlive后生命周期:
//首次进入缓存页面 :beforeRouterEnter --> created -->mounted --> updated --> destroyed
//再次进入缓存页面 :beforeRouteEnter --> activated --> deactivated
//注:
//1、这里的activated非常有用,因为页面被缓存时,created,mounted等生命周期均失效,你若想进行一些操作,那么可以在activated内完成(下面会举个栗子:列表页回到上次浏览位置)
//2、activated   keep-alive组件激活时调用,该钩子在服务器端渲染期间不被调用。 
//3、deactivated   keep-alive组件停用时调用,该钩子在服务端渲染期间不被调用

可以结合Router中的meta,来缓存部分页面

12. 多环境变量

13. 对axios封装,(url统一管理,axios请求拦截,响应拦截,函数封装)

14. element-ui,vant-ui 按需引入

15. sass配置

16. rem , vw/vh 适配

rem适配:
使用vant里面的游览器适配,
Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具:

postcss-pxtorem 是一款 postcss 插件,用于将单位转化为 rem
lib-flexible用于设置 rem 基准值
安装 lib-flexiblepostcss-plugin-px2rem
cnpm i lib-flexible postcss-plugin-px2rem --save-dev
配置rem: mian.js 导入

import 'lib-flexible/flexible'; //rem 就可以生效了

配置px–> rem:创建vue.config.js

//可以在此配置的基础上根据项目需求进行修改。
module.exports = {
   
    css: {
        loaderOptions: {
            postcss: {
                plugins: [
                    require('postcss-plugin-px2rem')({
                        rootValue:75, //换算基数, 默认100  ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。
                        // unitPrecision: 5, //允许REM单位增长到的十进制数字。
                        //propWhiteList: [],  //默认值是一个空数组,这意味着禁用白名单并启用所有属性。
                        // propBlackList: [], //黑名单
                        // exclude: /(page_pc)/i,  //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
                        exclude: /node_modules/i,
                        // selectorBlackList: ['van-'], //要忽略并保留为px的选择器,我们一般不转换vantui中的大小
                        // ignoreIdentifier: false,  //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
                        // replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
                        mediaQuery: false,  //(布尔值)允许在媒体查询中转换px。
                        minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0
                    }),
                ]
            }
        }
    },
}

17. webpack配置(配置跨域,路径别名,打包分析,cdn引入,去掉console.log,单独打包第三方模块,ie兼容,eslint规范,图片压缩)

本文地址:https://blog.csdn.net/GYF_123/article/details/112268866

相关标签: 面试