diff --git a/pack.config.js b/pack.config.js index c2cc050..b31d2d1 100644 --- a/pack.config.js +++ b/pack.config.js @@ -50,7 +50,6 @@ const PAD_END = Buffer.from(` fn(Anot) } } - window.importCss = importCss window.Anot = Anot return Anot })() diff --git a/package.json b/package.json index a24ce6e..bc51c60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anot", - "version": "2.0.0", + "version": "2.1.0", "description": "Anot - 迷你mvvm框架", "main": "dist/anot.js", "files": ["dist"], diff --git a/src/00-generate.js b/src/00-generate.js index c68a5b3..9db4c00 100644 --- a/src/00-generate.js +++ b/src/00-generate.js @@ -1,21 +1,17 @@ /********************************************************************* * 全局变量及方法 * **********************************************************************/ -const CSS_DEPS = {} -let bindingID = 1024 -let IEVersion = 0 -if (window.VBArray) { - IEVersion = document.documentMode || (window.XMLHttpRequest ? 7 : 6) -} -let expose = generateID() +var bindingID = 1024 + +var expose = generateID() //http://stackoverflow.com/questions/7290086/javascript-use-strict-and-nicks-find-global-function -let DOC = window.document -let head = DOC.head //HEAD元素 +var DOC = window.document +var head = DOC.head //HEAD元素 head.insertAdjacentHTML( 'afterbegin', '' ) -let ifGroup = head.firstChild +var ifGroup = head.firstChild function log() { // http://stackoverflow.com/questions/8785624/how-to-safely-wrap-console-log @@ -35,22 +31,21 @@ function createMap() { return Object.create(null) } -let subscribers = '$' + expose +var subscribers = '$' + expose -let nullObject = {} //作用类似于noop,只用于代码防御,千万不要在它上面添加属性 -let rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach -let rw20g = /\w+/g -let rsvg = /^\[object SVG\w*Element\]$/ -let oproto = Object.prototype -let ohasOwn = oproto.hasOwnProperty -let serialize = oproto.toString -let ap = Array.prototype -let aslice = ap.slice -let W3C = window.dispatchEvent -let root = DOC.documentElement -let anotFragment = DOC.createDocumentFragment() -let cinerator = DOC.createElement('div') -let class2type = { +var nullObject = {} //作用类似于noop,只用于代码防御,千万不要在它上面添加属性 +var rword = /[^, ]+/g //切割字符串为一个个小块,以空格或豆号分开它们,结合replace实现字符串的forEach +var rw20g = /\w+/g +var rsvg = /^\[object SVG\w*Element\]$/ +var oproto = Object.prototype +var ohasOwn = oproto.hasOwnProperty +var serialize = oproto.toString +var ap = Array.prototype +var aslice = ap.slice +var root = DOC.documentElement +var anotFragment = DOC.createDocumentFragment() +var cinerator = DOC.createElement('div') +var class2type = { '[object Boolean]': 'boolean', '[object Number]': 'number', '[object String]': 'string', @@ -75,9 +70,9 @@ function oneObject(array, val) { if (typeof array === 'string') { array = array.match(rword) || [] } - let result = {}, + var result = {}, value = val !== void 0 ? val : 1 - for (let i = 0, n = array.length; i < n; i++) { + for (var i = 0, n = array.length; i < n; i++) { result[array[i]] = value } return result @@ -87,52 +82,3 @@ function generateID(mark) { mark = (mark && mark + '-') || 'anot-' return mark + (++bindingID).toString(16) } - -/********************************************************************* - * css import * - **********************************************************************/ - -function getBaseUrl() { - if (window.LIBS_BASE_URL) { - return - } - let stack - try { - throw new Error() // 强制报错,以便捕获e.stack - } catch (err) { - stack = err.stack - } - stack = stack.trim().split(/[@ ]+/) - if (window.safari) { - stack = stack[1] - } else { - stack = stack.pop() - } - stack = stack.replace(/(:\\d+)?:\d+([\\w\\W]*)?$/i, '') - window.LIBS_BASE_URL = stack.replace( - /^([a-z\-]*):\/\/([^\/]+)(\/.*)?/, - '$1://$2' - ) -} - -function importCss(url, baseUrl) { - url = url.replace(/^\/+/, '/') - if (baseUrl) { - url = baseUrl + url - } else { - if (window.LIBS_BASE_URL) { - url = window.LIBS_BASE_URL + url - } - } - - if (CSS_DEPS[url]) { - return - } - head.insertAdjacentHTML( - 'afterbegin', - '' - ) - CSS_DEPS[url] = 1 -} - -getBaseUrl() diff --git a/src/02-core.js b/src/02-core.js index 3996328..6ea0398 100644 --- a/src/02-core.js +++ b/src/02-core.js @@ -203,10 +203,6 @@ Anot.mix = Anot.fn.mix = function() { } function cacheStore(tpye, key, val) { - if (!window[tpye]) { - return log('该浏览器不支持本地储存' + tpye) - } - if (this.type(key) === 'object') { for (let i in key) { window[tpye].setItem(i, key[i]) @@ -322,8 +318,9 @@ Anot.mix({ if (node instanceof Anot) { node = node[0] } - let prop = /[_-]/.test(name) ? camelize(name) : name, - fn + var prop = /[_-]/.test(name) ? camelize(name) : name + var fn + name = Anot.cssName(prop) || prop if (value === void 0 || typeof value === 'boolean') { //获取样式 @@ -331,8 +328,8 @@ Anot.mix({ if (name === 'background') { name = 'backgroundColor' } - let val = fn(node, name) - return value === true ? parseFloat(val) || 0 : val + var val = fn(node, name) + return value === true ? +val || 0 : val } else if (value === '') { //请除样式 node.style[name] = '' @@ -485,7 +482,10 @@ Anot.mix({ key += '' let uri = location.search - if (!key || !uri) return null + if (!key || !uri) { + return null + } + uri = decodeURIComponent(uri) uri = uri.slice(1) uri = uri.split('&') @@ -494,7 +494,7 @@ Anot.mix({ for (let i = 0, item; (item = uri[i++]); ) { let tmp = item.split('=') tmp[1] = tmp.length < 2 ? null : tmp[1] - tmp[1] = decodeURIComponent(tmp[1]) + tmp[1] = tmp[1] if (obj.hasOwnProperty(tmp[0])) { if (typeof obj[tmp[0]] === 'object') { obj[tmp[0]].push(tmp[1]) @@ -523,7 +523,7 @@ Anot.mix({ try { DOC.execCommand('copy') } catch (err) { - log('复制到粘贴板失败') + log('复制到粘贴板失败', err) } DOC.body.removeChild(ta) } diff --git a/src/04-dom.patch.js b/src/04-dom.patch.js index e10e1ca..8a67eca 100644 --- a/src/04-dom.patch.js +++ b/src/04-dom.patch.js @@ -17,79 +17,6 @@ Anot.contains = function(root, el) { } } -if (window.SVGElement) { - let svgns = 'http://www.w3.org/2000/svg' - let svg = DOC.createElementNS(svgns, 'svg') - svg.innerHTML = '' - if (!rsvg.test(svg.firstChild)) { - // #409 - /* jshint ignore:start */ - function enumerateNode(node, targetNode) { - if (node && node.childNodes) { - let nodes = node.childNodes - for (let i = 0, el; (el = nodes[i++]); ) { - if (el.tagName) { - let svg = DOC.createElementNS(svgns, el.tagName.toLowerCase()) - // copy attrs - ap.forEach.call(el.attributes, function(attr) { - svg.setAttribute(attr.name, attr.value) - }) - // 递归处理子节点 - enumerateNode(el, svg) - targetNode.appendChild(svg) - } - } - } - } - /* jshint ignore:end */ - Object.defineProperties(SVGElement.prototype, { - outerHTML: { - //IE9-11,firefox不支持SVG元素的innerHTML,outerHTML属性 - enumerable: true, - configurable: true, - get: function() { - return new XMLSerializer().serializeToString(this) - }, - set: function(html) { - let tagName = this.tagName.toLowerCase(), - par = this.parentNode, - frag = Anot.parseHTML(html) - // 操作的svg,直接插入 - if (tagName === 'svg') { - par.insertBefore(frag, this) - // svg节点的子节点类似 - } else { - let newFrag = DOC.createDocumentFragment() - enumerateNode(frag, newFrag) - par.insertBefore(newFrag, this) - } - par.removeChild(this) - } - }, - innerHTML: { - enumerable: true, - configurable: true, - get: function() { - let s = this.outerHTML - let ropen = new RegExp( - '<' + this.nodeName + '\\b(?:(["\'])[^"]*?(\\1)|[^>])*>', - 'i' - ) - let rclose = new RegExp('$', 'i') - return s.replace(ropen, '').replace(rclose, '') - }, - set: function(html) { - if (Anot.clearHTML) { - Anot.clearHTML(this) - let frag = Anot.parseHTML(html) - enumerateNode(frag, this) - } - } - } - }) - } -} - //========================= event binding ==================== let eventHooks = Anot.eventHooks diff --git a/src/06-vm.js b/src/06-vm.js index 1142b3e..9818d0a 100644 --- a/src/06-vm.js +++ b/src/06-vm.js @@ -317,7 +317,6 @@ function observeObject(source, options) { hideProperty($vmodel, '$events', {}) hideProperty($vmodel, '$refs', {}) hideProperty($vmodel, '$children', []) - hideProperty($vmodel, '$components', []) hideProperty($vmodel, 'hasOwnProperty', trackBy) hideProperty($vmodel, '$mounted', mounted) if (options.watch) { diff --git a/src/07-collection.js b/src/07-collection.js index 827182b..a2708ba 100644 --- a/src/07-collection.js +++ b/src/07-collection.js @@ -67,9 +67,7 @@ var newProto = { _splice.call(this.$track, 0, this.length) _splice.call(this, 0, this.length) } - if (!W3C) { - this.$model = toJson(this) - } + this.notify() this._.length = this.length }, @@ -89,9 +87,7 @@ arrayMethods.forEach(function(method) { } var result = original.apply(this, args) addTrack(this.$track, method, args) - if (!W3C) { - this.$model = toJson(this) - } + this.notify() this._.length = this.length return result @@ -120,9 +116,7 @@ arrayMethods.forEach(function(method) { } if (hasSort) { sortByIndex(this.$track, indexes) - if (!W3C) { - this.$model = toJson(this) - } + this.notify() } return this diff --git a/src/11-dom.instance.js b/src/11-dom.instance.js index d40b1df..66ce0bd 100644 --- a/src/11-dom.instance.js +++ b/src/11-dom.instance.js @@ -31,21 +31,6 @@ function camelize(target) { }) Anot.fn.mix({ - hasClass: function(cls) { - var el = this[0] || {} //IE10+, chrome8+, firefox3.6+, safari5.1+,opera11.5+支持classList,chrome24+,firefox26+支持classList2.0 - return el.nodeType === 1 && el.classList.contains(cls) - }, - toggleClass: function(value, stateVal) { - var className, - i = 0 - var classNames = String(value).match(/\S+/g) || [] - var isBool = typeof stateVal === 'boolean' - while ((className = classNames[i++])) { - var state = isBool ? stateVal : !this.hasClass(className) - this[state ? 'addClass' : 'removeClass'](className) - } - return this - }, attr: function(name, value) { if (arguments.length === 2) { this[0].setAttribute(name, value) @@ -55,25 +40,24 @@ Anot.fn.mix({ } }, data: function(name, value) { - name = 'data-' + hyphen(name || '') - switch (arguments.length) { + var len = arguments.length + var dataset = this[0].dataset + name = hyphen(name || '') + if (!name) { + len = 0 + } + switch (len) { case 2: - this.attr(name, value) + dataset[name] = value return this case 1: - var val = this.attr(name) + var val = dataset[name] return parseData(val) case 0: - var ret = {} - ap.forEach.call(this[0].attributes, function(attr) { - if (attr) { - name = attr.name - if (!name.indexOf('data-')) { - name = camelize(name.slice(5)) - ret[name] = parseData(attr.value) - } - } - }) + var ret = createMap() + for (var i in dataset) { + ret[i] = parseData(dataset[i]) + } return ret } }, @@ -159,27 +143,6 @@ Anot.fn.mix({ } }) -if (root.dataset) { - Anot.fn.data = function(name, val) { - name = name && camelize(name) - var dataset = this[0].dataset - switch (arguments.length) { - case 2: - dataset[name] = val - return this - case 1: - val = dataset[name] - return parseData(val) - case 0: - var ret = createMap() - for (name in dataset) { - ret[name] = parseData(dataset[name]) - } - return ret - } - } -} - Anot.parseJSON = JSON.parse var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/ @@ -190,14 +153,14 @@ function parseData(data) { data === 'true' ? true : data === 'false' - ? false - : data === 'null' - ? null - : +data + '' === data - ? +data - : rbrace.test(data) - ? JSON.parse(data) - : data + ? false + : data === 'null' + ? null + : +data + '' === data + ? +data + : rbrace.test(data) + ? JSON.parse(data) + : data } catch (e) {} return data } @@ -236,8 +199,8 @@ function getWindow(node) { return node.window && node.document ? node : node.nodeType === 9 - ? node.defaultView - : false + ? node.defaultView + : false } //=============================css相关================================== diff --git a/src/13-scan.js b/src/13-scan.js index 762d761..27593ef 100644 --- a/src/13-scan.js +++ b/src/13-scan.js @@ -6,14 +6,6 @@ var stopScan = oneObject( 'area,base,basefont,br,col,command,embed,hr,img,input,link,meta,param,source,track,wbr,noscript,script,style,textarea'.toUpperCase() ) -function isWidget(el) { - //如果是组件,则返回组件的名字 - var name = el.nodeName.toLowerCase() - if (/^anot-([a-z][a-z0-9\-]*)$/.test(name)) { - return RegExp.$1 - } - return null -} function isRef(el) { return el.hasAttribute('ref') ? el.getAttribute('ref') : null @@ -57,30 +49,8 @@ function executeBindings(bindings, vmodels) { bindings.length = 0 } -//https://github.com/RubyLouvre/Anot/issues/636 -var mergeTextNodes = - IEVersion && window.MutationObserver - ? function(elem) { - var node = elem.firstChild, - text - while (node) { - var aaa = node.nextSibling - if (node.nodeType === 3) { - if (text) { - text.nodeValue += node.nodeValue - elem.removeChild(node) - } else { - text = node - } - } else { - text = null - } - node = aaa - } - } - : 0 var roneTime = /^\s*::/ -var rmsAttr = /:(\w+)-?(.*)/ +var rmsAttr = /:(\w+)-?(.*)|@(.*)/ var events = oneObject( 'animationend,blur,change,input,click,dblclick,focus,keydown,keypress,keyup,mousedown,mouseenter,mouseleave,mousemove,mouseout,mouseover,mouseup,scan,scroll,submit' @@ -93,45 +63,7 @@ function bindingSorter(a, b) { } var rnoCollect = /^(:\S+|data-\S+|on[a-z]+|style|class)$/ -var ronattr = '__fn__' -var specifiedVars = [':disabled', ':loading', ':value'] var filterTypes = ['html', 'text', 'attr', 'data'] -function getOptionsFromTag(elem, vmodels) { - var attributes = aslice.call(elem.attributes, 0) - var ret = {} - var vm = vmodels[0] || {} - - for (var i = 0, attr; (attr = attributes[i++]); ) { - var name = attr.name - if ( - (attr.specified && !rnoCollect.test(name)) || - specifiedVars.includes(name) - ) { - elem.removeAttribute(name) - if (name.indexOf(ronattr) === 0) { - name = attr.value.slice(6) - ret[name] = elem[attr.value] - delete elem[attr.value] - } else { - var camelizeName = camelize(name) - if (camelizeName.indexOf('@') === 0) { - camelizeName = camelizeName.slice(1) - attr.value = attr.value.replace(/\(.*\)$/, '') - if (vm.$id.slice(0, 10) === 'proxy-each') { - vm = vm.$up - } - var fn = parseVmValue(vm, attr.value) - if (fn && typeof fn === 'function') { - ret[camelizeName] = fn.bind(vm) - } - } else { - ret[camelizeName] = parseData(attr.value) - } - } - } - } - return ret -} function scanAttr(elem, vmodels, match) { var scanNode = true @@ -151,9 +83,10 @@ function scanAttr(elem, vmodels, match) { //如果是以指定前缀命名的 var type = match[1] var param = match[2] || '' + var eparam = match[3] || '' // 事件绑定的简写 var value = attr.value - if (events[type]) { - param = type + if (events[type] || events[eparam]) { + param = type || eparam type = 'on' } if (directives[type]) { @@ -171,6 +104,7 @@ function scanAttr(elem, vmodels, match) { (directives[type].priority || type.charCodeAt(0) * 10) + (Number(param.replace(/\D/g, '')) || 0) } + // 如果指令允许使用过滤器 if (filterTypes.includes(type)) { var filters = getToken(value).filters binding.expr = binding.expr.replace(filters, '') @@ -211,12 +145,7 @@ function scanAttr(elem, vmodels, match) { executeBindings(bindings, vmodels) } } - if ( - scanNode && - !stopScan[elem.tagName] && - (isWidget(elem) ? elem.msResolved : 1) - ) { - mergeTextNodes && mergeTextNodes(elem) + if (scanNode && !stopScan[elem.tagName]) { scanNodeList(elem, vmodels) //扫描子孙元素 } } @@ -239,33 +168,11 @@ function scanNodeArray(nodes, vmodels) { switch (node.nodeType) { case 1: var elem = node - if ( - !elem.msResolved && - elem.parentNode && - elem.parentNode.nodeType === 1 - ) { - var widget = isWidget(elem) - - if (widget) { - elem.setAttribute('is-widget', '') - elem.removeAttribute(':if') - elem.removeAttribute(':if-loop') - componentQueue.push({ - element: elem, - vmodels: vmodels, - name: widget - }) - if (Anot.components[widget]) { - // log(widget, Anot.components) - //确保所有:attr-name扫描完再处理 - _delay_component(widget) - } - } else { - // 非组件才检查 ref属性 - var ref = isRef(elem) - if (ref && vmodels.length) { - vmodels[0].$refs[ref] = elem - } + if (elem.parentNode && elem.parentNode.nodeType === 1) { + // 非组件才检查 ref属性 + var ref = isRef(elem) + if (ref && vmodels.length) { + vmodels[0].$refs[ref] = elem } } diff --git a/src/15-component.js b/src/15-component.js index 44e678f..e69de29 100644 --- a/src/15-component.js +++ b/src/15-component.js @@ -1,351 +0,0 @@ -var componentQueue = [] -var widgetList = [] -var componentHooks = { - __init__: noop, - componentWillMount: noop, - componentDidMount: noop, - childComponentDidMount: noop, - componentWillUnmount: noop, - render: function() { - return null - } -} - -function parseSlot(collections, vms) { - var arr = aslice.call(collections, 0) - var obj = { __extra__: [] } - arr.forEach(function(elem) { - switch (elem.nodeType) { - case 1: - var isSlotTag = elem.tagName === 'SLOT' - var slotKey = null - var isSlotAttr = elem.getAttribute('slot') - - if (isSlotTag) { - slotKey = elem.name || elem.getAttribute('name') - } else if (isSlotAttr) { - slotKey = isSlotAttr - } - - if (slotKey) { - obj[slotKey] = obj[slotKey] || [] - elem.removeAttribute('slot') - if (isSlotTag) { - obj[slotKey].push(elem.innerHTML) - } else { - obj[slotKey].push(elem.outerHTML) - } - } else { - var txt = elem.outerHTML - if (isWidget(elem) || /:[\w-]*=".*"/.test(txt)) { - break - } - if (rexpr.test(txt)) { - var expr = normalizeExpr(txt) - txt = parseExpr(expr, vms, {}).apply(0, vms) - } - - obj.__extra__.push(txt) - } - - break - case 3: - var txt = elem.textContent.trim() - if (txt) { - obj.__extra__.push(txt) - } - break - default: - break - } - elem.parentNode.removeChild(elem) - }) - return obj -} - -function parseVmValue(vm, key, val) { - if (arguments.length === 2) { - var oval = Function('o', 'return o.' + key)(vm) - if (oval && typeof oval === 'object') { - try { - return oval.$model - } catch (err) {} - } - return oval - } else if (arguments.length === 3) { - Function('o', 'v', 'return o.' + key + ' = v')(vm, val) - } -} - -Anot.components = {} -Anot.component = function(name, opts) { - if (opts) { - Anot.components[name] = Anot.mix({}, componentHooks, opts) - } - for (var i = 0, obj; (obj = componentQueue[i]); i++) { - if (name === obj.name) { - componentQueue.splice(i, 1) - i-- - // (obj, Anot.components[name], obj.element, obj.name) - ;(function(host, hooks, elem, widget) { - //如果elem已从Document里移除,直接返回 - if (!Anot.contains(DOC, elem) || elem.msResolved) { - Anot.Array.remove(componentQueue, host) - return - } - - var dependencies = 1 - - //===========收集各种配置======= - if (elem.getAttribute(':attr-uuid')) { - //如果还没有解析完,就延迟一下 #1155 - return - } - hooks.watch = hooks.watch || {} - var parentVm = host.vmodels.concat().pop() - var state = {} - var props = getOptionsFromTag(elem, host.vmodels) - var $id = props.uuid || generateID(widget) - var slots = { __extra__: [] } - - // 对象组件的子父vm关系, 只存最顶层的$components对象中, - while (parentVm.$up && parentVm.$up.__WIDGET__ === name) { - parentVm = parentVm.$up - } - - if (elem.childNodes.length) { - slots = parseSlot(elem.childNodes, host.vmodels) - } - var txtContent = slots.__extra__.join('') - delete slots.__extra__ - elem.text = function() { - return txtContent - } - - if (props.hasOwnProperty(':disabled')) { - var disabledKey = props[':disabled'] - var disabledKeyReverse = false - if (disabledKey.indexOf('!') === 0) { - disabledKey = disabledKey.slice(1) - disabledKeyReverse = true - } - state.disabled = parseVmValue(parentVm, disabledKey) - if (disabledKeyReverse) { - state.disabled = !state.disabled - } - - parentVm.$watch(disabledKey, function(val) { - if (disabledKeyReverse) { - val = !val - } - Anot.vmodels[$id].disabled = val - }) - - delete props[':disabled'] - } - if (props.hasOwnProperty(':loading')) { - var loadingKey = props[':loading'] - var loadingKeyReverse = false - if (loadingKey.indexOf('!') === 0) { - loadingKey = loadingKey.slice(1) - loadingKeyReverse = true - } - state.loading = parseVmValue(parentVm, loadingKey) - if (loadingKeyReverse) { - state.loading = !state.loading - } - parentVm.$watch(loadingKey, function(val) { - if (loadingKeyReverse) { - val = !val - } - Anot.vmodels[$id].loading = val - }) - delete props[':loading'] - } - - // :value可实现双向同步值 - if (props.hasOwnProperty(':value')) { - var valueKey = props[':value'] - var valueWatcher = function() { - var val = parseVmValue(parentVm, valueKey) - Anot.vmodels[$id].value = val - } - var childValueWatcher = function() { - var val = this.value - if (val && typeof val === 'object') { - val = val.$model - } - parseVmValue(parentVm, valueKey, val) - } - state.value = parseVmValue(parentVm, valueKey) - - if (hooks.watch.value) { - hooks.watch.value = [hooks.watch.value] - } else { - hooks.watch.value = [] - } - if (hooks.watch['value.length']) { - hooks.watch['value.length'] = [hooks.watch['value.length']] - } else { - hooks.watch['value.length'] = [] - } - if (hooks.watch['value.*']) { - hooks.watch['value.*'] = [hooks.watch['value.*']] - } else { - hooks.watch['value.*'] = [] - } - - parentVm.$watch(valueKey, valueWatcher) - if (Array.isArray(state.value)) { - parentVm.$watch(valueKey + '.*', valueWatcher) - parentVm.$watch(valueKey + '.length', valueWatcher) - hooks.watch['value.*'].push(childValueWatcher) - hooks.watch['value.length'].push(childValueWatcher) - } else { - hooks.watch.value.push(childValueWatcher) - } - - delete props[':value'] - } - - delete props.uuid - delete props.name - delete props.isWidget - - hooks.props = hooks.props || {} - hooks.state = hooks.state || {} - - Object.assign(hooks.props, props) - Object.assign(hooks.state, state) - - var __READY__ = false - - hooks.__init__.call(elem, hooks.props, hooks.state, function next() { - __READY__ = true - - delete elem.text - }) - - if (!__READY__) { - return - } - - hooks.$id = $id - - //==========构建VM========= - var { - componentWillMount, - componentDidMount, - childComponentDidMount, - componentWillUnmount, - render - } = hooks - - delete hooks.__init__ - delete hooks.componentWillMount - delete hooks.componentDidMount - delete hooks.childComponentDidMount - delete hooks.componentWillUnmount - - var vmodel = Anot(hooks) - Anot.vmodels[vmodel.$id] = vmodel - hideProperty(vmodel, '__WIDGET__', name) - hideProperty(vmodel, '$recycle', function() { - for (var i in this.$events) { - var ev = this.$events[i] || [] - var len = ev.length - while (len--) { - if (ev[len].type === null || ev[len].type === 'user-watcher') { - ev.splice(len, 1) - } - } - } - }) - delete vmodel.$mounted - - // 对象组件的子父vm关系, 只存最顶层的$components对象中, - // 而子vm, 无论向下多少级, 他们的$up对象也只存最顶层的组件vm - parentVm.$components.push(vmodel) - if (parentVm.__WIDGET__ === name) { - vmodel.$up = parentVm - } - - elem.msResolved = 1 //防止二进扫描此元素 - - componentWillMount.call(vmodel) - - Anot.clearHTML(elem) - var html = render.call(vmodel, slots) || '' - - html = html.replace(/<\w+[^>]*>/g, function(m, s) { - return m.replace(/[\n\t\s]{1,}/g, ' ') - }) - - elem.innerHTML = html - - hideProperty(vmodel, '$elem', elem) - elem.__VM__ = vmodel - - Anot.fireDom(elem, 'datasetchanged', { - vm: vmodel, - childReady: 1 - }) - - var children = 0 - var removeFn = Anot.bind(elem, 'datasetchanged', function(ev) { - if (ev.childReady) { - dependencies += ev.childReady - if (vmodel.$id !== ev.vm.$id) { - if (ev.childReady === -1) { - children++ - childComponentDidMount.call(vmodel, ev.vm) - } - ev.stopPropagation() - } - } - if (dependencies === 0) { - var timer = setTimeout(function() { - clearTimeout(timer) - elem.removeAttribute('is-widget') - componentDidMount.call(vmodel) - }, children ? Math.max(children * 17, 100) : 17) - - Anot.unbind(elem, 'datasetchanged', removeFn) - //================== - host.rollback = function() { - try { - componentWillUnmount.call(vmodel) - } catch (e) {} - parentVm.$recycle && parentVm.$recycle() - Anot.Array.remove(parentVm.$components, vmodel) - delete Anot.vmodels[vmodel.$id] - } - injectDisposeQueue(host, widgetList) - if (window.chrome) { - elem.addEventListener('DOMNodeRemovedFromDocument', function() { - setTimeout(rejectDisposeQueue) - }) - } - } - }) - - scanTag(elem, [vmodel]) - - if (!elem.childNodes.length) { - Anot.fireDom(elem, 'datasetchanged', { - vm: vmodel, - childReady: -1 - }) - } else { - var id2 = setTimeout(function() { - clearTimeout(id2) - Anot.fireDom(elem, 'datasetchanged', { - vm: vmodel, - childReady: -1 - }) - }, 17) - } - })(obj, toJson(Anot.components[name]), obj.element, obj.name) // jshint ignore:line - } - } -} diff --git a/src/16-:attr.js b/src/16-:attr.js index 8bcffb1..4c4f46b 100644 --- a/src/16-:attr.js +++ b/src/16-:attr.js @@ -9,25 +9,6 @@ bools.replace(rword, function(name) { boolMap[name.toLowerCase()] = name }) -var propMap = { - //属性名映射 - 'accept-charset': 'acceptCharset', - char: 'ch', - charoff: 'chOff', - class: 'className', - for: 'htmlFor', - 'http-equiv': 'httpEquiv' -} - -var anomaly = [ - 'accessKey,bgColor,cellPadding,cellSpacing,codeBase,codeType,colSpan', - 'dateTime,defaultValue,frameBorder,longDesc,maxLength,marginWidth,marginHeight', - 'rowSpan,tabIndex,useMap,vSpace,valueType,vAlign' -].join(',') -anomaly.replace(rword, function(name) { - propMap[name.toLowerCase()] = name -}) - var attrDir = Anot.directive('attr', { init: function(binding) { //{{aaa}} --> aaa @@ -46,8 +27,9 @@ var attrDir = Anot.directive('attr', { 'data-loaded', binding.vmodels ) - var outer = (binding.includeReplace = !!Anot(elem).data('includeReplace')) - if (Anot(elem).data('cache')) { + // 是否直接替换当前容器 + var outer = (binding.includeReplace = elem.hasAttribute('replace')) + if (elem.hasAttribute('cache')) { binding.templateCache = {} } binding.start = DOC.createComment(':include') @@ -66,17 +48,16 @@ var attrDir = Anot.directive('attr', { update: function(val) { var elem = this.element var obj = {} - var vm = this.vmodels[0] val = toJson(val) if (this.param) { - if (typeof val === 'object' && val !== null) { + if (val && typeof val === 'object') { if (Array.isArray(val)) { obj[this.param] = val } else { if (Date.isDate(val)) { - obj[this.param] = val.toUTCString() + obj[this.param] = val.toISOString() } else { obj[this.param] = val } @@ -85,10 +66,12 @@ var attrDir = Anot.directive('attr', { obj[this.param] = val } } else { - if (!val || typeof val !== 'object' || Array.isArray(val)) { - return - } - if (Date.isDate(val)) { + if ( + !val || + typeof val !== 'object' || + Array.isArray(val) || + Date.isDate(val) + ) { return } @@ -97,71 +80,38 @@ var attrDir = Anot.directive('attr', { for (var i in obj) { if (i === 'style') { - console.error('设置style样式, 请改用 :css指令') + elem.style.cssText = obj[i] continue } - // 通过属性设置回调,必须以@符号开头 - if (i.indexOf('@') === 0) { - if (typeof obj[i] !== 'function') { - continue - } - } if (i === 'href' || i === 'src') { - //处理IE67自动转义的问题 - if (!root.hasAttribute) obj[i] = obj[i].replace(/&/g, '&') - elem[i] = obj[i] - - //chrome v37- 下embed标签动态设置的src,无法发起请求 - if (window.chrome && elem.tagName === 'EMBED') { - var _parent = elem.parentNode - var com = DOC.createComment(':src') - _parent.replaceChild(com, elem) - _parent.replaceChild(elem, com) - } } else { - var k = i - //古董IE下,部分属性名字要进行映射 - if (!W3C && propMap[k]) { - k = propMap[k] - } if (obj[i] === false || obj[i] === null || obj[i] === undefined) { obj[i] = '' } - if (typeof elem[boolMap[k]] === 'boolean') { + if (typeof elem[boolMap[i]] === 'boolean') { //布尔属性必须使用el.xxx = true|false方式设值 - elem[boolMap[k]] = !!obj[i] + obj[i] = !!obj[i] + elem[boolMap[i]] = obj[i] - //如果为false, IE全系列下相当于setAttribute(xxx, ''),会影响到样式,需要进一步处理 if (!obj[i]) { - obj[i] = !!obj[i] - } - if (obj[i] === false) { - elem.removeAttribute(k) + elem.removeAttribute(boolMap[i]) continue } } //SVG只能使用setAttribute(xxx, yyy), VML只能使用elem.xxx = yyy ,HTML的固有属性必须elem.xxx = yyy - var isInnate = rsvg.test(elem) - ? false - : DOC.namespaces && isVML(elem) - ? true - : k in elem.cloneNode(false) + var isInnate = rsvg.test(elem) ? false : i in elem.cloneNode(false) if (isInnate) { - elem[k] = obj[i] + elem[i] = obj[i] } else { if (typeof obj[i] === 'object') { obj[i] = Date.isDate(obj[i]) - ? obj[i].toUTCString() + ? obj[i].toISOString() : JSON.stringify(obj[i]) - } else if (typeof obj[i] === 'function') { - k = ronattr + camelize(k.slice(1)) - elem[k] = obj[i].bind(vm) - obj[i] = k } - elem.setAttribute(k, obj[i]) + elem.setAttribute(i, obj[i]) } } } diff --git a/src/17-:class.js b/src/17-:class.js index 2f16ba3..b82336e 100644 --- a/src/17-:class.js +++ b/src/17-:class.js @@ -1,25 +1,11 @@ -//类名定义, :class="xx:yy" :class="{xx: yy}" :class="xx" :class="{{xx}}" +//类名定义 :class="{xx: yy}" :class="xx" Anot.directive('class', { init: function(binding) { - binding.expr = binding.expr.replace(/\n/g, ' ').replace(/\s{2,}/g, ' ') - var expr = [] - if (!/^\{.*\}$/.test(binding.expr)) { - expr = binding.expr.split(':') - expr[1] = (expr[1] && expr[1].trim()) || 'true' - var arr = expr[0].split(/\s+/) - binding.expr = - '{' + - arr - .map(function(it) { - return it + ': ' + expr[1] - }) - .join(', ') + - '}' - } else if (/^\{\{.*\}\}$/.test(binding.expr)) { - binding.expr = binding.expr.slice(2, -2) - } + binding.expr = binding.expr.replace(/\n/g, ' ').replace(/\s+/g, ' ') if (binding.type === 'hover' || binding.type === 'active') { + var expr = new Function('return ' + binding.expr)() + //确保只绑定一次 if (!binding.hasBindEvent) { var elem = binding.element @@ -32,16 +18,16 @@ Anot.directive('class', { activate = 'mousedown' abandon = 'mouseup' var fn0 = $elem.bind('mouseleave', function() { - $elem.removeClass(expr[0]) + $elem.removeClass(expr) }) } } var fn1 = $elem.bind(activate, function() { - $elem.addClass(expr[0]) + $elem.addClass(expr) }) var fn2 = $elem.bind(abandon, function() { - $elem.removeClass(expr[0]) + $elem.removeClass(expr) }) binding.rollback = function() { $elem.unbind('mouseleave', fn0) @@ -73,9 +59,8 @@ Anot.directive('class', { obj = obj.$model } - var $elem = Anot(this.element) for (var i in obj) { - $elem.toggleClass(i, !!obj[i]) + this.element.classList.toggle(i, !!obj[i]) } } }) diff --git a/src/18-:css.js b/src/18-:css.js index 51629c8..d0e7a8f 100644 --- a/src/18-:css.js +++ b/src/18-:css.js @@ -4,22 +4,22 @@ Anot.directive('css', { init: directives.attr.init, update: function(val) { var $elem = Anot(this.element) - if (!this.param) { - var obj = val - try { - if (typeof val === 'object') { - if (!Anot.isPlainObject(val)) obj = val.$model - } else { - obj = new Function('return ' + val)() - } - for (var i in obj) { - $elem.css(i, obj[i]) - } - } catch (err) { - log('样式格式错误 %c %s="%s"', 'color:#f00', this.name, this.expr) - } - } else { + if (this.param) { $elem.css(this.param, val) + } else { + if (typeof val !== 'object') { + return log( + ':css指令格式错误 %c %s="%s"', + 'color:#f00', + this.name, + this.expr + ) + } + var obj = val + if (!Anot.isPlainObject(obj)) { + obj = val.$model + } + $elem.css(obj) } } }) diff --git a/src/19-:data.js b/src/19-:data.js index 4db7811..5bc9852 100644 --- a/src/19-:data.js +++ b/src/19-:data.js @@ -3,17 +3,25 @@ Anot.directive('data', { priority: 100, init: directives.attr.init, update: function(val) { - var obj = val - if (typeof obj === 'object' && obj !== null) { - if (!Anot.isPlainObject(obj)) obj = val.$model - - for (var i in obj) { - this.element.setAttribute('data-' + i, obj[i]) - } + var $el = Anot(this.element) + if (this.param) { + $el.data(this.param, val) } else { - if (!this.param) return - - this.element.setAttribute('data-' + this.param, obj) + if (typeof val !== 'object') { + return log( + ':data指令格式错误 %c %s="%s"', + 'color:#f00', + this.name, + this.expr + ) + } + var obj = val + if (!Anot.isPlainObject(obj)) { + obj = val.$model + } + for (var i in obj) { + $el.data(i, obj[i]) + } } } }) diff --git a/src/20-:rule.js b/src/20-:rule.js index d53ff7e..e69de29 100644 --- a/src/20-:rule.js +++ b/src/20-:rule.js @@ -1,129 +0,0 @@ -/*------ 表单验证 -------*/ -var __rules = {} -Anot.validate = function(key, cb) { - if (!__rules[key]) { - throw new Error('validate [' + key + '] not exists.') - } - if (typeof cb === 'function') { - __rules[key].event = cb - } - var result = __rules[key].result - for (var k in result) { - if (!result[k].passed) { - return result[k] - } - } - return true -} -Anot.directive('rule', { - priority: 2010, - init: function(binding) { - if (binding.param && !__rules[binding.param]) { - __rules[binding.param] = { - event: noop, - result: {} - } - } - binding.target = __rules[binding.param] - }, - update: function(opt) { - var _this = this - var elem = this.element - if (!['INPUT', 'TEXTAREA'].includes(elem.nodeName)) { - return - } - if (elem.msBinded) { - return - } - if (this.target) { - this.target.result[elem.expr] = { key: elem.expr } - } - var target = this.target - - // 0: 验证通过 - // 10001: 不能为空 - // 10002: 必须为合法数字 - // 10003: Email格式错误 - // 10004: 手机格式错误 - // 10005: 必须为纯中文 - // 10006: 格式匹配错误(正则) - // 10011: 输入值超过指定最大长度 - // 10012: 输入值短于指定最小长度 - // 10021: 输入值大于指定最大数值 - // 10022: 输入值小于指定最小数值 - // 10031: 与指定的表单的值不一致 - function checked(ev) { - var val = elem.value - var code = 0 - - if (opt.require && (val === '' || val === null)) { - code = 10001 - } - - if (code === 0 && opt.isNumeric) { - code = !isFinite(val) ? 10002 : 0 - } - - if (code === 0 && opt.isEmail) - code = !/^[\w\.\-]+@\w+([\.\-]\w+)*\.\w+$/.test(val) ? 10003 : 0 - - if (code === 0 && opt.isPhone) { - code = !/^1[34578]\d{9}$/.test(val) ? 10004 : 0 - } - - if (code === 0 && opt.isCN) { - code = !/^[\u4e00-\u9fa5]+$/.test(val) ? 10005 : 0 - } - - if (code === 0 && opt.exp) { - code = !opt.exp.test(val) ? 10006 : 0 - } - - if (code === 0 && opt.maxLen) { - code = val.length > opt.maxLen ? 10011 : 0 - } - - if (code === 0 && opt.minLen) { - code = val.length < opt.minLen ? 10012 : 0 - } - - if (code === 0 && opt.hasOwnProperty('max')) { - code = val > opt.max ? 10021 : 0 - } - - if (code === 0 && opt.hasOwnProperty('min')) { - code = val < opt.min ? 10022 : 0 - } - - if (code === 0 && opt.eq) { - var eqVal = parseVmValue(_this.vmodels[0], opt.eq) - code = val !== eqVal ? 10031 : 0 - } - - target.result[elem.expr].code = code - target.result[elem.expr].passed = opt.require - ? code === 0 - : val - ? code === 0 - : true - - var passed = true - for (var k in target.result) { - if (!target.result[k].passed) { - passed = false - target.event(target.result[k]) - break - } - } - if (passed) { - target.event(true) - } - } - Anot(elem).bind('blur', checked) - this.rollback = function() { - Anot(elem).unbind('blur', checked) - } - elem.msBinded = true - checked() - } -}) diff --git a/src/21-:duplex.js b/src/21-:duplex.js index 3bcc687..70b39f5 100644 --- a/src/21-:duplex.js +++ b/src/21-:duplex.js @@ -35,12 +35,12 @@ var duplexBinding = Anot.directive('duplex', { elem.tagName === 'SELECT' ? 'select' : elem.type === 'checkbox' - ? 'checkbox' - : elem.type === 'radio' - ? 'radio' - : /^change/.test(elem.getAttribute('data-event')) - ? 'change' - : 'input' + ? 'checkbox' + : elem.type === 'radio' + ? 'radio' + : /^change/.test(elem.getAttribute('data-event')) + ? 'change' + : 'input' } elem.expr = binding.expr //===================绑定事件====================== @@ -72,7 +72,11 @@ var duplexBinding = Anot.directive('duplex', { return } - var lastValue = binding.pipe(val, binding, 'get') + var lastValue = binding.pipe( + val, + binding, + 'get' + ) binding.oldValue = val binding.setter(lastValue) @@ -82,7 +86,11 @@ var duplexBinding = Anot.directive('duplex', { switch (binding.xtype) { case 'radio': bound('click', function() { - var lastValue = binding.pipe(elem.value, binding, 'get') + var lastValue = binding.pipe( + elem.value, + binding, + 'get' + ) binding.setter(lastValue) callback.call(elem, lastValue) }) @@ -95,7 +103,11 @@ var duplexBinding = Anot.directive('duplex', { log(':duplex应用于checkbox上要对应一个数组') array = [array] } - var val = binding.pipe(elem.value, binding, 'get') + var val = binding.pipe( + elem.value, + binding, + 'get' + ) Anot.Array[method](array, val) callback.call(elem, array) }) @@ -106,21 +118,27 @@ var duplexBinding = Anot.directive('duplex', { case 'input': bound('input', updateVModel) bound('keyup', updateVModel) - if (!IEVersion) { - bound('compositionstart', compositionStart) - bound('compositionend', compositionEnd) - bound('DOMAutoComplete', updateVModel) - } + bound('compositionstart', compositionStart) + bound('compositionend', compositionEnd) + bound('DOMAutoComplete', updateVModel) break case 'select': bound('change', function() { var val = Anot(elem).val() //字符串或字符串数组 if (Array.isArray(val)) { val = val.map(function(v) { - return binding.pipe(v, binding, 'get') + return binding.pipe( + v, + binding, + 'get' + ) }) } else { - val = binding.pipe(val, binding, 'get') + val = binding.pipe( + val, + binding, + 'get' + ) } if (val + '' !== binding.oldValue) { try { @@ -176,7 +194,11 @@ var duplexBinding = Anot.directive('duplex', { elem.value = value break case 'change': - curValue = this.pipe(value, this, 'set') //fix #673 + curValue = this.pipe( + value, + this, + 'set' + ) //fix #673 if (curValue !== this.oldValue) { var fixCaret = false if (elem.msFocus) { @@ -201,7 +223,11 @@ var duplexBinding = Anot.directive('duplex', { break case 'checkbox': var array = [].concat(value) //强制转换为数组 - curValue = this.pipe(elem.value, this, 'get') + curValue = this.pipe( + elem.value, + this, + 'get' + ) elem.checked = array.indexOf(curValue) > -1 break case 'select': diff --git a/src/25-:if.js b/src/25-:if.js index 2ac055c..89e0404 100644 --- a/src/25-:if.js +++ b/src/25-:if.js @@ -3,13 +3,18 @@ Anot.directive('if', { update: function(val) { var binding = this var elem = this.element - var stamp = (binding.stamp = +new Date()) + var stamp = (binding.stamp = Date.now()) var par var after = function() { - if (stamp !== binding.stamp) return + if (stamp !== binding.stamp) { + return + } binding.recoverNode = null } - if (binding.recoverNode) binding.recoverNode() // 还原现场,有移动节点的都需要还原现场 + if (binding.recoverNode) { + binding.recoverNode() // 还原现场,有移动节点的都需要还原现场 + } + try { if (!elem.parentNode) return par = elem.parentNode diff --git a/src/26-:include.js b/src/26-:include.js index 9666327..52b8271 100644 --- a/src/26-:include.js +++ b/src/26-:include.js @@ -1,6 +1,3 @@ -var getXHR = function() { - return new window.XMLHttpRequest() // jshint ignore:line -} //将所有远程加载的模板,以字符串形式存放到这里 var templatePool = (Anot.templateCache = {}) @@ -26,24 +23,30 @@ function nodesToFrag(nodes) { Anot.directive('include', { init: directives.attr.init, update: function(val) { + if (!val) { + return + } + var binding = this var elem = this.element var vmodels = binding.vmodels - var rendered = binding.includeRendered + var loaded = binding.includeLoaded // 加载完的回调 + var rendered = binding.includeRendered // 渲染完的回调 var effectClass = binding.effectName && binding.effectClass // 是否开启动画 - var templateCache = binding.templateCache // 是否data-include-cache - var outer = binding.includeReplace // 是否data-include-replace - var loaded = binding.includeLoaded + var templateCache = binding.templateCache // 是否开启 缓存 + var outer = binding.includeReplace // 是否替换容器 var target = outer ? elem.parentNode : elem - var _ele = binding._element // data-include-replace binding.element === binding.end + var _ele = binding._element // replace binding.element === binding.end binding.recoverNodes = binding.recoverNodes || Anot.noop var scanTemplate = function(text) { - var _stamp = (binding._stamp = +new Date()) // 过滤掉频繁操作 + var _stamp = (binding._stamp = Date.now()) // 过滤掉频繁操作 if (loaded) { var newText = loaded.apply(target, [text].concat(vmodels)) - if (typeof newText === 'string') text = newText + if (typeof newText === 'string') { + text = newText + } } if (rendered) { checkScan( @@ -104,7 +107,7 @@ Anot.directive('include', { if (outer && effectClass) { enterEl = _ele enterEl.innerHTML = '' // 清空 - enterEl.setAttribute(':skip', 'true') + enterEl.setAttribute('skip', '') target.insertBefore(enterEl, binding.end.nextSibling) // 插入到bingding.end之后避免被错误的移动 before = function() { enterEl.insertBefore(fragment, null) // 插入节点 @@ -133,51 +136,33 @@ Anot.directive('include', { Anot.effect.apply(enterEl, 'enter', before, after) } - if (!val) return - - var el = val - - if (typeof el === 'object') { - if (el.nodeType !== 1) return log('include 不支持非DOM对象') + if (templatePool[val]) { + Anot.nextTick(function() { + scanTemplate(templatePool[val]) + }) } else { - el = DOC.getElementById(val) - if (!el) { - if (typeof templatePool[val] === 'string') { - Anot.nextTick(function() { - scanTemplate(templatePool[val]) - }) - } else if (Array.isArray(templatePool[val])) { - //#805 防止在循环绑定中发出许多相同的请求 - templatePool[val].push(scanTemplate) - } else { - var xhr = getXHR() - xhr.onload = function() { - if (xhr.status !== 200) - return log('获取网络资源出错, httpError[' + xhr.status + ']') - - var text = xhr.responseText - for (var f = 0, fn; (fn = templatePool[val][f++]); ) { - fn(text) - } - templatePool[val] = text - } - xhr.onerror = function() { - log(':include load [' + val + '] error') - } - templatePool[val] = [scanTemplate] - xhr.open('GET', val, true) - if ('withCredentials' in xhr) { - xhr.withCredentials = true - } - xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest') - xhr.send(null) + fetch(val, { + method: 'get', + headers: { + 'X-Requested-With': 'XMLHttpRequest' } - return - } + }) + .then(res => { + if (res.status >= 200 && res.status < 300) { + return res.text() + } else { + return Promise.reject( + `获取网络资源出错, ${res.status} (${res.statusText})` + ) + } + }) + .then(text => { + templatePool[val] = text + scanTemplate(text) + }) + .catch(err => { + log(':include load [' + val + '] error\n%c%s', 'color:#f30', err) + }) } - - Anot.nextTick(function() { - scanTemplate(el.value || el.innerText || el.innerHTML) - }) } }) diff --git a/src/29-:visible.js b/src/29-:visible.js index 4768851..caf7bed 100644 --- a/src/29-:visible.js +++ b/src/29-:visible.js @@ -4,11 +4,9 @@ function parseDisplay(nodeName, val) { if (!parseDisplay[key]) { var node = DOC.createElement(nodeName) root.appendChild(node) - if (W3C) { - val = getComputedStyle(node, null).display - } else { - val = node.currentStyle.display - } + + val = getComputedStyle(node, null).display + root.removeChild(node) parseDisplay[key] = val } @@ -27,7 +25,7 @@ Anot.directive('visible', { stamp var noEffect = !this.effectName if (!this.stamp) { - stamp = this.stamp = +new Date() + stamp = this.stamp = Date.now() if (val) { elem.style.display = binding.display || '' if (Anot(elem).css('display') === 'none') { diff --git a/src/30-filters.js b/src/30-filters.js index 7e4b47d..3cf3e6e 100644 --- a/src/30-filters.js +++ b/src/30-filters.js @@ -88,7 +88,7 @@ var filters = (Anot.filters = { // IE67chrome // IE67chrome // IE67chrome - sanitize: function(str) { + xss: function(str) { return str.replace(rscripts, '').replace(ropen, function(a, b) { var match = a.toLowerCase().match(/<(\w+)\s/) if (match) { @@ -127,25 +127,20 @@ var filters = (Anot.filters = { }, number: numberFormat, //日期格式化,类似php的date函数, - date: function(stamp, str, second) { - second = second === undefined ? false : true - var oDate - if (!Date.isDate(stamp)) { - if (!/[^\d]/.test(stamp)) { - stamp -= 0 - if (second) { - stamp *= 1000 - } + date: function(stamp, str) { + var oDate = stamp + + if (!Date.isDate(oDate)) { + var tmp = +oDate + if (tmp === tmp) { + oDate = tmp } - oDate = new Date(stamp) - if (oDate + '' === 'Invalid Date') { + oDate = new Date(oDate) + if (oDate.toString() === 'Invalid Date') { return 'Invalid Date' } - } else { - oDate = stamp } return oDate.format(str) } }) -