vue面试题

vue面试题

11.29

1.数组中常用的方法?

  • 常用迭代方法:forEach、map、filter、find、findIndex、some、every、reduce、reduceRight、、、、
    • arr.forEach(function(item,index,obj){}),window:依次遍历数组中的每一项,不存在返回值,第二个函数是改变函数内的this指向,【箭头函数不存在this】
    • arr.map(function(item,index){}),window:map是在forEach的基础上,支持返回值:回调函数中返回啥,就是把数组中当前迭代这一项替换成啥,原始数组不会变,以新数组返回!!
    • arr.filter(function(item,index){reutrn true条件}):filter实现数据的筛选或者过滤:迭代数组每一项,把符合条件的(回调函数返回true)放在一个新数组中返回,一项符合 条件的都没有,返回空数组!!
    • arr.find/findIndex(function(item,index){return true条件}):find/findIndex按照条件找到符合条件的这一项(这一项的索引):有多项符合条件,只返回第一个符合条件的即可,如果一个符合条件的都没有,结果是undefined/(-1)
    • arr.some/every(function(item,index){return 判断条件})
      • some依次迭代数组中的每一项,只要其中有一项符合设定的条件,则结果为true,如果所有项都不符合条件,则结果是False;
      • evey和他相反,他是所有项都符合条件结果才是true,只要有一项不符合则结果是false。
    • arr.reduce/reduceRight(function(result,item,index){return 结果}):reduce依次迭代数组每一项,(reduceRight是从右到左迭代),他会把上一次迭代中,回调函数处理的结果传递给下一次迭代,以此实现结果的累计
        • 第一个参数:函数,存在三个实参
          • “x”:初始值是数组的第一项值,从数组第二项开始迭代
          • 每次迭代return的值,会赋值给下一项的x,实现累积操作
        • 第二个参数:x的初始值,没有第二个参数会比有第二个参数少迭代1次
          • 如果没有第二个参数,则x的初始值是数组的第一项值,数组从第二项开始迭代:首次迭代:x=arr[0] item=arr[1] index=1
          • 如果有,则x的初始值为第二个参数,数组从第一项开始迭代:首次迭代:x=第二个参数值 item=arr[0] index=0
  • ``arr.fill(value[start,end]):`将arr的start到end索引的多项填充为value值,如果不写start和end,则表示所有项改为value值
  • arr.flat(n):数组扁平化,将多维数 组降维度,原数组不变,返回新数组arr.flat(1):表示将arr降一维,如果arr开始是四维,那么现在是三维的arr.flat(Infinity):无论arr是几维,都扁平化为一维数组`

2、对象中常用的方法?

公有方法5个

把Object视为一个实例的私有方法21个

Object.prototype上的公有方法5个:obj.xxx()

  • obj.hasOwnProperty('property'):检测obj对象中是否存在property私有属性
  • toString:检测数据类型的 :Object.prototype.toString.call([value]);
  • obj1.isPrototypeOf(obj2):测试obj1是否存在于obj2的原型链上
  • obj.valueOf():返回obj的原始值,但是有些对象不能转成原始值类型,如:Object、Function...
  • obj.propertyIsEnumerable('property1'):判断obj对象中property1属性是否可枚举(遍历、迭代)

