小滴课堂22年新版互联网大厂前端高频面试题(8)~持续更新中


前言

小滴课堂,旨在让编程不在难学,让技术与生活更加有趣。 随着互联网+的时代,在线教育技术越来越便捷,小滴课堂依托在线教育时间以及空间上的便利,为广大IT从业者提供了更为方便、快捷的学习交流途径、提供大量高质量的IT在线课程。更多教程请访问xdclass.net(添加VX:xdclass99)

一、如何分包加载?分包加载的优势在哪?

回答

(一)分包的介绍

  • 分包加载其实就是把小程序划分成不同的子包,然后在用户使用的时候才进行加载,就是我们口中常说的按需加载。每个分包⼀般会有⼀个主包,主包会在小程序启动时首先下载,其他分包则会在进⼊对应页面时下载对应包的资源。

⽬前小程序分包⼤⼩有以下限制:

  • 整个⼩程序所有分包⼤小不超过 8M
  • 单个分包/主包⼤小不能超过 2M

(二)分包的使用

  • 通过在app.json中设置subpackages字段声明项目的分包结构,这⾥我们看下官网的例⼦:
{
   "pages":[
     "pages/index",
     "pages/logs"
   ],
 "subpackages": [
   {
     "root": "packageA",
     "pages": [
       "pages/cat",
       "pages/dog"
   ]
 }, {
   "root": "packageB",
   "name": "pack2",
   "pages": [
     "pages/apple",
     "pages/banana"
    ]
   }
  ]
}
  • 可以看到这⾥除了主包里的pages页面外,subpackages中也配置了几个包,里面也有对应的页面。subpackages具体配置可以看下下图:

在这里插入图片描述

  • 这⾥root根目录指的是指定根目录的文件夹,来看下目录结构就知道了

在这里插入图片描述

  • 上⾯指定的root中packageA和packageB就是packageA和packageB的路径

  • 这里使用时需要注意几点,如下:

