This repository has been archived on 2023-08-30. You can view files and clone it, but cannot push or open issues/pull-requests.
bytedo
/
anot
Archived
1
0
Fork 0

移除部分兼容处理;移除表单验证指令

master
宇天 2020-08-17 19:04:17 +08:00
parent 8b21f0a800
commit 099378aedd
12 changed files with 273 additions and 298 deletions

View File

@ -8,13 +8,13 @@ import './text'
import './css'
import './expr'
import './attr.modern'
import './attr'
import './html'
import './if'
import './on'
import './for'
import './class.hover.active'
import './duplex/modern'
import './rules'
import './validate'
import './duplex/index'
// import './rules'
// import './validate'

View File

@ -1,10 +1,6 @@
import { Anot, escapeRegExp } from '../seed/core'
import { $$skipArray } from '../vmodel/reserved'
/*
https://github.com/hufyhang/orderBy/blob/master/index.js
*/
export function orderBy(array, by, decend) {
var type = Anot.type(array)
if (type !== 'array' && type !== 'object') throw 'orderBy只能处理对象或数组'
@ -88,14 +84,7 @@ export function filterBy(array, search, ...args) {
var target = isArray ? [] : {}
__repeat(array, isArray, function(key) {
var val = array[key]
if (
criteria.apply(
{
key: key
},
[val, key].concat(args)
)
) {
if (criteria.apply({ key }, [val, key].concat(args))) {
if (isArray) {
target.push(val)
} else {
@ -121,7 +110,9 @@ export function selectBy(data, array, defaults) {
export function limitBy(input, limit, begin) {
var type = Anot.type(input)
if (type !== 'array' && type !== 'object') throw 'limitBy只能处理对象或数组'
if (type !== 'array' && type !== 'object') {
throw 'limitBy只能处理对象或数组'
}
//必须是数值
if (typeof limit !== 'number') {
return input

View File

@ -3,7 +3,7 @@ import { fromDOM } from '../vtree/fromDOM'
import { fromString } from '../vtree/fromString'
import { VFragment } from '../vdom/VFragment'
import { Directive } from './Directive'
import { Directive } from './directive'
import { orphanTag } from '../vtree/orphanTag'
import { parseAttributes, eventMap } from '../parser/attributes'
@ -11,6 +11,8 @@ import { parseInterpolate } from '../parser/interpolate'
import { startWith, groupTree, dumpTree, getRange } from './share'
var viewID
/**
* 生成一个渲染器,并作为它第一个遇到的ms-controller对应的VM的$render属性
* @param {String|DOM} node
@ -25,17 +27,18 @@ Anot.scan = function(node, vm, beforeReady) {
/**
* Anot.scan 的内部实现
*/
function Render(node, vm, beforeReady) {
this.root = node //如果传入的字符串,确保只有一个标签作为根节点
this.vm = vm
this.beforeReady = beforeReady
this.bindings = [] //收集待加工的绑定属性
this.callbacks = []
this.directives = []
this.init()
}
Render.prototype = {
class Render {
constructor(node, vm, beforeReady) {
this.root = node //如果传入的字符串,确保只有一个标签作为根节点
this.vm = vm
this.beforeReady = beforeReady
this.bindings = [] //收集待加工的绑定属性
this.callbacks = []
this.directives = []
this.init()
}
/**
* 开始扫描指定区域
* 收集绑定属性
@ -50,15 +53,13 @@ Render.prototype = {
} else if (typeof this.root === 'string') {
vnodes = fromString(this.root) //转换虚拟DOM
} else {
return console.warn(
'Anot.scan first argument must element or HTML string'
)
return console.warn('Anot.scan()第1个参数,只能是节点对象或节点字符串')
}
this.root = vnodes[0]
this.vnodes = vnodes
this.scanChildren(vnodes, this.vm, true)
},
}
scanChildren(children, scope, isRoot) {
for (var i = 0; i < children.length; i++) {
@ -81,7 +82,7 @@ Render.prototype = {
if (isRoot) {
this.complete()
}
},
}
/**
* 从文本节点获取指令
@ -99,7 +100,7 @@ Render.prototype = {
}
])
}
},
}
/**
* 从注释节点获取指令
@ -112,7 +113,7 @@ Render.prototype = {
if (startWith(vdom.nodeValue, 'ms-for:')) {
this.getForBinding(vdom, scope, parentChildren)
}
},
}
/**
* 从元素节点的nodeName与属性中获取指令
@ -223,7 +224,7 @@ Render.prototype = {
) {
this.scanChildren(children, scope, false)
}
},
}
/**
* 将绑定属性转换为指令
@ -245,7 +246,7 @@ Render.prototype = {
fn()
}
this.optimizeDirectives()
},
}
/**
* 将收集到的绑定属性进行深加工,最后转换指令
@ -276,7 +277,7 @@ Render.prototype = {
this.directives.push(directive)
}
}
},
}
/**
* 修改指令的update与callback方法,让它们以后执行时更加高效
@ -288,12 +289,13 @@ Render.prototype = {
el.update = newUpdate
el._isScheduled = false
}
},
update: function() {
}
update() {
for (var i = 0, el; (el = this.directives[i++]); ) {
el.update()
}
},
}
/**
* 销毁所有指令
@ -308,7 +310,7 @@ Render.prototype = {
for (let i in this) {
if (i !== 'dispose') delete this[i]
}
},
}
/**
* 将循环区域转换为for指令
@ -341,7 +343,7 @@ Render.prototype = {
parentChildren
}
])
},
}
/**
* 在带ms-for元素节点旁添加两个注释节点,组成循环区域
@ -370,7 +372,6 @@ Render.prototype = {
this.getForBinding(begin, scope, parentChildren, props['data-for-rendered'])
}
}
var viewID
function newUpdate() {
var oldVal = this.beforeUpdate()

View File

@ -8,104 +8,98 @@
removed <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- <-- added
*/
export function Cache(maxLength) {
export class Cache {
constructor(maxLength) {
// 标识当前缓存数组的大小
this.size = 0
// 标识缓存数组能达到的最大长度
// 标识缓存数组能达到的最大长度
this.limit = maxLength
// head最不常用的项tail最常用的项全部初始化为undefined
// head最不常用的项tail最常用的项全部初始化为undefined
this.head = this.tail = void 0
this._keymap = {}
}
}
Cache.prototype = {
put(key, value) {
var entry = {
key: key,
value: value
}
this._keymap[key] = entry
if (this.tail) {
// 如果存在tail缓存数组的长度不为0将tail指向新的 entry
this.tail.newer = entry
entry.older = this.tail
} else {
// 如果缓存数组的长度为0将head指向新的entry
this.head = entry
}
this.tail = entry
// 如果缓存数组达到上限,则先删除 head 指向的缓存对象
/* istanbul ignore if */
if (this.size === this.limit) {
this.shift()
} else {
this.size++
}
return value
},
shift() {
/* istanbul ignore next */
var entry = this.head
/* istanbul ignore if */
if (entry) {
// 删除 head ,并改变指向
this.head = this.head.newer
// 同步更新 _keymap 里面的属性值
this.head.older =
entry.newer =
entry.older =
this._keymap[entry.key] =
void 0
delete this._keymap[entry.key] //#1029
// 同步更新 缓存数组的长度
this.size--
}
},
get(key) {
var entry = this._keymap[key]
// 如果查找不到含有`key`这个属性的缓存对象
if (entry === void 0)
return
// 如果查找到的缓存对象已经是 tail (最近使用过的)
/* istanbul ignore if */
if (entry === this.tail) {
return entry.value
}
// HEAD--------------TAIL
// <.older .newer>
// <--- add direction --
// A B C <D> E
if (entry.newer) {
// 处理 newer 指向
if (entry === this.head) {
// 如果查找到的缓存对象是 head (最近最少使用过的)
// 则将 head 指向原 head 的 newer 所指向的缓存对象
this.head = entry.newer
}
// 将所查找的缓存对象的下一级的 older 指向所查找的缓存对象的older所指向的值
// 例如A B C D E
// 如果查找到的是D那么将E指向C不再指向D
entry.newer.older = entry.older // C <-- E.
}
if (entry.older) {
// 处理 older 指向
// 如果查找到的是D那么C指向E不再指向D
entry.older.newer = entry.newer // C. --> E
}
// 处理所查找到的对象的 newer 以及 older 指向
entry.newer = void 0 // D --x
// older指向之前使用过的变量即D指向E
entry.older = this.tail // D. --> E
if (this.tail) {
// 将E的newer指向D
this.tail.newer = entry // E. <-- D
}
// 改变 tail 为D
this.tail = entry
return entry.value
put(key, value) {
var entry = { key, value }
this._keymap[key] = entry
if (this.tail) {
// 如果存在tail缓存数组的长度不为0将tail指向新的 entry
this.tail.newer = entry
entry.older = this.tail
} else {
// 如果缓存数组的长度为0将head指向新的entry
this.head = entry
}
}
this.tail = entry
// 如果缓存数组达到上限,则先删除 head 指向的缓存对象
/* istanbul ignore if */
if (this.size === this.limit) {
this.shift()
} else {
this.size++
}
return value
}
shift() {
/* istanbul ignore next */
var entry = this.head
/* istanbul ignore if */
if (entry) {
// 删除 head ,并改变指向
this.head = this.head.newer
// 同步更新 _keymap 里面的属性值
this.head.older = entry.newer = entry.older = this._keymap[
entry.key
] = void 0
delete this._keymap[entry.key] //#1029
// 同步更新 缓存数组的长度
this.size--
}
}
get(key) {
var entry = this._keymap[key]
// 如果查找不到含有`key`这个属性的缓存对象
if (entry === void 0) return
// 如果查找到的缓存对象已经是 tail (最近使用过的)
/* istanbul ignore if */
if (entry === this.tail) {
return entry.value
}
// HEAD--------------TAIL
// <.older .newer>
// <--- add direction --
// A B C <D> E
if (entry.newer) {
// 处理 newer 指向
if (entry === this.head) {
// 如果查找到的缓存对象是 head (最近最少使用过的)
// 则将 head 指向原 head 的 newer 所指向的缓存对象
this.head = entry.newer
}
// 将所查找的缓存对象的下一级的 older 指向所查找的缓存对象的older所指向的值
// 例如A B C D E
// 如果查找到的是D那么将E指向C不再指向D
entry.newer.older = entry.older // C <-- E.
}
if (entry.older) {
// 处理 older 指向
// 如果查找到的是D那么C指向E不再指向D
entry.older.newer = entry.newer // C. --> E
}
// 处理所查找到的对象的 newer 以及 older 指向
entry.newer = void 0 // D --x
// older指向之前使用过的变量即D指向E
entry.older = this.tail // D. --> E
if (this.tail) {
// 将E的newer指向D
this.tail.newer = entry // E. <-- D
}
// 改变 tail 为D
this.tail = entry
return entry.value
}
}

View File

@ -24,8 +24,8 @@ export function oneObject(array, val) {
if (typeof array === 'string') {
array = array.match(rword) || []
}
var result = {},
value = val !== void 0 ? val : 1
var result = {}
var value = val !== void 0 ? val : 1
for (var i = 0, n = array.length; i < n; i++) {
result[array[i]] = value
}
@ -114,9 +114,10 @@ export var validators = {}
export var cssHooks = {}
window.Anot = Anot
Anot.platform = platform
/* istanbul ignore next */
export function createFragment() {
/* istanbul ignore next */
return document.createDocumentFragment()
}

View File

@ -6,22 +6,20 @@ var rarraylike = /(Array|List|Collection|Map|Arguments|Set)\]$/
// Anot.type
var class2type = {}
'Boolean Number String Function Array Date RegExp Object Error'.replace(
Anot.rword,
function(name) {
'Boolean,Number,String,Function,Array,Date,RegExp,Object,Error,AsyncFunction,Promise,Generator,GeneratorFunction'
.split(',')
.forEach(function(name) {
class2type['[object ' + name + ']'] = name.toLowerCase()
}
)
})
Anot.type = function(obj) {
//取得目标的类型
if (obj == null) {
return String(obj)
if (obj) {
// 早期的webkit内核浏览器实现了已废弃的ecma262v4标准可以将正则字面量当作函数使用因此typeof在判定正则时会返回function
return typeof obj === 'object' || typeof obj === 'function'
? class2type[inspect.call(obj)] || 'object'
: typeof obj
}
// 早期的webkit内核浏览器实现了已废弃的ecma262v4标准可以将正则字面量当作函数使用因此typeof在判定正则时会返回function
return typeof obj === 'object' || typeof obj === 'function'
? class2type[inspect.call(obj)] || 'object'
: typeof obj
return String(obj)
}
Anot.isFunction = function(fn) {
@ -123,8 +121,8 @@ export function isArrayLike(obj) {
}
Anot.each = function(obj, fn) {
//排除null, undefined
if (obj) {
//排除null, undefined
var i = 0
if (isArrayLike(obj)) {
for (var n = obj.length; i < n; i++) {

View File

@ -5,32 +5,34 @@ import {
propagateChanged
} from './transaction'
import { Anot, platform } from '../seed/core'
/**
*
与Computed等共享UUID
*/
export let obid = 1
export function Mutation(expr, value, vm) {
//构造函数
this.expr = expr
if (value) {
var childVm = platform.createProxy(value, this)
if (childVm) {
value = childVm
}
}
this.value = value
this.vm = vm
try {
vm.$mutations[expr] = this
} catch (ignoreIE) {}
this.uuid = ++obid
this.updateVersion()
this.mapIDs = {}
this.observers = []
}
Mutation.prototype = {
export class Mutation {
constructor(expr, value, vm) {
//构造函数
this.expr = expr
if (value) {
var childVm = platform.createProxy(value, this)
if (childVm) {
value = childVm
}
}
this.value = value
this.vm = vm
try {
vm.$mutations[expr] = this
} catch (ignoreIE) {}
this.uuid = ++obid
this.updateVersion()
this.mapIDs = {}
this.observers = []
}
get() {
if (Anot.trackingAction) {
this.collect() //被收集
@ -52,22 +54,7 @@ Mutation.prototype = {
}
}
return this.value
},
collect() {
// Anot.track(name, '被收集')
reportObserved(this)
},
updateVersion() {
this.version = Math.random() + Math.random()
},
notify() {
transactionStart()
propagateChanged(this)
transactionEnd()
},
}
set(newValue) {
var oldValue = this.value
@ -87,4 +74,18 @@ Mutation.prototype = {
this.notify()
}
}
collect() {
// Anot.track(name, '被收集')
reportObserved(this)
}
updateVersion() {
this.version = Math.random() + Math.random()
}
notify() {
transactionStart()
propagateChanged(this)
transactionEnd()
}
}

View File

@ -3,76 +3,76 @@ import { voidTag } from './voidTag'
import { makeOrphan } from './makeOrphan'
export function fromDOM(dom) {
return [from(dom)]
return [_from(dom)]
}
export function from(node) {
var type = node.nodeName.toLowerCase()
switch (type) {
case '#text':
case '#comment':
return {
nodeName: type,
dom: node,
nodeValue: node.nodeValue
}
default:
var props = markProps(node, node.attributes || [])
var vnode = {
nodeName: type,
dom: node,
isVoidTag: !!voidTag[type],
props: props
}
if(type === 'option'){
//即便你设置了option.selected = true,
//option.attributes也找不到selected属性
props.selected = node.selected
}
if (orphanTag[type] || type === 'option') {
makeOrphan(vnode, type, node.text || node.innerHTML)
if (node.childNodes.length === 1) {
vnode.children[0].dom = node.firstChild
}
} else if (!vnode.isVoidTag) {
vnode.children = []
for (var i = 0, el; el = node.childNodes[i++];) {
var child = from(el)
if (/\S/.test(child.nodeValue)) {
vnode.children.push(child)
}
}
}
return vnode
}
export function _from(node) {
var type = node.nodeName.toLowerCase()
switch (type) {
case '#text':
case '#comment':
return {
nodeName: type,
dom: node,
nodeValue: node.nodeValue
}
default:
var props = markProps(node, node.attributes || [])
var vnode = {
nodeName: type,
dom: node,
isVoidTag: !!voidTag[type],
props: props
}
if (type === 'option') {
//即便你设置了option.selected = true,
//option.attributes也找不到selected属性
props.selected = node.selected
}
if (orphanTag[type] || type === 'option') {
makeOrphan(vnode, type, node.text || node.innerHTML)
if (node.childNodes.length === 1) {
vnode.children[0].dom = node.firstChild
}
} else if (!vnode.isVoidTag) {
vnode.children = []
for (var i = 0, el; (el = node.childNodes[i++]); ) {
var child = _from(el)
if (/\S/.test(child.nodeValue)) {
vnode.children.push(child)
}
}
}
return vnode
}
}
var rformElement = /input|textarea|select/i
function markProps(node, attrs) {
var ret = {}
for (var i = 0, n = attrs.length; i < n; i++) {
var attr = attrs[i]
if (attr.specified) {
//IE6-9不会将属性名变小写,比如它会将用户的contenteditable变成contentEditable
ret[attr.name.toLowerCase()] = attr.value
}
var ret = {}
for (var i = 0, n = attrs.length; i < n; i++) {
var attr = attrs[i]
if (attr.specified) {
//IE6-9不会将属性名变小写,比如它会将用户的contenteditable变成contentEditable
ret[attr.name.toLowerCase()] = attr.value
}
if (rformElement.test(node.nodeName)) {
ret.type = node.type
var a = node.getAttributeNode('value')
if (a && /\S/.test(a.value)) { //IE6,7中无法取得checkbox,radio的value
ret.value = a.value
}
}
if (rformElement.test(node.nodeName)) {
ret.type = node.type
var a = node.getAttributeNode('value')
if (a && /\S/.test(a.value)) {
//IE6,7中无法取得checkbox,radio的value
ret.value = a.value
}
var style = node.style.cssText
if (style) {
ret.style = style
}
//类名 = 去重(静态类名+动态类名+ hover类名? + active类名)
if (ret.type === 'select-one') {
ret.selectedIndex = node.selectedIndex
}
return ret
}
}
var style = node.style.cssText
if (style) {
ret.style = style
}
//类名 = 去重(静态类名+动态类名+ hover类名? + active类名)
if (ret.type === 'select-one') {
ret.selectedIndex = node.selectedIndex
}
return ret
}

View File

@ -1,8 +1,8 @@
export var orphanTag = {
script: 1,
style: 1,
textarea: 1,
xmp: 1,
noscript: 1,
template: 1
}
script: 1,
style: 1,
textarea: 1,
xmp: 1,
noscript: 1,
template: 1
}

View File

@ -1,5 +1,29 @@
import { Anot, oneObject } from '../seed/core'
var pNestChild = oneObject('div,ul,ol,dl,table,h1,h2,h3,h4,h5,h6,form,fieldset')
var tNestChild = makeObject('tr,style,script')
var nestObject = {
p: pNestChild,
select: makeObject('option,optgroup,#text'),
optgroup: makeObject('option,#text'),
option: makeObject('#text'),
tr: makeObject('th,td,style,script'),
tbody: tNestChild,
tfoot: tNestChild,
thead: tNestChild,
colgroup: makeObject('col'),
// table: oneObject('caption,colgroup,tbody,thead,tfoot,style,script,template,#document-fragment'),
head: makeObject(
'base,basefont,bgsound,link,style,script,meta,title,noscript,noframes'
),
html: oneObject('head,body')
}
function makeObject(str) {
return oneObject(str + ',template,#document-fragment,#comment')
}
export function validateDOMNesting(parent, child) {
var parentTag = parent.nodeName
var tag = child.nodeName
@ -8,16 +32,16 @@ export function validateDOMNesting(parent, child) {
if (parentTag === 'p') {
if (pNestChild[tag]) {
console.warn(
'P element can not add these childlren:\n' + Object.keys(pNestChild)
'P标签节点不允许以下类型的子节点:\n' + Object.keys(pNestChild)
)
return false
}
} else if (!parentChild[tag]) {
console.warn(
parentTag.toUpperCase() +
'element only add these children:\n' +
'标签节点只能增加以下子节点:\n' +
Object.keys(parentChild) +
'\nbut you add ' +
'\n当前子节点为:' +
tag.toUpperCase() +
' !!'
)
@ -26,38 +50,3 @@ export function validateDOMNesting(parent, child) {
}
return true
}
function makeObject(str) {
return oneObject(str + ',template,#document-fragment,#comment')
}
var pNestChild = oneObject('div,ul,ol,dl,table,h1,h2,h3,h4,h5,h6,form,fieldset')
var tNestChild = makeObject('tr,style,script')
var nestObject = {
p: pNestChild,
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inselect
select: makeObject('option,optgroup,#text'),
optgroup: makeObject('option,#text'),
option: makeObject('#text'),
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intd
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incaption
// No special behavior since these rules fall back to "in body" mode for
// all except special table nodes which cause bad parsing behavior anyway.
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intr
tr: makeObject('th,td,style,script'),
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intbody
tbody: tNestChild,
tfoot: tNestChild,
thead: tNestChild,
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-incolgroup
colgroup: makeObject('col'),
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-intable
// table: oneObject('caption,colgroup,tbody,thead,tfoot,style,script,template,#document-fragment'),
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inhead
head: makeObject(
'base,basefont,bgsound,link,style,script,meta,title,noscript,noframes'
),
// https://html.spec.whatwg.org/multipage/semantics.html#the-html-element
html: oneObject('head,body')
}