把Object作为一个实例对象,学习其私有属性方法Object.xxx()

  • 跟规则没关系的方法3个:

    • Object.assign(obj1,obj2,...):合并两个(或多个)对象,让obj2及以后的对象替换obj1中的内容返回obj1【ES6】
    • Object.create(obj):创建一个空对象,并且把obj作为其原型对象
    • Object.is(value1,value2):基于三个等于号,绝对相等进行比较的【ES6新增】
      • 特殊:Object.is(NaN,NaN)->true:这里可以判断一个值是不是NaN,做的也是全等比较
  • 对对象中属性操作的方法8个:

    • Object.defineProperty(obj,key,descriptor):对当前对象中的某个属性进行监听或劫持,以及设置一些规则

      • let proxy={...obj};
        
        Object.definePropery(obj,'name',{
        //以下三个属性的值默认为false
            //是否可以基于delete删除
            configurable:true,
            //是否可以枚举的,如果是不可枚举的属性,则基于for/in循环或者Object.keys()等操作都无法获取这个属性
            enumerable:true,
            //是否可以修改值【不能和get/set】
            writable:true
            //当我们获取obj的name属性值的时候,会触发Getter函数,方法返回的值就是获取的属性值
            get(){
        	return obj.name;//不能这样用,因为每次获取都会触发get事件,最终形成死循环
            return proxy.name;//return的时候用代理对象,不让它重复触发get方法
        	},
            //当我们设置name属性值的时候,会触发SETTER函数,value是需要新设置的值
            set(vaule){
        
              	obj.name=value;//不能这样用,因为在这里设置,仍然会触发set方法,最终形成死循环
                proxy.name=value;//能这样用,使用代理对象,不让它重复触发set方法
            }
        })
        
      • descriptor:{对象类型},描述,可以对对象中某个属性进行监听或劫持,可以规定属性是否可以【删、改、遍历…】

        • configurale:true:是否可以基于delete删除name属性
        • enumerable:true:是否是可枚举的name属性,如果不可枚举,则for/in/Object.key()等操作无法遍历到该属性
        • writable:true:是否可以修改值【只要设置了该描述,不管true或false,都不能使用get/set方法】
        • get(){return xxx}:对获取obj.name属性操作进行拦截,return的值,就是真正获取到的值
        • set(value){xxx}:对设置obj.name=value操作进行拦截,并执行函数体内的操作
    • Object.getOwnPropertyDescriptor(obj,key):获取obj中key属性所设置的规则的状态(可删除/枚举/修改…),

    • Object.getOwnPropertyDescriptors(obj):获取obj中每一个属性所设置的规则的状态

    • 获取当前对象不同类型的键或值5个:

      • Object.getOwnPropertyNames(obj):获取当前对象所有非Symbol类型的私有属性【含不可枚举的】
      • Object.getOwnPropertySymbols(obj):获取当前对象所有Symbol类型的私有属性【含不可枚举的】
      • Object.keys(obj):获取当前对象所有非Symbol类型且可枚举的私有属性名【不能获取不可枚举的】
      • Object.values(obj):获取当前对象所有非Symbol类型且可枚举的私有属性值
      • ES6新增一个Reflect对象,可以更快捷的对“对象”进行相关操作
        • Refelect.ownKeys(obj):获取所有私有属性【包含各种类型及可枚举和不可枚举的】
  • 冻结2:不让其设置defineProperty劫持

    • Object.freeze(obj):冻结,把一个对象进行冻结,目的是让其不能在再基于Object.defineProperty做劫持,后续可以基于Object.isFrozen(obj):检测对象是否是冻结的
  • 设置和获取原型2个:

    • Object.getPropertyOf(obj):获取obj.__proto__指向的原型
    • Object.setPropertyOf(obj,property):设置obj原型对象obj.__proto__===prototype
  • 阻止扩展2:不能再为其设置新的属性

    • Object.preventExtensions(obj):把obj变为不可扩展对象
    • Object.isExtensible(obj):判断一个对象是不是可扩展对象
  • **封存2个:**不允许添加或删除对象中的属性,但允许修改对象中存在的属性

    • Object.seal(obj):封存对象,不允许添加或删除对象中的属性,但允许修改对象中存在的属性
    • Object.isSealed(obj):判断一个对象是否封存了。
  • 对象的属性与二维数组互相转换2个:

    • Object.entries(obj):将对象中的每个可枚举的键值对转为数组,返回一个二维数组
    • Object.fromEntries(arr):将二维数组的各数据项,转换为对象,返回一个对象

3、Refelect对象的作用?

  • Refelect对象,可以更快捷的对"对象"进行相关操作[把对象中常见的相关操作,聚合在一起,基于Refelect对象提供的方法],也可以完成对"对象"的操作。
  • 常用的方法:
    • Reflect.ownKeys(obj):获取所有私有属性[包含各种类型及可枚举和不可枚举的]
    • Refelct.deleteProperty(obj,key):删除obj中的key属性,与delete obj[key]作用相同
    • Reflect.has(obj,key):判断obj中是否存在key属性,与key in obj作用相同
    • 其他的方法Object中的方法也可以实现

4、forEach和for循环的区别是什么?

  • 编程方式不同:
    • forEach属于函数式编程:把循环的操作封装到函数中,我们不需要关注循环的过程,只需要关注结果 WHAT;
    • for循环属于命令式编程:循环的过程自己把控,关注过程 HOW;
    • 开发推荐用函数式编程,如果遇到需要灵活把控每一步,使用命令式编程
  • 循环灵活度
    • forEach会迭代数组每一项,不支持提前结束、也不支持跳跃式循环
    • for循环想咋做咋做
    • 真实项目中,大部分需求都直接基于forEach处理即可,这样可以提高开发效率,减少冗余代码,但是某些负责的需求,需要我们在循环过程中做一些特殊处理的,我都自己写for循环。。。

