文章目录
前言
小滴课堂,旨在让编程不在难学,让技术与生活更加有趣。 随着互联网+的时代,在线教育技术越来越便捷,小滴课堂依托在线教育时间以及空间上的便利,为广大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)中
- 主包(app)可以有⾃己的pages(即subpackages外的 pages 字段)
- subpackage 的根目录不能是另外⼀个 subpackages 内的子目录
- tabBar 页面必须在主包(app)内
- 分包与分包之间不可以引用其js⽂件、template以及资源(如packageA 无法require packageB JS 文件),但可以 require app`、⾃己package 内的 js⽂件、template以及资源
(三)分包的优势
- 采用分包加载,对开发者而⾔,代码体积可以承载更⼤;而对⽤户而言,可以提高小程序的启动速度,大大提升体验。
二、什么是MVC和MVVM?
回答
(一)MVC和MVVM都是常⻅的软件架构,在软件的设计过程中经常被提到。具体区别,你真的理解了吗?
(二)MVC
- 视图(View):⽤户看到并与之交互的界⾯,HTML在其中起着重要作⽤,即应⽤程序中显示数据的部分
- 控制器(Controller):应⽤程序中处理⽤户交互的部分,⼀般应⽤程序从视图层
- 读取数据,控制⽤户的输⼊,并向Model发送数据
- 模型(Model):应⽤程序中处理数据的逻辑部分,并存取数据
- 交互模式⼀般有两种。
- ⼀种是通过 View 接受指令,传递给 Controller。
- ⼀种是直接通过controller接受指令。
- 直接通过controller接受指令图解:
(三)MVVM
- 组成部分:
- Model:应用软件中的数据提供部分
- View: 应用软件中的视图部分,也就是用户看到的界面部分
- ViewModel:将View中的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开,取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑
-
MVVM 模式将 Controller 改名为 ViewModel,同时改变了通信方向。
-
View的变动,自动反映在 ViewModel,反之亦然。 Angular 和 Vue 都采用这种模式。
-
特点:
-
低耦合。视图(View)可以独立于Model变化和修改,⼀个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
-
可重用性。你可以把⼀些视图逻辑放在⼀个ViewModel里面,让很多view重用这段视图逻辑。
-
独立开发。开发⼈员可以专注于业务逻辑和数据的开发(ViewModel),设计⼈员可以专注于页⾯设计。
图解:
三、什么是Proxy及其作用
回答
(一)概述:
- Proxy可以理解成,在⽬标对象之前架设⼀层 “拦截”,当外界对该对象进⾏操作的时候,都必须经过这层拦截,而Proxy就充当了这种机制,类似于代理的含义,它可以对外界访问对象之前进行过滤和改写该对象。
(二)引⼦:
- 如果对vue2.xx了解或看过源码的⼈都知道,vue2.xx中使⽤ Object.defifineProperty()⽅法对该对象通过递归+遍历的⽅式来实现对数据的监控的,但这种方式是有缺点的。
缺点如下:
- 当我们使用数组的方法或改变数组的下标是不能重新触发 Object.defifineProperty中的set()方法的,因此就做不到实时响应了。
- 必须遍历每个对象的每个属性,才能进行监听,如果对象嵌套很深的话,需要使用递归调用。
- 因此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双向绑定
步骤:
- 需要实现⼀个数据监听器 Observer, 能够对所有数据进行监听,如果有数据变动的话,拿到最新的值并通知订阅者Watcher.
- 需要实现⼀个指令解析器Compile,它能够对每个元素的指令进⾏扫描和解析,根据指令模板替换数据,以及绑定相对应的函数。
- 需要实现⼀个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中对象数据的更新问题
- 新增数据更新问题
- 描述
- 通过普通对象添加属性⽅法,Vue不能监测到且不是响应式
this.obj.name= '小滴课堂'
- 解决
- this.$se
this.$set(this.obj,'name','小滴课堂')
- 注意
- this.$set不能给vue实例的根数据对象添加属性
(二)数组数据更新问题
-
描述
- 直接通过数组索引值改变数组的数据,Vue监测不到改变
- 实际在 js 内存已经把数据的第⼀项数据修改了
-
解决
- Vue在数组的原始操作方法上包裹了重新解析模板的⽅法,也就是说我们在data里面的数组操作方法不是原生的,是vue封装过的
- 哪些数组操作方法经过了封装?