前端面试题——Vue篇

1. 关于Vue 的生命周期

答:
	beforeCreated —— 创建前
	created —— 创建后
	beforeMount —— 加载前
	mounted —— 加载后
	beforeUpdate —— 更新前
	updated —— 更新后
	beforeDestroy —— 销毁前
	destroyed —— 销毁后

2. 谈谈你对keep-alive 的理解

答:
	keep-alive是Vue的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁.(概念)
	
	keep-alive是系统自带的一个组件,主要用来缓存组件,避免多次加载相同的组件,减少性能消耗,提高用户体验(作用)
	
	列表页进入详情页,如果在列表页点击的都是相同的 ,详情页就不用请求多次了,直接缓存起来就行了,如果点击的不同,则需要重新请求数据(使用场景)

使用方法一:在App.vue中使用keep-alive标签,表示缓存所有页面

  <div id="app">
  	<keep-alive>
	    <tar-bar></tar-bar>
	    <div class="container">
	      <left-menu></left-menu>
	      <Main />
	    </div>
    </keep-alive>
  </div>

使用方法二:按条件缓存,使用include,exclude判断是否缓存

// 1. 将缓存 name 为 cc 的组件,如果有多个,可用逗号分
  	<keep-alive include='cc'>
      <router-view/>
    </keep-alive>
// 2. 将不缓存 name 为 cc 的组件
	<keep-alive exclude='cc'>
  	  <router-view/>
	</keep-alive>
// 3. 还可使用属性绑定动态判断
	<keep-alive :include='includedComs'>
  	  <router-view/>
	</keep-alive>

使用方法三:在router目录下的index.js中,

	//使用meta:{keepAlive = true },表示需要缓存
 const routes = [
  {
    path:'/',
    component:Home,
    meta:{
        keepalive:true
    }
  },
  {
    path:'/login',
    component:Login
  },
   {
      path:'/edit',
      component:Edit,
      meta:{
          istoken: true
      }
   },
  {
      path:'/home',
      component:Home,
      meta:{
          keepalive:true
      }
  }
// 第二步 在App.vue中进行判断

<div id="app">
    <!--keep-alive 表示页面不会被销毁,即保持页面状态-->
    <keep-alive>
      <router-view v-if="$route.meta.keepalive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepalive"></router-view>
  </div>

Props:

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

3.v-if与v-show 的区别

答: 
	v-show 是通过控制display属性来进行DOM的显示与隐藏,主要用于频繁操作
	v-if 是直接对DOM节点的销毁与销毁,相对于v-show  更加损耗性能
  1. v-show不支持语法,即v-show="false"对template元素来说不起作用。但是此时的template元素支持v-if、v-else-if、v-else、v-for这些指令
  2. v-if切换时候会实时的销毁和重建内部的事件、钩子函数等,v-show只会初始化渲染时候执行,再切换时候不会执行生命后期的过程。

4.v-for 与v-if 的优先级

答: 
	1. vue2中,v-for的优先级高于v-if,把它们放在同一个标签上时,页面每次渲染的时候都会重复的进行判断是十分消耗性能的
	2. 在vue3中,又恰好相反v-if的优先级是高于v-for的,同样vue3也不能把它们两者写在一起,正因为v-if优先于v-for,并且v-if又依赖v-for的数据源,在这个情况下将会出现报错的情况。
	3. .一般我们在处理v-if和v-for连用的场景时我们可采取下列方式:
	  (1) .在循环渲染之前先用filter过滤下不需要的数据,也可以使用computed计算属性进行过滤
	  (2)   .如果需要根据条件渲染单个项,可以将 v-if 放在内层元素上。
	4. 将v-for和v-if写在同层级和v-for中嵌套v-if有什么区别呢?
		- 将 v-if 和 v-for 写在同一层级时,Vue 会在渲染组件时,先根据 v-for 遍历出所有的子元素,并将它们都生成对应的 Virtual DOM,然后再根据 v-if 条件判断是否需要将这些元素渲染出来。如果元素不符合条件,则将它们对应的 Virtual DOM 从渲染队列中移除。
		- 将 v-if 放在内层元素上时,Vue 可以先根据 v-for 遍历出所有的子元素,但只有符合 v-if 条件的子元素会被渲染,不符合条件的子元素不会生成对应的 Virtual DOM。这样可以避免不必要的性能消耗,提高页面渲染速度。

5. ref 是什么?

答:
	ref是一个用于访问组件或DOM元素的属性。通过在元素上使用v-bind指令将ref绑定到组件实例或DOM元素上,就可以使用$refs对象访问它们。
	// 主要获取节点的相关属性
<template>
  <div>
    <input type="text" ref="myInput">
  </div>
</template>

6.nextTick 是什么

	答:nextTick 是将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它
// 原本的情况
<template>
  <div>
    <button @click="testClick()" ref="a">{{msg}}</button>
  </div>
</template>
 
<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg:"原始值",
    }
  },
  methods:{
    testClick(){
      this.msg="修改值";
      console.log(this.$refs.a.innerText);   //this.$refs.a获取指定DOM,输出:原始值
    }
  }
}
</script>
//使用 nextTick 之后
  methods:{
    testClick(){
      this.msg="修改值";
      this.$nextTick(() => {
        console.log(this.$refs.a.innerText);  //输出:修改值
      });
    }
  }