5、函数式编程的作用?

  • 优点:提高开发效率,减少代码冗余
  • 缺点:过程都封装好了,我们无法更改处理的过程

6、命令式编程的作用?

  • 优点:可以有效管控过程中的每一步,灵活
  • 缺点:开发效率低,代码冗余高
  • 开发推荐用函数式编程,如果遇到需要灵活把控每一步,使用命令式编程

7.什么叫稀疏数组?

  • 稀疏数组:数组中并不是每一项都有值,这样的数组称为稀疏数组 例如:new Array(5),长度是5,但是每一项都是empty
  • 密集数组:每一项都有值
  • 迭代方法在处理的时候,如果是数组中的稀疏项,那么不进行迭代

8.如何实现数组的扁平化?

  • 数组的扁平化就是说将一个多维数组,变为低维,或者是一维的数组
    • 方式一:arr.flat(Infinity)
    • 方式二:使用concat()
    • 方式三:使用递归
    • 方式四:使用字符串join方法。

---------------------------------------------------------------------------------vue---------------------------------------------------------------------

1.Vue是什么?

  • 官方网址https://cn.vuejs.org/
  • Vue是渐进式框架:vue.min.js只包含了vue最核心的内容【例如:options api/数据处理、template模板视图的解析等操作】;真实项目中我们还会根据需求,导入
    • vuex:实现公共状态管理
    • vue-router:实现SPA(single page application)单页面应用
    • element-ui(饿了么)、antdv(蚂蚁金服)、iview()、vant()、cube…基于这些UI组件库快速创建项目
    • axios:实现数据通信
    • @vue/cli:基于vue的脚手架创建工程化项目
  • Vue是基于MVVM模式构建的框架
    • 最后学习vue的原理,把两条主线关联在一起

2.Vue中Model数据层存在的操作?

  • 创建Vue实例:let vm=new Vue({options}),

  • 指定视图:

    • let vm=new Vue({
      	//方案一:指定页面中存在的DOM元素作为视图
      	el:`#box`,
      	//方案二:创建视图
             template:`<div>
              //最后把数据渲染在这个视图中
          </div>`,
          //方案四:render渲染视图
              render:h=>{
             ...
          		}
      })
      	//方案三:挂载视图
         vm.$mount(('#app'));
      
  • 构建数据模型:[需要在视图中渲染的数据]

    • //设置的数据直接挂载到vm实例对象上 vm.msg;
      //挂载都实例上的东西能够直接在视图中使用{{msg}}
      
      let vm=new Vue({
          data:{
              msg:'hello world'//会在vm实例上生成私有属性msg,值是'hello world'
          }
      })
      	vm.text="zhufeng";
      
  • 响应式:

    • //后期更改数据,vue会监听到数据的更改,通知视图按照最新的数据重新渲染;我们把修改后视图会重新渲染的数据,称之为"响应式数据"
      
      setTimeout(()=>{
      	vm.msg="你好,世界";
      	vm.text="珠峰"
      })
      
  • vm.$forceUpdate():强制让视图渲染

3.响应式和非响应式的区别?

  • 响应式数据:只要数据层中的数据修改了,Vue就会通知视图层重新渲染。例如:在vm创建时构造函数中options下data对象中设置的数据
  • 非响应式数据:即使数据被修改了,也不会造成视图层的重新渲染。例如:vm.text="珠峰",给vm实例设置的私有属性数据,给它重新赋值:vm.text="aaa",这里不会触发视图层的重新渲染。

2.不同框架采用的设计模式?

  • vue:MVVM双向数据绑定->(在谷歌的中国人:尤雨溪)
  • angular(简称:ng):MVVM ->(谷歌)
  • react:MVC->(facebook)

3.vue框架什么?

  • Vue框架&&React框架:让开发者放弃直接操作DOM,转为操作数据,当我们把数据处理"明白",框架本身会按照最新的数据帮助我们渲染出想要的视图[操作DOM的事情交给框架内部实现,而且做了性能优化]

4.Vue框架的模式?

  • Vue框架的模式:MVVM(model view viewModel):双向数据监听/绑定
    • model(数据层):构建数据、修改数据
    • view(视图层):学会vue的template语法
    • viewModel(数据和视图监听层(vue核心)):
      • 监听数据变化:通知视图重新渲染,
      • 监听视图改变[表单元素]:通知数据跟着改变

