面试题整理

  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.兄弟组件传值:

  8. 通过main.js初始化一个全局的$bus,在发送事件的一方通过$bus.$emit(“事件名”,传递的参数信息)发送,在接收事件的一方通过$bus.$on("事件名",参数)接收传递的事件

  9. 使用同一个父组件作为中间消息传递者实现兄弟通信

    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  开启后可以深度监听数组,对象

  10. vue 中 Computed、Methods、Watch 区别

    Watch、Computed 被监听的数据发生改变的时候都能够做出响应、methods是事件方法的集合

    computed

    computed的工作原理

    监听一个数据返回一个数据,且新数据必须被使用才能对被监听数据做观察。

    watch

    watch的共组原理

    就是单纯的监听一个数据,当数据改变后就执行

    watch对数据类型的要求

    如果是对象/数组则需要开启深度监听,而计算属性没有类型的要求

    watch每次只能对一个数据监听,而计算可以一次监听多个值,只要其中一个 值发生变化,就会执行

    watch可以执行异步操作,当一个数据改变后发起接口请求。但是因为计算属性属于立即执行立即返回,所以只能写同步代码

    methods

    methods不会被缓存:方法每次都会去重新计算结果。methods 方法表示一个具体的操作,主要书写业务逻辑; 使用 methods 方法编写的逻辑运算,在调用时 add() 一定要加“()”,methods 里面写的多位方法,调用方法一定要有()。methods方法页面刚加载时调用一次,以后只有被调用的时候才会被调用。我们在长度框和宽度框的值输入完以后,点击“+” methods 方法调用一次。这里很明显我们采用 methods 会更节省资源。

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

  12. vue 中的事件修饰符、

    .stop  阻止事件冒泡
    .cpture 设置事件捕获
    .self  只有当事件作用在元素本身才会触发
    .prevent 阻止默认事件,比如超链接跳转
    .once 事件只能触发一次
    .native 触发js原生的事件
    .number 把文本框的内容转换为数字
    .trim  去除文本框左右空格

  13. vue 自定义组件、

    在vue 中的 component 中新建组件,定义好<template>视图层,<script>逻辑层,<style>css样式层。,然后在页面引入,在components 中注册组件 ,在页面中作为标签来使用。
    
    在vue中开发,都是用的组件化的思想开发的,组件封装的方式可以使我们的开发效率提高,把单页面的每个模块拆分为一个组件件,
    
    组件封装的方式解决了我们传统项目,开发效率低,难以维护,复用性低等问题。
    
    使用:比如说封装一个 swiper 首先我们要定义一个props要接受传递的数据,写入响应的逻辑,在通过import引入到页面注册作为标签使用即可。

  14. vue 自定义指令、

    vue中除了核心功能内置的指令外,也允许注册自定义指令。自定义指令又分为全局的自定义指令和局部自定义指令。
    
    ##### *全局自定义指令\****是通过Vue.directive('第一个参数是指令的名称',{第二个参数是一个对象,这个对象上有钩子函数})
    
    ***\*局部自定义指令:\****
    是定义在组件内部的,只能在当前组件中使用
    
    ***\*钩子函数:\****
    一个指令定义对象可以提供如下几个钩子函数 (均为可选):
    
    **inserted**:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    
    **bind**:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    
    **update**:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
    
    **componentUpdated**:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
    
    **unbind**:只调用一次,指令与元素解绑时调用。

  15. 自定义指令使用场景、

    拖拽、输入框获取焦点、图片懒加载、对dom进行操作

  16. vue 自定义过滤器 filter、

    过滤器是对 即将显示的数据做进一步的筛选处理,然后显示,过滤器并没有改变原来的数据,只是在原数据的基础上产生新的数据
    全局:
    Vue.filter(‘过滤器名’,funciton(val){})
    局部过滤器,定义在组件内部 filters 属性上.它只能在此组件内部使用.
    filters:{过滤器名:funciton(参数){//逻辑代码}}
    使用: 过滤时间,过滤金钱

  17. 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':''//注册全局路径
                    }
                }
            }
        }

  18. keep-alive

    keep-alive是Vue提供给我们一个内置组件,会缓存不活动的组件实例,而不是销毁它们, 作为标签使用 包裹在需要缓存的组件外
    在组件切换过程中 把切换出去的组件保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性
    **作用:**  比如列表页面进入详情,我们想保存列表滚动的位置,我们就可以使用keep-alive保存列表页面的滚动位置。
    组件使用keep-alive以后会新增两个生命周期 actived()  deactived()
    activated(组件激活时使用) 与 deactivated(组价离开时调用)

  19. v-for 中为何要使用 key

    key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点

  20. slot、vue 中的 prop 验证

    slot就是插槽有三种

    默认插槽就是把父组件中的数据,显示到子组件中,子组件通过一个slot插槽标签显示父组件中的数据 具名插槽就是在父组件中通过slot属性,给插槽命名,在子组件中通过slot标签,根据定义好的名字填充到对应的位置 作用域插槽:他是带有数据的插槽,子组件提供给父组件的参数,父组件根据子组件传过来的插槽来进行不同的展现和填充内容,在标签中通过slot-scope来接收数据

    单项数据流 所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。 每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。

  21. vue 中$nextTick()作用

    在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM

    this.$nextTick()将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
    可以根据打印的顺序看到,在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作并无作用,而在created()里使用this.$nextTick()可以等待dom生成以后再来获取dom对象,而通过this.$nextTick()获取到的值为dom更新之后的值

  22. vue 修改数据页面不更新

    xxxxxxxxxx 问题原因:因为 vue 的检查机制在进行视图更新时无法监测 数组中的对象的某个属性值的变化。解决方案如下Object.defineProperty 无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实施响应。 this.$set()解决vue3没有这个问题因为是 proxy方案一:利用  this.set(this.obj,key,val)

  23. 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支持
       声明周期的变化

  24. 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

  25. 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两个时间段,在这里可以对下半场过渡定义过渡时间、曲线等

  26. vue 中 mixins(混入)的使用

    混入 (mixins): 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项

    在src目录下创建一个mixins文件夹,文件夹下新建一个myMixins.js文件。

    在需要调用的组件中引入myMixins.js文件,然后在export default 中引入你需要的对象即可

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值