🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] ## 1 (web\compiler\) web编译目录 ### 1-1 目录层次 ~~~ compiler\directives html.js ;html指令 text.js ;text指令 model.js ;model指令 index.js ;指令编译入口 ~~~ ### 1-2 html指令编译 >[info] import ~~~ ;(导入)添加prop接口 import { addProp } from 'compiler/helpers' ~~~ >[info] module ~~~ ;html解析编译 export default function html (el, dir) { if (!dir.value) return addProp(el, 'innerHTML', `__toString__(${dir.value})`) } ~~~ >[info] export ~~~ ;(导出)html解析接口 export default function html (el, dir) {} ~~~ ### 1-3 text解析 >[info] import ~~~ import { addProp } from 'compiler/helpers' ~~~ >[info] module ~~~ ;text指令解析编译 export default function text (el, dir) { if (!dir.value) return addProp(el, 'textContent', `__toString__(${dir.value})`) } ~~~ >[info] export ~~~ ;(导出)text指令解析编译 export default function text (el, dir) {} ~~~ ### 1-4 model指令解析 >[info] import ~~~ ;(导入)添加事件处理,添加prop,获取绑定属性 import { addHandler, addProp, getBindingAttr } from 'compiler/helpers' ~~~ >[info] module ~~~ ;v-model 模型指令解析入口 export default function model (el, dir) { ;dir.value,dir.modifiers const value = dir.value const modifiers = dir.modifiers ;el类型select,checkbox,radio if (el.tag === 'select') { if (el.attrsMap.multiple != null) { genMultiSelect(el, value) } else { genSelect(el, value) } } else { ;el类型checkbox,radio,input switch (el.attrsMap.type) { case 'checkbox': genCheckboxModel(el, value) break case 'radio': genRadioModel(el, value) break default: return genDefaultModel(el, value, modifiers) } } } ;创建Checkbox模型 function genCheckboxModel (el, value) { const valueBinding = getBindingAttr(el, 'value') addProp(el, 'checked', `Array.isArray(${value})` + `?(${value}).indexOf(${valueBinding})>-1` + `:!!(${value})` ) addHandler(el, 'change', `var $$a=${value},` + '$$el=$event.target,' + '$$c=$$el.checked;' + 'if(Array.isArray($$a)){' + `var $$v=${valueBinding},` + '$$i=$$a.indexOf($$v);' + 'if($$c){$$i<0&&$$a.push($$v)}' + 'else{$$i>-1&&$$a.splice($$i,1)}' + `}else{${value}=$$c}` ) } ;创建Radio模型 function genRadioModel (el, value) { const valueBinding = getBindingAttr(el, 'value') addProp(el, 'checked', `(${value}==${valueBinding})`) addHandler(el, 'change', `${value}=${valueBinding}`) } ;创建默认模型input function genDefaultModel (el, value, modifiers) { const type = el.attrsMap.type const { lazy, number, trim } = modifiers || {} const event = lazy ? 'change' : 'input' const needCompositionGuard = !lazy && type !== 'range' const valueExpression = `$event.target.value${trim ? '.trim()' : ''}` let code = number || type === 'number' ? `${value}=Number(${valueExpression})` : `${value}=${valueExpression}` if (needCompositionGuard) { code = `if($event.target.composing)return;${code}` } addProp(el, 'value', `(${value})`) addHandler(el, event, code) if (needCompositionGuard) { // need runtime directive code to help with composition events return true } } ;select值代码 const getSelectedValueCode = 'Array.prototype.filter' + '.call($event.target.options,function(o){return o.selected})' + '.map(function(o){return "_value" in o ? o._value : o.value})' ;select子选项修改 function patchChildOptions (el, fn) { for (let i = 0; i < el.children.length; i++) { const c = el.children[i] if (c.tag === 'option') { addProp(c, 'selected', fn(getBindingAttr(c, 'value'))) } } } ;生成select function genSelect (el, value) { addHandler(el, 'change', `${value}=${getSelectedValueCode}[0]`) patchChildOptions(el, valueBinding => `$(${value})===(${valueBinding})`) } ;生成MultiSelect function genMultiSelect (el, value) { addHandler(el, 'change', `${value}=${getSelectedValueCode}`) patchChildOptions(el, valueBinding => `$(${value}).indexOf(${valueBinding})>-1`) } ~~~ >[info] export ~~~ ;(导出)model解析编译 ~~~ ### 1-5 index.js web编译入口 >[info] import ~~~ ;(导入)model指令解析,text指令解析,html指令解析 import model from './model' import text from './text' import html from './html' ~~~ >[info] export ~~~ ;(导出)model,text,html指令解析 export default { model, text, html } ~~~