注意:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。

7. scoped原理

  • 什么是scoped?

      	答:1.在vue文件中的style标签上,有一个特殊的属性:scoped
      	   2.当一个style标签拥有scoped属性时,它的CSS样式就只能作用于当前的组件,通过该属性,可以使得组件之间的样式不互相污染。
    
  • scoped 原理

      答:1. 为组件实例生成一个唯一标识,给组件中的每个标签对应的dom元素添加一个标签属性,data-v-xxxx
      	 2.给<style scoped>中的每个选择器的最后一个选择器添加一个属性选择器,原选择器[data-v-xxxx],如:原选择器为.container #id div,则更改后选择器为.container #id div[data-v-xxxx]
    

8.Vue 中如何做样式穿透

样式穿透的写法有三种:>>>、/deep/、::v-deep

' >>> ' 用于原生的css中
/*  用法:  */
div >>> .cla {
color: red;
}
'/deep/'   项目中用到了预处理器 scss 、sass、less 操作符 >>> 可能会因为无法编译而报错 。可以使用 /deep/
注意:vue-cli3以上版本不可以
/*  用法:  */
div /deep/ .cla {
color: red;
}
'::v-deep' 
/*  用法:  */
div ::v-deep .cla {
color: red;
}

9. Vue中组件传值

  • 父子组件传值

    • 父向子传递,通过props传值

    在子组件里定义一个props,即props:[‘msg’],msg可以是对象也可以是基本数据类型

    • 子向父传值

    需要在子组件中使用自定义事件,子组件中使用this.$emit(‘myEvent’) 触发,然后在父组件中使用@myEvent监听

  • 兄弟组件值

    运用自定义事件emit的触发和监听能力,定义一个公共的事件总线eventBus,通过它作为中间桥梁,我们就可以传值给任意组件了。而且通过eventBus的使用,可以加深emit的理解

  • 使用$ref传值

    通过$ref的能力,给子组件定义一个ID,父组件通过这个ID可以直接访问子组件里面的方法和属性

  • 使用依赖注入传给后代子孙曾孙

    父组件通过provide 选项,是给后代组件的提供数据/方法
    然后在任何后代组件里,我们都可以使用 inject 来给当前实例注入父组件的数据/方法

  • 祖传孙 $attrs 以及孙传祖的 $listeners

    $attrs–继承所有的父组件属性(除了 prop 传递的属性、class 和 style ),一般用在子组件的子元素上

    $ listeners属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,你就可以配合 v-on=“$listeners” 将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)

  • $parent

    通过parent可以获父组件实例,然后通过这个实例就可以访问父组件的属性和方法,它还有一个兄弟root,可以获取根组件实

  • sessionStorage传值

    sessionStorage 是浏览器的全局对象,存在它里面的数据会在页面关闭时清除 。运用这个特性,我们可以在所有页面共享一份数据

  • vuex

    状态管理器,详情见官方文档

10.computed、methods、watch 有什么区别

  • computed

    omputed计算属性顾名思义就是通过其他变量计算得来的另一个属性,计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要它们的响应式数据没有发生改变,多次访问 这个数据 计算属性会立即返回之前的计算结果,而不必再次执行函数。(需要有return,主要return中的依赖不会发生改变,不会二次执行computed,有缓存机制)

  • watch

    侦听一个特定的值,当该值变化时执行特定的函数。例如分页组件中,我们可以监听当前页码,当页码变化时执行对应的获取数据的函数。

  • methods

    定义函数,它需要手动调用才能执行,只要发生重新渲染,methods 调用总会执行该函数

