前端面试题7

1. ### 为何组件的 data 必须是一个函数、
  
  如果不是一个函数,每个组件实例的data都是同一个引用数据,当该组件作为公共组件共享使用,一个地方的data更改,所有的data一起改变,如果data是一个函数,每个实例的data都在闭包中,就不会各自影响了。
  
      【Object是引用数据类型,如果不用function返回,每个组件的data都是内存的同一个地址,一个数据改变了其他也改变了,这就造成了数据污染。如果data是一个函数,每个实例的data都在闭包中,就不会各自影响了】
  

2. ### vue 常用的指令、
  
      ⑴v-bind:给元素绑定属性
      ⑵v-on:给元素绑定事件
      ⑶v-html:给元素绑定数据,且该指令可以解析 html 标签
      ⑷v-text:给元素绑定数据,不解析标签
      ⑸v-model:数据双向绑定
      ⑹v-for:遍历数组
      ⑺v-if:条件渲染指令,动态在 DOM 内添加或删除 DOM 元素
      ⑻v-else:条件渲染指令,必须跟 v-if 成对使用
      ⑼v-else-if:判断多层条件,必须跟 v-if 成对使用
      ⑽v-cloak:解决插值闪烁问题
      ⑾v-once:只渲染元素或组件一次
      ⑿v-pre:跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度
      ⒀v-show:条件渲染指令,将不符合条件的数据隐藏(display:none)
  

3. ### v-if/v-show 区别、
  
  1、 v-if通过创建或删除DOM节点来实现元素的显示隐藏,v-show通过css中的display属性来控制
  
  2、v-if更适合数据的筛选和初始渲染 v-show更适合元素的切换 3、v-if会频繁触发组件生命周期,v-show则不会。
  
      【v-if 有更高的切换消耗,而 v-show 有更高的初始化渲染消耗,一般推荐频繁切换的时候使用 v-show 更好,当我们的判断分支比较多的时候,和首次渲染的时候 使用v-if】
  

4. ### vue 生命周期
  
      beforeCreate() 创建前,这个时候data中的数据,还未定义,所以不能使用
      created()创建后 最早开始使用 data和methods中数据的钩子函数
      
      beforeMount()挂载前 指令已经解析完毕内存中已经生成dom树,但是尚未挂载到页面中去,此时页面还是旧的。
      mounted()挂载后 dom已经渲染完毕,此时页面和内存中都是最新的数据,最早可以操作DOM元素钩子函数
      
       beforeUpdate()更新前 当视图层的数据发生改变会执行这个钩子 内存更新,但是DOM节点还未更新,数据没有与页面同步
       updated()更新后 数据更新完成以后触发的方法,DOM节点已经更新
      
       beforeDestroy()即将销毁 data和methods中的数据此时还是可以使用的,可以做一些释放内存的操作
       destroyed()销毁完毕  组件已经全部销毁,Vue实例已经被销毁,Vue中的任何数据都不可用
      
       其他三个:
      activated  被 keep-alive 缓存的组件激活时调用。
      deactivated 被 keep-alive 缓存的组件停用时调用。
      errorCaptured 2.5.0+ 新增当捕获一个来自子孙组件的错误时被调用
  

5. ### vue 数据双向绑定原理、
  
  是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图, 实现数据和视图同步。
  
  ​
  
  在**vue****3** 中
  
  Vue3是通过Object.define.proxy 对对象进行代理,从而实现数据劫持。使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为 Proxy 是 ES6 的语法
  