5.如何用Vue构建项目?

  • 第一步:引入vue对应的包:<script src="js/vue.min.js"></script>

  • 第二步:Vue是一个构造函数,我们基于vue开发,其实是创建这个类的一个实例:每个实例都有自己指定的视图,以及需要的数据

    • 1、指定视图

    • let vm=new Vue({
          //视图
          el:'#computedBox',
      })
      
    • 2、传入数据:data中所有内容都是未来需要在视图中渲染的数据

    •     //数据:data中所有内容都是未来需要在视图中渲染的数据
          data:{
              list: [{
                  id: 1,
                  count: 0,
                  price: 12.5
              }, {
                  id: 2,
                  count: 0,
                  price: 10.5
              }]
          }
      

12.1

1.为什么在v-for中必须有:key="xxx"属性,并且不能用index?

  • 当在组件中使用 v-for 时,key 现在是必须的。
    • 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。
    • 如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
    • 比如我们用多选框选中了数组中的第二个数据:
      • 如果没有存key值:则浏览器默认认为index=2的数据被选中了,当我们在数组最前面插入数据项,则后面的数据位置都发生了改变,而系统仍然认为index=2的数据项被选中了,这时正确被选中的应该是第三项猜对
      • 如果有:key值,但是:key=“index”:浏览器回去找:key=2的数据选中,但是当在最前面插入数据项时,后面所有数据的key值,都会跟着改变,结果仍然是不正确的
  • 所以我们为了保证Vue能够跟踪每个节点的身份,从而重用和重新排序现有的元素,我们应该给每一项提供一个唯一的key属性,且这个key属性不会被改变。

2.template与div用v-for的区别?

  • v-for的优先级高于v-if那么就会出现一个问题:

    • <div v-for="(item,index) in arr" v-if="item>10"></div>//arr=[10,20,30]
      
    • 以上标签在渲染时,会首先通过v-for循环创建3个div标签,再通过v-if判断是否符合条件,不符合条件的再被销毁,但这里有item=10的标签并不需要渲染创建再销毁,这样是消耗性能的

  • 如何解决:使用template标签

    • template标签:template标签不会被渲染到页面上。

    •     <template v-for="(item,index) in arr">
              <div v-if="item>10">{{item}}</div>
          </template>
      
      • template里面的div在渲染时已经知道了item值,所以不符合规则的div不会再无用的生成再销毁一次,优化了性能

3.computed、watch、methods的区别?

  • computed是属性调用,而methods是函数调用

  • computed带有缓存功能,而watch没有

  • watch可以监控对象,而computed、methods不能

4.computed和watch、methods的用法?

  • computed:计算属性【多个值变化,影响到一个结果值变化】

    • 计算:以函数的形式定义

    • 属性:以属性的形式使用

    • 定义方式:可以是直接函数和对象定义的两种方式

    •     //函数定义方式
      <!-- 以属性的形式使用 -->
          <div>{{funllname}}</div>
          <script>
              let vm=new Vue({
                  computed:{
                      // 以函数的形式定义
                      fullname(){
                          return this.first+"-"+this.last;
                      }
                  }   
              })
      
      • **特点:**computed里属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算
    • 对象定义方式:computed中的计算属性本身其实存在两个方法,只是默认获取,get()和set方法,原理:使用了Object.defineProperty()中的get/set劫持

    •       //对象定义方式        
      //计算变量的get和set方法
      	computed:{
                  fullname:{
                      // 对fullname属性获取时拦截,也是函数定义形式使用的默认方法
                     get(){
                         //实现多个值变换,改变一个结果值
                      return this.first+"-"+this.last;
                     },
                      //对fullname属性赋值时拦截     
                     set(val){//val是想赋给fullname的值,也可以说是心值
                      let arr=val.split("-");
                      //实现一个值变化,改变多个结果只
                      this.first=arr[0];
                      this.last=arr[1];
                     }
                  }
              } 
      
  • watch:侦听属性【一个值变化,影响多个结果值变换】

    • 侦听:watch中的定义的属性名就是我们监控的vm里的私有属性名,当这个私有属性发生变化是,会自动执行watch中对应方法:可以看作是computedmethods的结合体

    • 特点watch能够监控路由,如果不需要监控路由,我们尽可能的用computed的set方法来代替watch,原因是computed有缓存

    • 注意:我们监控的对象必须vm里已经存在该私有属性

    • 用法:可以是直接函数和定义对象两种用法

      • 直接函数的定义方式:不能给对应属性配置参数
      • 对象的定义方式:可以给对应属性配置参数:deep:是否深层侦听immediate:页面第一次加载时是否立即侦听一次
      • 如果我们侦听的是一个obj对象,对象里面的属性值发生改变时,并不会触发obj的侦听方法,这时我们就用obj的对象定义形式将obj的deep配置项设为true
    •             watch:{
                      //fullname就是我们监控的vm实例中的私有属性,存在两个值
                      //函数式写法
                      "obj"(newVal,oldVal){
                          let arr=newVal.split("-");
                          //实现一个值变化,改变多个结果值
                          this.first=arr[0];
                          this.last=arr[1];
                      },
                      // 对象式写法
                      "obj":{
                          // 这是函数式写法默认用的方法
                          // handler(newVal,oldVal){...}
                          //设置对obj的属性是否进行深侦听
                          deep:true,
                          // 设置对obj的属性是否在第一次渲染页面时立即侦听一次
                          immediate:true
                      }
                  }
      
  • methods:方法定义:方法表示一个具体的操作,主要书写业务逻辑;与我们js中函数的写法和用法相同

