
发表日期: 2021-04-01 11:08:23 浏览次数:129
衡东400电话办理【衡东网站公司】衡东百度优化、衡东域名注册、衡东网店美工、衡东微信公众号托管
衡东县,隶属于湖南省衡阳市,位于湖南东部偏南,居湘江中游的衡阳盆地与醴攸盆地之间。东连攸县,南与安仁县、衡南县为邻,西部是50公里长、400米宽的湘江与衡山县隔水分界,北与渌口区接壤。该县森林覆盖率达到51%,是“全国造林绿化百佳县”。
有“鱼米之乡”、“皮影戏之乡”、“花鼓戏之乡”、“剪纸之乡”和“印章之乡”之称,是湖南省截止2014年唯一冠名的“土菜名县”。
2015年,根据衡东县乡镇区划调整方案,调整后下辖2乡15镇:踏庄、珍珠2个乡和城关镇成建制合并设立洣水镇。德圳、栗木、莫井3个乡和吴集镇成建制合并设立吴集镇。大桥镇、三樟乡成建制合并设立三樟镇。草市镇、高塘乡成建制合并设立草市镇。
本轮乡镇行政区划调整,衡东县共撤销7个乡级建制,现辖石滩、南湾2个乡,洣水、吴集、三樟、草市、大浦、新塘、霞流、甘溪、杨桥、荣桓、蓬源、石湾、白莲、杨林、高湖15个镇。县人民政府驻洣水镇(原县人民政府驻地)。
2016年末全县常住人口为63.82万人,全县实现地区生产总值261.70亿元,同比增长7.9%。
这种使用双大括号来绑定变量的方式,我们称之为数据绑定。它是怎么实现的呢,前面也有大致提到,数据绑定的过程其实不复杂:
(1) 解析语法生成 AST。
(2) 根据 AST 结果生成 DOM。
(3) 将数据绑定更新至模板。
上述这个过程,是 Vue 中模板引擎在做的事情。我们来看看上面在 Vue 里的代码片段<div>{{ message }}</div>,我们可以通过 DOM 元素捕获,解析后获得这样一个 AST 对象:
thisDiv = {
dom: {
type: "dom",
ele: "div",
nodeIndex: 0,
children: [{ type: "text", value: "" }]
},
binding: [{ type: "dom", nodeIndex: 0, valueName: "message" }]};复制代码这样,我们在生成一个 DOM 的时候,同时添加对message的监听,数据更新时我们会找到对应的nodeIndex,更新值:
// 假设这是一个生成 DOM 的过程,包括 innerHTML 和事件监听function generateDOM(astObject) {
const { dom, binding = [] } = astObject;
// 生成DOM,这里假装当前节点是baseDom
baseDom.innerHTML = getDOMString(dom);
// 对于数据绑定的,来进行监听更新吧
baseDom.addEventListener("data:change", (name, value) => {
// 寻找匹配的数据绑定
const obj = binding.find(x => x.valueName == name);
// 若找到值绑定的对应节点,则更新其值。
if (obj) {
baseDom.find(`[data-node-index="${obj.nodeIndex}"]`).innerHTML = value;
}
});}// 获取DOM字符串,这里简单拼成字符串function getDOMString(domObj) {
// 无效对象返回''
if (!domObj) return "";
const { type, children = [], nodeIndex, ele, value } = domObj;
if (type == "dom") {
// 若有子对象,递归返回生成的字符串拼接
const childString = "";
children.forEach(x => {
childString += getDOMString(x);
});
// dom对象,拼接生成对象字符串
return `<${ele} data-node-index="${nodeIndex}">${childString}</${ele}>`;
} else if (type == "text") {
// 若为textNode,返回text的值
return value;
}}复制代码这样,我们就能在message变量更新的时候,通过该变量关联的引用,来自动更新对应展示的内容。而要知道message变量什么时候进行了改变,我们需要对数据进行监听。
我们能看到,上面的简单代码描述过程中,使用的数据监听方法是用了addEventListener("data:change", Function)的方式。其实每个框架都会有自己的方式,例如 Angular 使用的则是大家都熟知的脏检查。
(1) Angular: watch 机制
脏检查是什么呢?在 AngularJS 中,并不直接监听数据的变动,而是监听常见的事件如用户交互(点击、输入等)、定时器、生命周期等。在每次事件触发完毕后,计算数据的新值和旧值是否有差异,若有差异则更新页面,并触发下一次的脏检查,直到没有差异或是次数达到设定阈值。很显然,这样每一次脏检查可能会形成环状,导致死循环。虽然 AngularJS 有阈值控制,但也无法避免这种机制所导致的低效甚至性能问题。
由于设计上存在的这些问题一直被大家诟病,在 Angular2 中应用的组织类似 DOM,也是树结构的,脏检查会从根组件开始,自上而下对树上的所有子组件进行检查。相比 AngularJS 中的带有环的结构,这样的单向数据流效率更高,而且容易预测,性能上也有不少的提升。
(2) React: 手动 set 写入
在 React 里,是需要手动调用set()的方式写入数据来更新模版。
(3) Vue: Getter/Setter
而在 Vue 中,主要是依赖了Getter/Setter:
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
// getter
get: function reactiveGetter() {
const value = getter ? getter.call(obj) : val;
if (Dep.target) {
dep.depend();
if (childOb) {
childOb.dep.depend();
if (Array.isArray(value)) {
dependArray(value);
}
}
}
return value;
},
// setter,最终更新后会通知噢
set: function reactiveSetter(newVal) {
const value = getter ? getter.call(obj) : val;
if (newVal === value || (newVal !== newVal && value !== value)) {
return;
}
if (process.env.NODE_ENV !== "production" && customSetter) {
customSetter();
}
if (getter && !setter) return;
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = !shallow && observe(newVal);
dep.notify();
}});复制代码在数据更新的时候就执行了模板更新、watch、computed 等一些工作,而 Vue3.0 将使用Proxy的方式来进行,可参考《第 16 章 关于 Vue 3.0》。
模板引擎还可以协助预防下 XSS 相关漏洞。我们知道,XSS 的整个攻击过程大概为:
(1) 通常页面中包含的用户输入内容都在固定的容器或者属性内,以文本的形式展示。
(2) 攻击者利用这些页面的用户输入片段,拼接特殊格式的字符串,突破原有位置的限制,形成了代码片段。
(3) 攻击者通过在目标网站上注入脚本,使之在用户的浏览器上运行,从而引发潜在风险。
避免 XSS 的方法之一主要是将用户所提供的内容进行过滤,而大多数模板引擎会自带 HTML 转义功能。在 Vue 中,默认的数据绑定方式(双大括号、v-bind等)会进行 HTML 转义,将数据解释为普通文本,而非 HTML 代码。来感受下这堆正则和转义,篇幅关系,只贴一部分来观摩下:
// 元素标签和属性相关的正则表达式const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`;const qnameCapture = `((?:${ncname}\\:)?${ncname})`;const startTagOpen = new RegExp(`^<${qnameCapture}`);const startTagClose = /^\s*(\/?)>/;const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`);const doctype = /^<!DOCTYPE [^>]+>/i;// 避免注释中被处理掉const comment = /^<!\--/;const conditionalComment = /^<!\[/;// 特殊元素处理export const isPlainTextElement = makeMap("script,style,textarea", true);const reCache = {};// 转义const decodingMap = {
"<": "<",
">": ">",
""": '"',
"&": "&",
" ": "\n",
"	": "\t",
"'": "'"};复制代码当然,如果你一定要输出 HTML 代码,也可以使用v-html指令输出。官方文档也有特殊说明:你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。
Vue 中大多数能力都依赖于模板引擎,包括组件化管理、事件管理、Vue 实例、生命周期等等,更多的能力阅读,大家感兴趣的可以去翻一下 Vue 源码,相信你理解了 AST、虚拟 DOM、数据绑定相关的机制之后,再去翻阅源码看具体的实现也不再是难事了

服务热线
顶部
备案号: 苏ICP备11067224号
CopyRight © 2011 书生商友信息科技 All Right Reserved
24小时服务热线:400-111-6878 E-MAIL:1120768800@qq.com QQ:1120768800
网址: http://www.768800.com 网站建设:上往建站
关键词: 网站建设| 域名邮箱| 服务器空间| 网站推广| 上往建站| 网站制作| 网站设计| 域名注册| 网络营销| 网站维护|
企业邮箱| 虚拟主机| 网络建站| 网站服务| 网页设计| 网店美工设计| 网站定制| 企业建站| 网站设计制作| 网页制作公司|
400电话办理| 书生商友软件| 葬花网| 调温纤维| 海洋馆运营维护| 北京保安公司| 殡仪馆服务| 殡葬服务| 苏州殡葬一条龙| 朝阳殡葬| 苏州殡葬服务|
欢迎您免费咨询,请填写以下信息,我们收到后会尽快与您联系
服务热线:400-111-6878