watch更擅长一对多:就是主要监听一个可以影响多个数据的数据
computed擅长多对一:主要监听多个数据影响一个数据的数据,一定要return

  • 什么情况下使用:

    (1)数据量大,需要缓存的时候用computed;每次确实需要重新加载,不需要缓存时用methods。
    (2)尽量用computed计算属性来监视数据的变化,因为它本身就这个特性,用watch没有computed“自动”,手动设置使代码变复杂。
    (3)虽然计算属性在大多数情况下是非常适合的,但是在有些情况下我们需要自定义一个watcher,在数据变化时来执行异步操作,这时watch是非常有用的

    tips:
    methods是通过事件驱动来执行函数的是被动的
    watch、computed是当监听的数据发生变化时主动执行这个函数
    watch,可监听同一属性值前后改变的值变化 (可监听数组,对象,字符串

11.props 和 data 的优先级谁更高

	答:
		 props   ==>   methods  ==>  data   ==>  computed   ==>  watch

12.Vuex中有哪些属性

答:5个,分别是State、 Getter、Mutation 、Action、Module
  • state

    state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在 Vue.js 的组件中才能获取你定义的这个对象的状态。

    类似于组件中的data,存放数据

  • getter

    getter 有点类似 Vue.js 的计算属性,当我们需要从 store 的 state中派生出一些状态,那么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter 的返回值会根据它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需要派生状态的值)发生改变的时候才会被重新计算

    类似于组件中的 computed

  • mutation

    更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation 都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state 的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个相应的调用方法:store.commit。

    类似于组件中 methods,可以定义方法 【同步的一些处理方法】

  • action

    action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可以有任何的异步操作。在页面中如果我们要用这个 action,则需要执行 store.dispatch。

    提交mutations的,可以定义方法 【异步的一些处理方法】

  • module

    module 其实只是解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模块,每个模块中拥有自己的 state、mutation、action和 getter

    把以上4个属性再细分,让仓库更好管理

13.Vuex是单向数据流还是双向数据流

答:单向数据流。组件可以使用vuex的值但不可以直接修改值,只能通过调用vuex中的mutations方法修改值

14.Vuex的mutaions和actions 区别

  • mutations

    mutations是用于修改Vuex状态的唯一方法。它们是同步操作,意味着它们必须是纯函数,以确保状态的可预测性。这意味着mutations应该只用于同步操作,例如在响应用户事件时更新状态。它们不应该包含任何异步代码,如API调用

  • actions

    actions用于执行异步操作或包含异步操作的操作序列。它们可以包含任何异步代码,例如API调用或其他异步操作,但不能直接修改状态。相反,它们通过commit触发mutations来间接修改状态

mutations是同步的,actions是异步的

15.Vuex 如何做持久化存储

答:Vuex本身不是持久化存储
  • 使用localstorage
  • 使用插件vuex-persist

