From 23b83143fb05a10d8849cd25637b5d4df86cd732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=87=E5=A4=A9?= Date: Wed, 19 Aug 2020 19:07:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=A4=A7=E6=B3=A2=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/directives/expr.js | 6 +- src/directives/for.js | 4 +- src/filters/array.js | 1 - src/renders/domRender.js | 6 +- src/renders/serverRender.js | 33 ---------- src/renders/share.js | 14 ++--- src/seed/core.js | 4 +- src/seed/index.js | 57 ++++++++--------- src/vmodel/modern.js | 4 +- src/vmodel/proxy.js | 115 +++++++++++++++++----------------- src/vmodel/reserved.js | 4 +- src/vmodel/share.js | 119 +++++------------------------------- 12 files changed, 120 insertions(+), 247 deletions(-) delete mode 100644 src/renders/serverRender.js diff --git a/src/directives/expr.js b/src/directives/expr.js index 54b5e06..1267bb8 100644 --- a/src/directives/expr.js +++ b/src/directives/expr.js @@ -1,10 +1,12 @@ import Anot from '../seed/index' +//https://github.com/RubyLouvre/avalon/issues/1834 Anot.directive('expr', { update: function(vdom, value) { value = value == null || value === '' ? '\u200b' : value vdom.nodeValue = value - //https://github.com/RubyLouvre/Anot/issues/1834 - if (vdom.dom) vdom.dom.data = value + if (vdom.dom) { + vdom.dom.data = value + } } }) diff --git a/src/directives/for.js b/src/directives/for.js index 1acb6ec..e0f2924 100644 --- a/src/directives/for.js +++ b/src/directives/for.js @@ -8,7 +8,7 @@ import { } from '../seed/core' import { VFragment } from '../vdom/VFragment' -import { $$skipArray } from '../vmodel/reserved' +import { SYS_SKIP } from '../vmodel/reserved' import { addScope, makeHandle } from '../parser/index' import { updateView } from './duplex/share' @@ -145,7 +145,7 @@ function createFragments(instance, obj) { instance.fragments = fragments } else { Anot.each(obj, function(key, value) { - if (!(key in $$skipArray)) { + if (!(key in SYS_SKIP)) { var k = array ? getTraceKey(value) : key fragments.push(new VFragment([], k, value, i++)) ids.push(k) diff --git a/src/filters/array.js b/src/filters/array.js index 214d1a2..bdd9b09 100644 --- a/src/filters/array.js +++ b/src/filters/array.js @@ -1,5 +1,4 @@ import { Anot, escapeRegExp, isObject } from '../seed/core' -import { $$skipArray } from '../vmodel/reserved' export function orderBy(array, by, decend) { var type = Anot.type(array) diff --git a/src/renders/domRender.js b/src/renders/domRender.js index de1a69f..ea8fe05 100644 --- a/src/renders/domRender.js +++ b/src/renders/domRender.js @@ -9,7 +9,7 @@ import { orphanTag } from '../vtree/orphanTag' import { parseAttributes, eventMap } from '../parser/attributes' import { parseInterpolate } from '../parser/interpolate' -import { startWith, groupTree, dumpTree, getRange } from './share' +import { groupTree, dumpTree, getRange } from './share' var viewID @@ -110,7 +110,7 @@ class Render { * @returns {undefined} */ scanComment(vdom, scope, parentChildren) { - if (startWith(vdom.nodeValue, 'ms-for:')) { + if (vdom.nodeValue.startsWith('ms-for:')) { this.getForBinding(vdom, scope, parentChildren) } } @@ -134,7 +134,7 @@ class Render { if (attr.charAt(0) === ':') { attr = 'ms-' + attr.slice(1) } - if (startWith(attr, 'ms-')) { + if (attr.startsWith('ms-')) { dirs[attr] = value var type = attr.match(/\w+/g)[1] type = eventMap[type] || type diff --git a/src/renders/serverRender.js b/src/renders/serverRender.js deleted file mode 100644 index cb890d5..0000000 --- a/src/renders/serverRender.js +++ /dev/null @@ -1,33 +0,0 @@ -function serverRender(vm, str) { - var nodes = Anot.lexer(str) - var templates = {} - collectTemplate(nodes, templates) - var render = Anot.scan(str) - var html = Anot.vdom(render.root, 'toHTML', false) - return { - templates: templates, - html: html - } -} - -function collectTemplate(vdoms, obj) { - for (var i = 0, el; (el = vdoms[i++]); ) { - var props = el.props - if (props) { - var id = - props['ms-controller'] || - props[':controller'] || - props['ms-important'] || - props[':important'] - if (id) { - obj[id] = Anot.VElement.prototype.toHTML.call(el, true) - continue - } - } - if (el.children) { - collectTemplate(el.children, obj) - } - } -} - -if (typeof module === 'object') module.exports = serverRender diff --git a/src/renders/share.js b/src/renders/share.js index 19881a5..b301f79 100644 --- a/src/renders/share.js +++ b/src/renders/share.js @@ -60,14 +60,16 @@ export function dumpTree(elem) { export function getRange(childNodes, node) { var i = childNodes.indexOf(node) + 1 - var deep = 1, - nodes = [], - end + var deep = 1 + var nodes = [] + var end + nodes.start = i + while ((node = childNodes[i++])) { nodes.push(node) if (node.nodeName === '#comment') { - if (startWith(node.nodeValue, 'ms-for:')) { + if (node.nodeValue.startsWith('ms-for:')) { deep++ } else if (node.nodeValue === 'ms-for-end:') { deep-- @@ -83,10 +85,6 @@ export function getRange(childNodes, node) { return nodes } -export function startWith(long, short) { - return long.indexOf(short) === 0 -} - var appendChildMayThrowError = { '#text': 1, '#comment': 1, diff --git a/src/seed/core.js b/src/seed/core.js index 25862cb..44c1a20 100644 --- a/src/seed/core.js +++ b/src/seed/core.js @@ -158,7 +158,9 @@ Object.assign(Anot, { remove: function(target, item) { //移除数组中第一个匹配传参的那个元素,返回布尔表示成功与否 var index = target.indexOf(item) - if (~index) return Anot.Array.removeAt(target, index) + if (~index) { + return Anot.Array.removeAt(target, index) + } return false } }, diff --git a/src/seed/index.js b/src/seed/index.js index 417c4fb..a8ff726 100644 --- a/src/seed/index.js +++ b/src/seed/index.js @@ -7,15 +7,16 @@ var rarraylike = /(Array|List|Collection|Map|Arguments|Set)\]$/ // Anot.type var class2type = {} -'Boolean,Number,String,Function,Array,Date,RegExp,Object,Error,AsyncFunction,Promise,Generator,GeneratorFunction' +var types = + 'Boolean,Number,String,Function,Array,Date,RegExp,Object,Error,AsyncFunction,Promise,Generator,GeneratorFunction' + +types .split(',') - .forEach(function(name) { - class2type['[object ' + name + ']'] = name.toLowerCase() - }) + .forEach(name => (class2type[`[object ${name}]`] = name.toLowerCase())) Anot.type = function(obj) { + // 早期的webkit内核浏览器实现了已废弃的ecma262v4标准,可以将正则字面量当作函数使用,因此typeof在判定正则时会返回function if (obj) { - // 早期的webkit内核浏览器实现了已废弃的ecma262v4标准,可以将正则字面量当作函数使用,因此typeof在判定正则时会返回function return typeof obj === 'object' || typeof obj === 'function' ? class2type[inspect.call(obj)] || 'object' : typeof obj @@ -23,20 +24,10 @@ Anot.type = function(obj) { return String(obj) } -Anot.isFunction = function(fn) { - return typeof fn === 'function' -} - -Anot.isWindow = function(obj) { - return rwindow.test(inspect.call(obj)) -} - /*判定是否是一个朴素的javascript对象(Object),不是DOM对象,不是BOM对象,不是自定义类的实例*/ Anot.isPlainObject = function(obj) { - // 简单的 typeof obj === 'object'检测,会致使用isPlainObject(window)在opera下通不过 return ( - inspect.call(obj) === '[object Object]' && - Object.getPrototypeOf(obj) === Object.prototype + typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype ) } @@ -75,24 +66,26 @@ Anot.init = function(source) { throw new Error(`vm实例[${id}]已经存在`) } vm = platform.modelFactory(source) + + console.log('+++++++++++', vm) Anot.vmodels[id] = vm - Anot.nextTick(function() { - let $elem = document.querySelector('[anot=' + vm.$id + ']') - if ($elem) { - if ($elem === document.body) { - Anot.scan($elem) - } else { - let _parent = $elem - while ((_parent = _parent.parentNode)) { - if (_parent.__VM__) { - break - } - } - Anot.scan($elem.parentNode, _parent && _parent.__VM__) - } - } - }) + // Anot.nextTick(function() { + // let $elem = document.querySelector('[anot=' + vm.$id + ']') + // if ($elem) { + // if ($elem === document.body) { + // Anot.scan($elem) + // } else { + // let _parent = $elem + // while ((_parent = _parent.parentNode)) { + // if (_parent.__VM__) { + // break + // } + // } + // Anot.scan($elem.parentNode, _parent && _parent.__VM__) + // } + // } + // }) } return vm } diff --git a/src/vmodel/modern.js b/src/vmodel/modern.js index 3cade54..1c11339 100644 --- a/src/vmodel/modern.js +++ b/src/vmodel/modern.js @@ -1,5 +1,5 @@ import { Anot, platform } from '../seed/core' -import { $$skipArray } from './reserved' +import { SYS_SKIP } from './reserved' import { Action } from './Action' import './share' import './ProxyArray' @@ -58,7 +58,7 @@ export function fireFactory(core) { export function afterCreate(vm, core, keys, bindThis) { var ac = vm.$accessors //隐藏系统属性 - for (var key in $$skipArray) { + for (var key in SYS_SKIP) { hideProperty(vm, key, vm[key]) } //为不可监听的属性或方法赋值 diff --git a/src/vmodel/proxy.js b/src/vmodel/proxy.js index 6e81cbc..a3458b6 100644 --- a/src/vmodel/proxy.js +++ b/src/vmodel/proxy.js @@ -1,63 +1,9 @@ import { Anot, platform, isObject } from '../seed/core' -import { $$skipArray } from './reserved' +import { SYS_SKIP } from './reserved' import { Mutation } from './Mutation' import { Computed } from './Computed' import { IProxy, canHijack, createProxy } from './share' -platform.modelFactory = function modelFactory(definition, dd) { - var clone = {} - for (let i in definition) { - clone[i] = definition[i] - delete definition[i] - } - - definition.$id = clone.$id - var proxy = new IProxy(definition, dd) - - var vm = toProxy(proxy) - //先添加普通属性与监控属性 - for (let i in clone) { - vm[i] = clone[i] - } - var $computed = clone.$computed - //再添加计算属性 - if ($computed) { - delete clone.$computed - for (let i in $computed) { - let val = $computed[i] - if (typeof val === 'function') { - let _val = val - val = { get: _val } - } - if (val && val.get) { - val.getter = val.get - //在set方法中的target是IProxy,需要重写成Proxy,才能依赖收集 - val.vm = vm - if (val.set) val.setter = val.set - $computed[i] = val - delete clone[i] //去掉重名的监控属性 - } else { - delete $computed[i] - } - } - for (let i in $computed) { - vm[i] = $computed[i] - } - } - - return vm -} - -//https://developer.mozilla.org/en-US/docs/Archive/Web/Old_Proxy_API -function toProxy(definition) { - return Proxy.create - ? Proxy.create(definition, traps) - : new Proxy(definition, traps) -} - -function wrapIt(str) { - return '☥' + str + '☥' -} var traps = { deleteProperty(target, name) { if (target.hasOwnProperty(name)) { @@ -89,7 +35,7 @@ var traps = { if (name === '$model' || name === '$track') { return true } - if (name in $$skipArray) { + if (name in SYS_SKIP) { target[name] = value return true } @@ -126,13 +72,68 @@ var traps = { //has 只能用于 in 操作符,没什么用删去 } +function wrapIt(str) { + return '☥' + str + '☥' +} + function updateTrack(target, name) { var arr = target.$track.match(/[^☥]+/g) || [] arr.push(name) target.$track = arr.sort().join('☥') } -Anot.itemFactory = platform.itemFactory = function itemFactory(before, after) { +platform.modelFactory = function(definition, dd) { + var clone = {} + for (let i in definition) { + clone[i] = definition[i] + delete definition[i] + } + + definition.$id = clone.$id + var proxy = new IProxy(definition, dd) + + var vm = new Proxy(proxy, traps) + var { state, props, watch, methods, mounted, computed } = clone + + console.log('--------------', vm) + //先添加普通属性与监控属性 + for (let i in state) { + vm[i] = state[i] + } + for (let i in methods) { + vm[i] = methods[i] + } + //再添加计算属性 + if (computed) { + delete clone.computed + for (let i in computed) { + let val = computed[i] + if (typeof val === 'function') { + let _val = val + val = { get: _val } + } + if (val && val.get) { + val.getter = val.get + //在set方法中的target是IProxy,需要重写成Proxy,才能依赖收集 + val.vm = vm + if (val.set) { + val.setter = val.set + } + computed[i] = val + delete state[i] //去掉重名的监控属性 + } else { + delete computed[i] + } + } + for (let i in computed) { + vm[i] = computed[i] + } + } + + return vm +} + +Anot.itemFactory = platform.itemFactory = function(before, after) { var definition = before.$model definition.$proxyItemBackdoor = true definition.$id = diff --git a/src/vmodel/reserved.js b/src/vmodel/reserved.js index fc22573..2167a58 100644 --- a/src/vmodel/reserved.js +++ b/src/vmodel/reserved.js @@ -1,5 +1,5 @@ /** -$$skipArray:是系统级通用的不可监听属性 +SYS_SKIP:是系统级通用的不可监听属性 $skipArray: 是当前对象特有的不可监听属性 不同点是 @@ -7,7 +7,7 @@ $skipArray: 是当前对象特有的不可监听属性 $skipArray被hasOwnProperty后返回true */ var falsy -export var $$skipArray = { +export var SYS_SKIP = { $id: falsy, $render: falsy, $track: falsy, diff --git a/src/vmodel/share.js b/src/vmodel/share.js index dc67af4..ec5b3e4 100644 --- a/src/vmodel/share.js +++ b/src/vmodel/share.js @@ -1,15 +1,16 @@ import { Anot, platform, isObject, makeHashCode } from '../seed/core' -import { $$skipArray } from './reserved' +import { SYS_SKIP } from './reserved' import { Mutation } from './Mutation' import { Computed } from './Computed' +var $proxyItemBackdoorMap = {} + /** * 这里放置ViewModel模块的共用方法 * IProxy, 基本用户数据产生的一个数据对象,基于$model与vmodel之间的形态 * modelFactory: 生成用户VM * canHijack: 判定此属性是否该被劫持,加入数据监听与分发的的逻辑 * createProxy: listFactory与modelFactory的封装 - * createAccessor: 实现数据监听与分发的重要对象 * itemFactory: ms-for循环中产生的代理VM的生成工厂 * fuseFactory: 两个ms-controller间产生的代理VM的生成工厂 */ @@ -18,21 +19,25 @@ import { Computed } from './Computed' * Anot改用Proxy来创建VM,因此 */ -export function IProxy(definition, dd) { - Anot.mix(this, definition) - Anot.mix(this, $$skipArray) +export function IProxy(source, dd) { + // var { state, props, watch, methods, mounted } = source + + // console.log(state, methods) + Anot.mix(this, source) + Anot.mix(this, SYS_SKIP) this.$hashcode = makeHashCode('$') this.$id = this.$id || this.$hashcode this.$events = { __dep__: dd || new Mutation(this.$id) } - + // console.log('***********', this.$id) delete this.$mutations + this.$accessors = {} this.$computed = {} this.$track = '' - if (dd === void 0) { + if (dd === undefined) { this.$watch = platform.watchFactory(this.$events) this.$fire = platform.fireFactory(this.$events) } else { @@ -41,50 +46,10 @@ export function IProxy(definition, dd) { } } -platform.modelFactory = function modelFactory(definition, dd) { - var $computed = definition.$computed || {} - delete definition.$computed - var core = new IProxy(definition, dd) - var $accessors = core.$accessors - var keys = [] - - platform.hideProperty(core, '$mutations', {}) - - for (let key in definition) { - if (key in $$skipArray) continue - var val = definition[key] - keys.push(key) - if (canHijack(key, val)) { - $accessors[key] = createAccessor(key, val) - } - } - for (let key in $computed) { - if (key in $$skipArray) continue - var val = $computed[key] - if (typeof val === 'function') { - val = { - get: val - } - } - if (val && val.get) { - val.getter = val.get - val.setter = val.set - Anot.Array.ensure(keys, key) - $accessors[key] = createAccessor(key, val, true) - } - } - //将系统API以unenumerable形式加入vm, - //添加用户的其他不可监听属性或方法 - //重写$track - //并在IE6-8中增添加不存在的hasOwnPropert方法 - var vm = platform.createViewModel(core, $accessors, core) - platform.afterCreate(vm, core, keys, !dd) - return vm -} -var $proxyItemBackdoorMap = {} - export function canHijack(key, val, $proxyItemBackdoor) { - if (key in $$skipArray) return false + if (key in SYS_SKIP) { + return false + } if (key.charAt(0) === '$') { if ($proxyItemBackdoor) { if (!$proxyItemBackdoorMap[key]) { @@ -120,60 +85,6 @@ export function createProxy(target, dd) { platform.createProxy = createProxy -platform.itemFactory = function itemFactory(before, after) { - var keyMap = before.$model - var core = new IProxy(keyMap) - var state = Object.assign(core.$accessors, before.$accessors) //防止互相污染 - var data = after.data - //core是包含系统属性的对象 - //keyMap是不包含系统属性的对象, keys - for (var key in data) { - var val = (keyMap[key] = core[key] = data[key]) - state[key] = createAccessor(key, val) - } - var keys = Object.keys(keyMap) - var vm = platform.createViewModel(core, state, core) - platform.afterCreate(vm, core, keys) - return vm -} - -function createAccessor(key, val, isComputed) { - var mutation = null - var Accessor = isComputed ? Computed : Mutation - return { - get: function Getter() { - if (!mutation) { - mutation = new Accessor(key, val, this) - } - return mutation.get() - }, - set: function Setter(newValue) { - if (!mutation) { - mutation = new Accessor(key, val, this) - } - mutation.set(newValue) - }, - enumerable: true, - configurable: true - } -} - -platform.fuseFactory = function fuseFactory(before, after) { - var keyMap = Anot.mix(before.$model, after.$model) - var core = new IProxy( - Anot.mix(keyMap, { - $id: before.$id + after.$id - }) - ) - var state = Anot.mix(core.$accessors, before.$accessors, after.$accessors) //防止互相污染 - - var keys = Object.keys(keyMap) - //将系统API以unenumerable形式加入vm,并在IE6-8中添加hasOwnPropert方法 - var vm = platform.createViewModel(core, state, core) - platform.afterCreate(vm, core, keys, false) - return vm -} - function toJson(val) { var xtype = Anot.type(val) if (xtype === 'array') {