6. ### Vue 虚拟 Dom 、vue diff 算法
  
  虚拟dom是用js对象来描述真实的dom,在这个js对象里,体现了真实dom的节点名称,属性名称以及子元素等内容
  
  我们在渲染页面的时候 会对新的虚拟dom和旧的虚拟dom进行对比 只渲染不同的地方,而不再是像之前只要发生变化,全部真实的dom都要重新渲染,所以提高了渲染的效率,vue虚拟dom使用diff算法计算出来的。
  
  **Diff算法**
  
  diff算法就是进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方,最后用patch记录的消息去局部更新Dom。
  
      ##### 【虚拟 DOM,其实就是用对象的方式取代真实的 DOM 操作,把真实的 DOM 操作放在内存当中,在内存中的对象里做模拟操作。当页面打开时浏览器会解析 HTML 元素,构建一颗 DOM 树,将状态全部保存起来,在内存当中模拟我们真实的 DOM 操作,操作完后又会生成一颗 dom 树,两颗 DOM 树进行比较,根据 diff 算法比较两颗 DOM 树不同的地方,只渲染一次不同的地方。
      
      (个人理解)**虚拟dom**他不并不是真实的 dom ,是根据模板生成一个js对象(使用createElement,方法),根据这个js对象再去生成真实的dom,对复杂的文档DOM结构,提供一种方便的工具,进行最小化的DOM操作 ,是可以快速的渲染和高效的更新元素,提高浏览器的性能,
      
      diff 算法是一种通过同层的树节点进行比较的高效算法,比较方式:diff整体策略为:深度优先,同层比较
      当data发生改变 会根据新的数据生成一个新的虚拟dom ,新的虚拟dom和旧的虚拟dom进行对比,这个对比的过程就是diff算法,会找到不同地方,只去渲染不同的地方,总的来说就是减少DOM,重绘和回流。】
  

7. ### vue 组件通信、vuex、watch 深度监听
  
  ###### 1.父传子:
  
  父组件使用v-bind向子组件传递数据,子组件使用props接收父组件传递的数据。
  
  ###### 2.子传父:
  
  父组件使用v-on向子组件绑定自定义事件,子组件使用`$emit`调用父组件传递的函数名字。
  
  ###### 3.兄弟组件传值:
  
  1. 通过main.js初始化一个全局的$bus,在发送事件的一方通过$bus.$emit(“事件名”,传递的参数信息)发送,在接收事件的一方通过$bus.$on("事件名",参数)接收传递的事件
8. 使用同一个父组件作为中间消息传递者实现兄弟通信
  
  ###### 4.$attrs和$listeners
  

如果父组件A下面有子组件B,组件B下面有组件C,这个时候A组件想要传数据给C组件就可以用这种方式实现。适合用于多级组件嵌套传值

在b组件中使用组件c的时候用v-bind绑定一个属性$attrs这样就可以直接在c组件中拿到父组件a传下来的数据了。用v-on绑定一个$listeners属性就可以直接在组件c里调用a组件的方法了。

###### 5.provider和inject

父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,都可以通过inject来调用provide的数据

但是这种写法传递的数据是不响应的。

###### 6.v-model也能实现组件传值

给子组件绑定v-model,子组件被注入value属性和input事件,在子组件中通过emit调用input事件就能修改父组件的v-model值

###### 7.$parent和$children

      在组件内部可以直接通过子组件$parent对父组件进行操作,父组件通过$children对子组件进行操作.$children是一个数组 用的时候加下标

###### 8.Vuex

vuex也可以实现组件之间的传值,把公共的数据放在state中,所有的组件都可以使用

#### vuex

    vuex是一个状态管理工具,所谓的状态就是数据,采用集中式存储管所有组件的状态,是为了解决大型项目一个数据共享的问题。vuex 他可以将数据保存到本地,数据是响应式的,能够保持数据页面的共享,提高开发效率。
    12中vue通信方式硬核:https://blog.csdn.net/qq_54753561/article/details/122281196?spm=1001.2014.3001.5502

##### watch深度监听

    watch是默认不开启深度监听的,需要手动开启,deep:true  开启后可以深度监听数组,对象