5.vue2.0中如何使用过滤器?

  • vue1.0中存在自带的过滤器

  • vue2.0中需要在vm实例options API的filters里定义局部过滤器,也可以用Vue.filter定义全局过滤器

  • 能够用filter过滤器的有{{}}(小胡子语法)v-bind指令

6.new Vue的生命周期函数(钩子函数)?

我们想看某个阶段的数据情况:直接在new Vue中调用对应的方法,比如查看初始化之前的:beforeCreate(){}

  • 生命周期钩子分为了四个阶段:初始化、渲染、更新、销毁

    • 初始化:init(new Vue的时候走)

      • berforeCreate:【初始化之前】组件实例刚刚创建,无任何属性,所以在这里,不能给任何属性赋值
      • created:【初始化之后】组件实例创建完成,datamethods中的数据已完成,el已经生成了,但是因为需要挂载DOM节点,而DOM树还没生成,所以el还没有被赋值。
    • 模板编译:mount(new Vue的时候走)

      • beforeMount:【模板编译之前】页面未渲染,页面知道了{{msg}}需要vm中msg值,但是并没有将vm的msg挂载上去
      • mounted:【模板编译之后】页面渲染结束,到这里已经向页面中挂载完了数据,已经将vm中的msg获取到,并且挂载到{{msg}}上去
    • 更新:update(响应式数据变了才会触发更新)

      • beforeUpdate:【更新之前】响应式数据变化了,但页面没变化
      • updated:【更新之后】响应式数据变化了,页面也更新了
    • 销毁:destroy(调用了vm.$destroy()方法,才会触发销毁阶段)

      • beforeDestroy:【销毁之前】实例销毁之前调用。在这一步,实例仍然完全可用
      • destroyed:【销毁之后】实例销毁后调用。该钩子被调用后,对应 Vue 的vm实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁但是vm实例仍然存在,仍然可以获取vm中的私有属性
      • 执行了destroy操作,视图中的原来样式保留,后续就不再受vue控制了
    •     <script>
              let vm=new Vue({
                  el:"div",
                  data:{
                      msg:[10,20,30]
                  },
                  beforeCreate(){
                      // this.msg[0]=100;//报错:因为还没有生成data,vm中不存在msg私有属性
                  },
                  created(){
                      this.msg[0]=100;//vm.msg=[100,20,30],已经生成了data和methods,可以修改vm的私有属性msg
                  },
                  beforeMount(){
                      this.msg[1]=200;//vm.msg=[100,200,30],修改了vm的私有属性,但是页面还没有被渲染:<div>{{msg}}</div>=><div>{{msg}}</div>
                  },
                  //在这两者之间,页面被渲染了:<div>{{msg}}</div>=><div>[100,200,30]</div>
                  mounted(){
                      this.msg[2]=300;//vm.msg=[100,200,300],但是页面已经渲染了,页面的显示仍然是:<div>{{msg}}</div>=><div>[100,200,30]</div>
                  },
                  beforeDestroy(){
                      //执行了vm.$destroy(),在这一步,实例仍然完全可用
                  },
                  destroyed(){
                      //执行了vm.$destroy(),到这一步,Vue的vm实例与视图的所有关系都解除了:指令都被解绑、事件监听器被移除、子实例也都被销毁
                  }
              })
      
              vm.$destroy();
              console.log(vm);
      
          </script>
      
  • 除以上8个常用钩子函数之外还有3个不常用的钩子函数:

    • activated:激活,被 keep-alive 缓存的组件激活时调用。
    • deactivated:停用,被 keep-alive 缓存的组件失活时调用。
    • errorCaptured:错误捕获
      • 语法:(err: Error, vm: Component, info: string) => ?boolean
      • 说明:在捕获一个来自后代组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值