16.Vue设置代理

  • 在vue.config.js 文件中配置

    	module.exports = {
    	  devServer: {
    	    proxy: {
    	      '/api': {
    	        target: 'http://api.example.com',
    	        changeOrigin: true,
    	        pathRewrite: {
    	          '^/api': ''
    	        }
    	      }
    	    }
    	  }
    
  • 搭建后端目录

    全局命令: npm install express-generator -g
    进入项目:express --view=ejs server

  • 设置跨域

    -Origin *

16.Vue项目打包上线

  • 在Vue项目根目录下,运行命令npm run buildyarn build 进行打包,打包后会生成一个dist 目录
  • dist 目录的所有文件上传到服务器
  • 在服务器安装Node.js环境,并安装http-server 或者nginx 等Web服务器
  • 配置Web服务器,让它能够访问 dist 目录的文件
  • 启动Web服务器,访问服务器IP地址或者域名即可查看Vue项目的网页

17.Vue的路由模式

路由的模式主要有两种:historyhash
  • 区别:
    1. 表现形态的不同(hash会多一个#)

      history:http://127.0.0.1:8000/about
      hash:http://127.0.0.1:8000/#/about

    2. 跳转请求:

      hash:不会发送请求
      history:http://127.0.0.1:8000/id ===> 会发送请求

    3. 打包后前端自测要使用 hash模式,如果使用 history 会出现空白页。

18. 介绍下SPA以及SPA有什么缺点

  • SPA

    SPA(single-page application) 是单页面Web应用

  • SPA优点:

    1. 无刷新界面,给用户体验原生的应用感觉
    2. 节省原生(android 和 ios)app 开发成本
    3. 提高发布效率,无需每次安装更新包
    4. 容易借助其他知名平台更有利于营销和推广
    5. 符合 web2.0 的趋势
  • SPA缺点:

    1. 效果和性能确实和原生的有较大差距(一个页面加载多个JS)
    2. 各个浏览器的版本兼容性不一样
    3. 业务随着代码量增加而增加,不利于首屏优化
    4. 某些平台对 hash 有偏见,有些甚至不支持 pushstate
    5. 不利于搜索引擎抓取

19. Vue的路径传值

  • 显式 url可以传参

    http://127.0.0.1:8000/about?a=1

    传:this.$router.push({path: '/about', query: {a:1})
    接:this.$route.query.

  • 隐式 url上不显示

    http://127.0.0.1:8000/about?a=1

    传:this.$router.push({name: 'about', params: {a:1}) 通过路由的 name
    接:this.$route.params.a

20. 路由导航守卫有哪些

路由守卫

> 路由守卫,也可以是路由拦截,我们可以通过路由拦截,来判断用户是否登录,该页面用户是否有权限浏览,需要结合meta来实现   
  • 路由守卫导航主要有3种,分别是全局守卫独享守卫组件内守卫
  • 全局守卫 beforeEach
    router.beforeEach((to, from, next)=>{
          if() { next() } else { router.push('/login'); next('/ogin') }
     })
    
  • 独享守卫beforeEnter
    const routes = [
    	{
    		name: 'user',
    		component: User
    		beforeEnter: (to, from) => {
    			
    		}
    	}
    ]
    //beforeEnter: [removeQueryParams, removeHash], 可以接受函数数组,removeQueryParams,removeHash为自定义的函数
    
    
  • 组件内守卫beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

    beforeRouteEnter: 组件对应路由被验证前调用,不能获取组件实例this
    beforeRouteUpdate:在当前组件路由改变时,但是组件本身被复用时调用。可以访问this。
    beforeRouteLeave:在导航离开当前组件路由时调用,可以访问this

都是有两个参数:
(to, from, next)=>{}
to:进入到哪个路由去,from:从哪个路由离开,next:函数,决定是否展示你要看到的路由页面。

使用场景:判断是否登录,如果登录就next否则就跳转到登录页面。

21. Vue的动态路由

答:
	场景:详情页
    比如:路由的路径上加一个  /:id   就把这个id作为一个动态的变化。

22.双向绑定原理

答:
vue数据的双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。其核心就是通过Object.defineProperty()方法设置set和get函数来实现数据的劫持,在数据变化时发布消息给订阅者,触发相应的监听回调。也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;

23. 什么是虚拟DOM

  • 虚拟DOM

    虚拟DOM的概念是通过状态生成一个虚拟节点树,然后使用虚拟节点树进行渲染。在渲染之前,会使用新生成的虚拟节点和上一次生成的虚拟节点进行对比,只渲染不同的部分

  • vue中的虚拟DOM

    1. vue中状态变化时,只能通知到组件,组件内部的变化需要通过虚拟DOM去进行比对与渲染
    2. 在vue中,我们使用模板来描述状态与DOM之间的映射关系。vue通过编译将模板转换成渲染函数,执行渲染函数就可以得到一个虚拟节点树,使用虚拟节点数就可以渲染页面
    3. 虚拟DOM在vue中主要提供与真实节点对应的虚拟节点vnode,然后需要将vnode和oldVnode进行比对,然后更新视图,对比两个虚拟节点的算法是patch算法

24. diff 算法

diff算法是一种通过同层的树节点进行比较的高效算法
diff算法的目的就是找出新旧不同虚拟DOM之间的差异,使最小化的更新视图,所以 diff 算法本质上就是比较两个js对象的差异

  • 特点:
    1. 比较只会在同层级进行,不会跨层级比较
    2. 在diff比较的构成中,循环从两边向中间比较

25. 讲一下MVVM

  • 什么是MVVM

    MVVM从字面意思来理解就是划分为 View model VIewModel 三个部分,分别表达了View(视图)、Model(数据)、ViewModel(负责两者之间的数据处理操作)。这就类似于Mvc框架中的Model层、View层、congtroller层,MVVM的本质就是MVC的升级版,更好的应用于前端开发。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值