8. ### vue 中 Computed、Methods、Watch 区别
  
  ​ Watch、Computed 被监听的数据发生改变的时候都能够做出响应、methods是事件方法的集合
  
  ##### computed
  
  computed的工作原理
  
  监听一个数据返回一个数据,且新数据必须被使用才能对被监听数据做观察。
  
  ##### watch
  
  watch的共组原理
  
  就是单纯的监听一个数据,当数据改变后就执行
  
  watch对数据类型的要求
  
  如果是对象/数组则需要开启深度监听,而计算属性没有类型的要求
  
  watch每次只能对一个数据监听,而计算可以一次监听多个值,只要其中一个 值发生变化,就会执行
  
  watch可以执行异步操作,当一个数据改变后发起接口请求。但是因为计算属性属于立即执行立即返回,所以只能写同步代码
  
  ##### methods
  
  methods不会被缓存:方法每次都会去重新计算结果。methods 方法表示一个具体的操作,主要书写业务逻辑;使用 methods 方法编写的逻辑运算,在调用时 add() 一定要加“()”,methods 里面写的多位方法,调用方法一定要有()。methods方法页面刚加载时调用一次,以后只有被调用的时候才会被调用。我们在长度框和宽度框的值输入完以后,点击“+” methods 方法调用一次。这里很明显我们采用 methods 会更节省资源。
  
9. ### mvvm 和 mvc
  
  ​ MVVM是为了实现MVC中的V MVVM分为:M(model数据)、V(view试图)、VM(viewModel控制数据的改变和控制试图)
  
  区别:MVC中Controller演变成了MVVM中的viewModel。MVVM主要解决了MVC中大量的DOM操作带来的使页面渲染性能降低,加载速度变慢等问题。MVVM中当和Model频繁发生变化,开发者需要主动更新到View。
  
       (2)MVVM是为了实现MVC中的V MVVM分为:M(model数据)、V(view试图)、VM(viewModel控制数据的改变和控制试图) 
          MVVM与MVC最大的区别就是:它实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变。非常的神奇~这里我们拿典型的MVVM模式的代表,Vue,
          html部分相当于View层,可以看到这里的View通过通过模板语法来声明式的将数据渲染进DOM元素,当ViewModel对Model进行更新时,通过数据绑定更新到View。
           Vue实例中的data相当于Model层,而ViewModel层的核心是Vue中的双向数据绑定,即Model变化时VIew可以实时更新,View变化也能让Model发生变化。
          整体看来,MVVM比MVC精简很多,不仅简化了业务与界面的依赖,还解决了数据频繁更新的问题,不用再用选择器操作DOM元素。因为在MVVM中,View不知道Model的存在,Model和ViewModel也观察不到View,这种低耦合模式提高代码的可重用性。
      
       优点:数据源和视图实现了双向绑定,很好的做到了数据的一致性
        相比于mvp各层的耦合度更低,一个viewmodel层可以给多个view层共用。
      
      缺点: 因为使用了dataBinding,增加了大量的内存开销,增加了程序的编译时间,项目越大内存开销越大。
        数据绑定使得 Bug 很难被调试。你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题                   
      
      
  