subpackages配置路径外的目录会被打包到主包(app)中

  1. 主包(app)可以有⾃己的pages(即subpackages外的 pages 字段)
  2. subpackage 的根目录不能是另外⼀个 subpackages 内的子目录
  3. tabBar 页面必须在主包(app)内
  4. 分包与分包之间不可以引用其js⽂件、template以及资源(如packageA 无法require packageB JS 文件),但可以 require app`、⾃己package 内的 js⽂件、template以及资源

(三)分包的优势

  • 采用分包加载,对开发者而⾔,代码体积可以承载更⼤;而对⽤户而言,可以提高小程序的启动速度,大大提升体验。

二、什么是MVC和MVVM?

回答

(一)MVC和MVVM都是常⻅的软件架构,在软件的设计过程中经常被提到。具体区别,你真的理解了吗?

(二)MVC

  1. 视图(View):⽤户看到并与之交互的界⾯,HTML在其中起着重要作⽤,即应⽤程序中显示数据的部分
  2. 控制器(Controller):应⽤程序中处理⽤户交互的部分,⼀般应⽤程序从视图层
  3. 读取数据,控制⽤户的输⼊,并向Model发送数据
  4. 模型(Model):应⽤程序中处理数据的逻辑部分,并存取数据
  5. 交互模式⼀般有两种。
  6. ⼀种是通过 View 接受指令,传递给 Controller。
  7. ⼀种是直接通过controller接受指令。
  • 直接通过controller接受指令图解:

在这里插入图片描述

(三)MVVM

  1. 组成部分:
  • Model:应用软件中的数据提供部分
  • View: 应用软件中的视图部分,也就是用户看到的界面部分
  • ViewModel:将View中的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开,取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑
  1. MVVM 模式将 Controller 改名为 ViewModel,同时改变了通信方向。

  2. View的变动,自动反映在 ViewModel,反之亦然。 Angular 和 Vue 都采用这种模式。

  3. 特点:

  • 低耦合。视图(View)可以独立于Model变化和修改,⼀个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。

  • 可重用性。你可以把⼀些视图逻辑放在⼀个ViewModel里面,让很多view重用这段视图逻辑。

  • 独立开发。开发⼈员可以专注于业务逻辑和数据的开发(ViewModel),设计⼈员可以专注于页⾯设计。

图解:

在这里插入图片描述

三、什么是Proxy及其作用

回答

(一)概述:

  • Proxy可以理解成,在⽬标对象之前架设⼀层 “拦截”,当外界对该对象进⾏操作的时候,都必须经过这层拦截,而Proxy就充当了这种机制,类似于代理的含义,它可以对外界访问对象之前进行过滤和改写该对象。

(二)引⼦:

  • 如果对vue2.xx了解或看过源码的⼈都知道,vue2.xx中使⽤ Object.defifineProperty()⽅法对该对象通过递归+遍历的⽅式来实现对数据的监控的,但这种方式是有缺点的。

缺点如下:

  1. 当我们使用数组的方法或改变数组的下标是不能重新触发 Object.defifineProperty中的set()方法的,因此就做不到实时响应了。
  2. 必须遍历每个对象的每个属性,才能进行监听,如果对象嵌套很深的话,需要使用递归调用。
    • 因此vue3.xx中之后就改用Proxy来更好的解决如上面的问题。

(三)基本语法:

const obj = new Proxy(target, handler);
/*
** 参数说明如下:
** target: 被代理对象。
** handler: 是⼀个对象,声明了代理target的⼀些操作。
** obj: 是被代理完成之后返回的对象。
*/

当外界每次对obj进⾏操作时,就会执⾏handler对象上的⼀些⽅法。handler中常⽤的
对象⽅法如下:

1. get(target, propKey, receiver)
2. set(target, propKey, value, receiver)
3. has(target, propKey)
4. construct(target, args):
5. apply(target, object, args)

(四)使用Proxy实现简单的Vue双向绑定

步骤:

  1. 需要实现⼀个数据监听器 Observer, 能够对所有数据进行监听,如果有数据变动的话,拿到最新的值并通知订阅者Watcher.
  2. 需要实现⼀个指令解析器Compile,它能够对每个元素的指令进⾏扫描和解析,根据指令模板替换数据,以及绑定相对应的函数。
  3. 需要实现⼀个Watcher, 它是链接Observer和Compile的桥梁,它能够订阅并收到每个属性变动的通知,然后会执⾏指令绑定的相对应 的回调函数,从而更新视图。

(五)实现Vue双向绑定的js部分

class Vue {
         constructor(options) {
           this.$el = document.querySelector(options.el);
           this.$methods = options.methods;
           this._binding = {};
           this._observer(options.data);
           this._compile(this.$el);
         }
         _pushWatcher(watcher) {
           if (!this._binding[watcher.key]) {
             this._binding[watcher.key] = [];
           }
           this._binding[watcher.key].push(watcher);
         }
         /*
          observer的作⽤是能够对所有的数据进⾏监听操作,通过使⽤Proxy对象中的set⽅法来监听,如有发⽣变动就会拿到最新值通知订阅者。
         */
         _observer(datas) {
           const me = this;
           const handler = {
             set(target, key, value) {
               const rets = Reflect.set(target, key, value);
               me._binding[key].map(item => {
                 item.update();
               });
               return rets; 
             }
           };
           this.$data = new Proxy(datas, handler);
         }
         /*
          指令解析器,对每个元素节点的指令进⾏扫描和解析,根据指令模板替换数据,以及绑定相对应的更新函数
         */
         _compile(root) {
           const nodes =
Array.prototype.slice.call(root.children);
            const data = this.$data;
            nodes.map(node => {
              if (node.children && node.children.length) {
                this._compile(node.children);
              }
               const $input = node.tagName.toLocaleUpperCase() ===
"INPUT";
               const $textarea = node.tagName.toLocaleUpperCase()
=== "TEXTAREA";
               const $vmodel = node.hasAttribute('v-model');
               // 如果是input框 或 textarea 的话,并且带有 v-model 属性的
               if (($vmodel && $input) || ($vmodel && $textarea)) {
                 const key = node.getAttribute('v-model');
                 this._pushWatcher(new Watcher(node, 'value', data, key));
                 node.addEventListener('input', () => {
                   data[key] = node.value;
                 });
               }
               if (node.hasAttribute('v-bind')) {
                 const key = node.getAttribute('v-bind');
                 this._pushWatcher(new Watcher(node, 'innerHTML', data, key));
               }
               if (node.hasAttribute('@click')) {
                 const methodName = node.getAttribute('@click');
                 const method =
this.$methods[methodName].bind(data);
                node.addEventListener('click', method);
              }
            });
          }
        }
        /*
         watcher的作⽤是 链接Observer 和 Compile的桥梁,能够订阅并收到每个属性变动的通知,
         执⾏指令绑定的响应的回调函数,从⽽更新视图。
        */
        class Watcher {
          constructor(node, attr, data, key) {
            this.node = node;
            this.attr = attr;
            this.data = data;
            this.key = key; 
          }
          update() {
            this.node[this.attr] = this.data[this.key];
          } 
        }

四、实现垂直居中的几种方法(包含css3新特性flflex布局)

回答

1.position:absolute绝对定位

(一)已知子元素⾼度

 .parent {
       position: relative;
       width: 300px;
       height: 300px;
       background: #000;
}
.son {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 100px;
      height: 100px;
      margin-top: -50px;
      margin-left: -50px;
      background: red;
      color:#fff;
}
  • 效果如下图

在这里插入图片描述

(二)未知子元素高度:

.parent {
      position: relative;
      width: 300px;
      height: 300px;
      background: #000;
}
.son {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      background: red;
      color: #fff;
}
  • 效果如下图:

在这里插入图片描述

这两种方法均可达到垂直居中的效果,第⼀种是利用绝对定位+margin来设置的,第⼆种是利用决定定位+translate来设置,可以看到第⼆种不需要去计算宽高值的实际⼤小,直接用百分比即可达到效果。

2.利用table-cell

利⽤table-cell将元素变成表格形式,之后⽤vertical-align:middle对⼦元素设置垂直居中

  • 代码如下:
.parent {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  width: 300px;
  height: 300px;
  background: #000;
}
.son {
      background: red;
      color: #fff;
}
  • 效果如下:

在这里插入图片描述

3.利用css3的flex布局

这里运用到了css3的flflex布局,align-items将子元素垂直居中,之后justify-content则设置水平居中

  • 代码如下:
.parent {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 300px;
      height: 300px;
      background: #000;
}
.son {
      background: red;
      color: #fff;
}
  • 效果如下

在这里插入图片描述

五、说说vue是如何监听对象和数组变化的

回答

思路

(一)vue中对象数据的更新问题

  • 新增数据更新问题
  1. 描述
    • 通过普通对象添加属性⽅法,Vue不能监测到且不是响应式
this.obj.name= '小滴课堂'
  1. 解决
    • this.$se
this.$set(this.obj,'name','小滴课堂')
  • 注意
  • this.$set不能给vue实例的根数据对象添加属性

(二)数组数据更新问题

  1. 描述

    • 直接通过数组索引值改变数组的数据,Vue监测不到改变
    • 实际在 js 内存已经把数据的第⼀项数据修改了
  2. 解决

    • Vue在数组的原始操作方法上包裹了重新解析模板的⽅法,也就是说我们在data里面的数组操作方法不是原生的,是vue封装过的
    • 哪些数组操作方法经过了封装?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值