(1)mvc 分为M:(model模型)、V(view试图)、C(controller控制器) MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型、视图和控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。 【优点】 耦合性低,方便维护,可以利于分工协作 重用性高 【缺点】 使得项目架构变得复杂,对开发人员要求高

    
    
    
    10. ### vue 中的事件修饰符、
    
     ```
     .stop  阻止事件冒泡
     .cpture 设置事件捕获
     .self  只有当事件作用在元素本身才会触发
     .prevent 阻止默认事件,比如超链接跳转
     .once 事件只能触发一次
     .native 触发js原生的事件
     .number 把文本框的内容转换为数字
     .trim  去除文本框左右空格
     ```
    
    
    
    11. ### vue 自定义组件、
    
     ```
     在vue 中的 component 中新建组件,定义好<template>视图层,<script>逻辑层,<style>css样式层。,然后在页面引入,在components 中注册组件 ,在页面中作为标签来使用。
    
     在vue中开发,都是用的组件化的思想开发的,组件封装的方式可以使我们的开发效率提高,把单页面的每个模块拆分为一个组件件,
    
     组件封装的方式解决了我们传统项目,开发效率低,难以维护,复用性低等问题。
    
     使用:比如说封装一个 swiper 首先我们要定义一个props要接受传递的数据,写入响应的逻辑,在通过import引入到页面注册作为标签使用即可。
     ```
    
    
    
    12. ### vue 自定义指令、
    
     ```
     vue中除了核心功能内置的指令外,也允许注册自定义指令。自定义指令又分为全局的自定义指令和局部自定义指令。
    
     ##### *全局自定义指令\****是通过Vue.directive('第一个参数是指令的名称',{第二个参数是一个对象,这个对象上有钩子函数})
    
     ***\*局部自定义指令:\****
     是定义在组件内部的,只能在当前组件中使用
    
     ***\*钩子函数:\****
     一个指令定义对象可以提供如下几个钩子函数 (均为可选):
    
     **inserted**:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    
     **bind**:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    
     **update**:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
    
     **componentUpdated**:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    
     **unbind**:只调用一次,指令与元素解绑时调用。
     ```
    
    
    
    13. ### 自定义指令使用场景、
    
     拖拽、输入框获取焦点、图片懒加载、对dom进行操作
    
    14. ### vue 自定义过滤器 filter、
    
     ```
     过滤器是对 即将显示的数据做进一步的筛选处理,然后显示,过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据
     全局:
     Vue.filter(‘过滤器名’,funciton(val){})
     局部过滤器,定义在组件内部 filters 属性上.它只能在此组件内部使用.
     filters:{过滤器名:funciton(参数){//逻辑代码}}
     使用: 过滤时间,过滤金钱
     ```
    
    
    
    15. ### vue-router、vue-router 原理、vue 脚手架本地开发跨域请求设置
    
     ```
     由于Vue在开发时对路由支持的不足,于是官方补充了vue-router插件。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,实际上就是组件的切换。路由就是SPA(单页应用)的路径管理器。再通俗的说,vue-router就是我们WebApp的链接路径管理系统。
    
     原理
     一般源码中,都会用到 window.history 和 location.hash
     原理:通过改变浏览器地址URL,在不重新请求页面的情况下,更新页面视图,通过BOM中的location对象,其中对象中的location.hash储存的是路由的地址、可以赋值改变其URL的地址。而这会触发hashchange事件,而通过window.addEventListener监听hash值然后去匹配对应的路由、从而渲染页面的组件
     1.一种是# hash,在地址中加入#以欺骗浏览器,地址的改变是由于正在进行页内导航 
     2.一种是h5的history,使用URL的Hash来模拟一个完整的URL
    
     在根目录创建vue.config.js
     在module.exports中配置devserver的内容 
     主要是通过 proxy
    
     devServer: {
             host:'0.0.0.0',
             port: 8080,//端口号
             open: true,//运行项目自启
             proxy:{
                 '/api':{
                     target:'http://localhost:3000/',//跨域请求资源地址
                     ws:false,//是否启用websockets
                     changeOrigin:true,//开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题
                     pathRewrite:{
                         '^/api':''//注册全局路径
                     }
                 }
             }
         }
     ```
    
    
    
    16. ### keep-alive
    
     ```
     keep-alive是Vue提供给我们一个内置组件,会缓存不活动的组件实例,而不是销毁它们, 作为标签使用 包裹在需要缓存的组件外
     在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性
     **作用:**  比如列表页面进入详情,我们想保存列表滚动的位置,我们就可以使用keep-alive保存列表页面的滚动位置。
     组件使用keep-alive以后会新增两个生命周期 actived()  deactived()
     activated(组件激活时使用) 与 deactivated(组价离开时调用)
     ```
    
    
    
    17. ### v-for 中为何要使用 key
    
     key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
    
    18. ### slot、vue 中的 prop 验证
    
     slot就是插槽有三种                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
    
     默认插槽就是把父组件中的数据,显示到子组件中,子组件通过一个slot插槽标签显示父组件中的数据
     具名插槽就是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置
     作用域插槽:他是带有数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽来进行不同的展现和填充内容,在标签中通过slot-scope来接收数据
    
      单项数据流
     所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
     每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。 
    
    19. ### vue 中$nextTick()作用
    
     在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM
    
     ```
     this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
     可以根据打印的顺序看到,在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作并无作用,而在created()里使用this.$nextTick()可以等待dom生成以后再来获取dom对象,而通过this.$nextTick()获取到的值为dom更新之后的值
     ```
    
    
    
    20. ### vue 修改数据页面不更新
    
     ```
     xxxxxxxxxx 问题原因:因为 vue 的检查机制在进行视图更新时无法监测 数组中的对象的某个属性值的变化。解决方案如下Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实施响应。 this.$set()解决vue3没有这个问题因为是 proxy方案一:利用  this.set(this.obj,key,val)
     ```
    
    
    
    21. ### vue2 和 vue3 的区别
    
     1. vue2是选项api 需要什么选项就直接写什么选项
         vue3是组合api 所有的代码都写在setup里边  需要什么就要import引入什么
    
     2.双向数据绑定原理发生了改变,vue3的proxy替换vue2的Object.defineProperty
    
     3.Vue3默认使用懒加载
    
     4.Vue3新加入了TypeScript以及PWA支持
    
     5.重构虚拟DOM
    
     6.生命周期也有改变
    
     7.vue3取消了过滤器filters
    
    
    
     ```
     使用 选项类型API(Options API) 对比Vue3 合成型API(Composition API)
     vue2 - optionsApi  使用传统api中,新增一个需求,要在data,methods,computed中修改
     vue3 - compositionApi  我们可以更加优雅的组织我们的代码,函数,让我们的代码更加有序的组合在一起
     随着虚拟 DOM 重写,减少 运行时(runtime)开销。重写将包括更有效的代码来创建虚拟节点。
     vue3 没有了过滤器
     双向数据绑定 从 Object.defineProperty() 变成了 proxy,通过下标修改数组变化了试图数据没发生变化 this.$set()     vue3不需要
    
     1. 双向数据绑定原理发生了改变,使用proxy替换Object.defineProerty,使用Proxy的优势:
        setup 函数
        3.0新加入了TypeScript以及PWA支持
        声明周期的变化
     ```
    
    
    
    22. ### vue 中的 provide 和 inject (依赖注入)
    
     父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,都可以通过inject来调用provide的数据
    
     但是这种写法传递的数据是不响应的。
    
     ```
     provide / inject 为依赖注入,说是不推荐直接用于应用程序代码中,但是在一些插件或组件库里却是被常用,所以我觉得用也没啥,还挺好用的
    
     provide:可以让我们指定想要提供给后代组件的数据或方法
    
     inject:在任何后代组件中接收想要添加在这个组件上的数据或方法,不管组件嵌套多深都可以直接拿来用
    
     要注意的是 provide 和 inject 传递的数据不是响应式的,也就是说用 inject 接收来数据后,provide 里的数据改变了,后代组件中的数据不会改变,除非传入的就是一个可监听的对象
    
     详细 : https://blog.csdn.net/qq_54753561/article/details/122281196?spm=1001.2014.3001.5502
     ```
    
    
    
    23. ### vue 动画 transition
    
     Vue提供了transition的封装组件,在下列情况中,可以给任何元素和组件添加”进入”和”离开”过渡动画。 
    
     ```
     可以实现过渡和动画标签,是vue的内置组件
    
     v-enter:定义上半场过渡的初始状态;在过渡开始前被添加,在过渡开始时会被移除
     v-enter-to:定义上半场过渡的结束状态;在过渡开始时被添加,在过渡完成时会被移除
     v-enter-active:这里包含了上面的v-enter、v-enter-to两个时间段,在这里可以对上半场过渡定义过渡时间、曲线等
     v-leave:定义下半场过渡的初始状态;在过渡开始前被添加,在过渡开始时会被移除
     v-leave-to:定义下半场过渡的结束状态;在过渡开始时被添加,在过渡完成时会被移除
     v-leave-active:这里包含了上面的v-leave、v-leave-to两个时间段,在这里可以对下半场过渡定义过渡时间、曲线等
     ```
    
    
    
    24. ### vue 中 mixins(混入)的使用
    
      混入 (mixins): 是一种分发 [Vue](https://so.csdn.net/so/search?q=Vue&spm=1001.2101.3001.7020) 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项 
    
      在src目录下创建一个mixins文件夹,文件夹下新建一个myMixins.js文件。 
    
      在需要调用的组件中引入myMixins.js文件,然后在export default 中引入你需要的对象即可

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值