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-14 18:46:34 +08:00
parent eb3d4f82fc
commit 8b21f0a800
36 changed files with 386 additions and 631 deletions

View File

@ -2,10 +2,9 @@
//http://www.cnblogs.com/rubylouvre/archive/2012/12/17/2818540.html
import { Anot, directives, getLongID as markID } from '../seed/core'
function classNames() {
function classNames(...args) {
var classes = []
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i]
for (let arg of args) {
var argType = typeof arg
if (argType === 'string' || argType === 'number' || arg === true) {
classes.push(arg)

View File

@ -8,11 +8,11 @@ var cssDir = Anot.directive('css', {
//转换成对象
var b = {}
newVal.forEach(function(el) {
el && Anot.shadowCopy(b, el)
el && Object.assign(b, el)
})
newVal = b
if (!arrayWarn[this.type]) {
Anot.warn('ms-' + this.type + '指令的值不建议使用数组形式了!')
console.warn('ms-' + this.type + '指令的值不建议使用数组形式了!')
arrayWarn[this.type] = 1
}
}

View File

@ -36,7 +36,7 @@ export var updateDataActions = {
var field = this
var array = field.value
if (!Array.isArray(array)) {
Anot.warn('ms-duplex应用于checkbox上要对应一个数组')
console.warn('ms-duplex应用于checkbox上要对应一个数组')
array = [array]
}
var method = field.dom.checked ? 'ensure' : 'remove'

View File

@ -19,7 +19,7 @@ Anot.directive('for', {
str = str.replace(rforAs, function(a, b) {
/* istanbul ignore if */
if (!rident.test(b) || rinvalid.test(b)) {
Anot.error(
console.error(
'alias ' +
b +
' is invalid --- must be a valid JS identifier which is not a reserved name.'
@ -226,11 +226,7 @@ function updateItemVm(vm, top) {
}
function resetVM(vm, a, b) {
if (Anot.config.inProxyMode) {
vm.$accessors[a].value = NaN
} else {
vm.$accessors[a].set(NaN)
}
vm.$accessors[a].value = NaN
}
function updateList(instance) {

View File

@ -55,6 +55,6 @@ function continueScan(instance, vdom) {
instance.fragment,
instance.vm
))
Anot.shadowCopy(vdom, innerRender.root)
Object.assign(vdom, innerRender.root)
delete vdom.nodeValue
}

View File

@ -31,7 +31,7 @@ Anot.directive('on', {
'\tvar __vmodel__ = this;',
'\t' + filters,
'\treturn ' + body,
'}catch(e){Anot.log(e, "in on dir")}'
'}catch(e){console.log(e, "in on dir")}'
].filter(function(el) {
return /\S/.test(el)
})

View File

@ -33,7 +33,7 @@ function isCorrectDate(value) {
return false
}
//https://github.com/adform/validator.js/blob/master/validator.js
Anot.shadowCopy(Anot.validators, {
Object.assign(Anot.validators, {
pattern: {
message: '必须匹配{{pattern}}这样的格式',
get: function(value, field, next) {

View File

@ -5,7 +5,7 @@ Anot.directive('text', {
init: function() {
var node = this.node
if (node.isVoidTag) {
Anot.error('自闭合元素不能使用ms-text')
console.error('自闭合元素不能使用ms-text')
}
var child = { nodeName: '#text', nodeValue: this.getValue() }
node.children.splice(0, node.children.length, child)

View File

@ -44,7 +44,7 @@ var valiDir = Anot.directive('validate', {
var fn = (vmValidator.onManual = onManual.bind(vmValidator))
validator.onManual = fn
} catch (e) {
Anot.warn(
console.warn(
'要想使用onManual方法必须在validate对象预定义一个空的onManual函数'
)
}
@ -94,12 +94,7 @@ var valiDir = Anot.directive('validate', {
var value = field.value
var elem = field.dom
/* istanbul ignore if */
if (typeof Promise !== 'function') {
//Anot-promise不支持phantomjs
Anot.warn(
'浏览器不支持原生Promise,请下载并<script src=url>引入\nhttps://github.com/RubyLouvre/Anot/blob/master/test/promise.js'
)
}
/* istanbul ignore if */
if (elem.disabled) return
var rules = field.vdom.rules

View File

@ -13,7 +13,7 @@ import { Anot, rnowhite, rword } from '../../seed/core'
}
})
Anot.shadowCopy(Anot.fn, {
Object.assign(Anot.fn, {
hasClass: function(cls) {
var el = this[0] || {}
//IE10+, chrome8+, firefox3.6+, safari5.1+,opera11.5+支持classList,

View File

@ -1,4 +1,4 @@
import { Anot, oneObject, cssHooks } from '../../seed/core'
import { Anot, root, oneObject, cssHooks } from '../../seed/core'
var cssMap = oneObject('float', 'cssFloat')
export { cssMap, cssHooks }
@ -11,7 +11,7 @@ Anot.cssName = function(name, host, camelCase) {
if (cssMap[name]) {
return cssMap[name]
}
host = host || Anot.root.style || {}
host = host || root.style || {}
for (var i = 0, n = prefixes.length; i < n; i++) {
camelCase = Anot.camelize(prefixes[i] + name)
if (camelCase in host) {
@ -103,7 +103,7 @@ Anot.fn.offsetParent = function() {
while (offsetParent && Anot.css(offsetParent, 'position') === 'static') {
offsetParent = offsetParent.offsetParent
}
return Anot(offsetParent || Anot.root)
return Anot(offsetParent || root)
}
/* istanbul ignore next */

View File

@ -18,7 +18,7 @@ Anot.fireDom = function(elem, type, opts) {
if (document.createEvent) {
var hackEvent = document.createEvent('Events')
hackEvent.initEvent(type, true, true, opts)
Anot.shadowCopy(hackEvent, opts)
Object.assign(hackEvent, opts)
elem.dispatchEvent(hackEvent)
}
}

View File

@ -1,4 +1,4 @@
import { Anot, _slice, eventHooks, root, getShortID } from '../../seed/core'
import { Anot, eventHooks, root, getShortID } from '../../seed/core'
import { canBubbleUp } from './canBubbleUp'
/* istanbul ignore if */
var hackSafari = document.ontouchstart
@ -11,10 +11,8 @@ Anot.fn.bind = function(type, fn, phase) {
}
}
Anot.fn.unbind = function(type, fn, phase) {
Anot.fn.unbind = function(...args) {
if (this[0]) {
var args = _slice.call(arguments)
args.unshift(this[0])
Anot.unbind.apply(0, args)
}
return this

View File

@ -1,4 +1,4 @@
import { Anot, Cache } from '../seed/core'
import { Anot, Cache, root } from '../seed/core'
import { cssDiff } from '../directives/css'
import {
css3,
@ -16,7 +16,7 @@ var effectDir = Anot.directive('effect', {
this.value = effect = {
is: effect
}
Anot.warn('ms-effect的指令值不再支持字符串,必须是一个对象')
console.warn('ms-effect的指令值不再支持字符串,必须是一个对象')
}
this.value = vdom.effect = effect
var ok = cssDiff.call(this, effect, this.oldValue)
@ -42,13 +42,13 @@ var effectDir = Anot.directive('effect', {
var globalOption = Anot.effects[is]
if (!globalOption) {
//如果没有定义特效
Anot.warn(is + ' effect is undefined')
console.warn(is + ' effect is undefined')
return
}
var finalOption = {}
var action = actionMaps[option.action]
if (typeof Effect.prototype[action] !== 'function') {
Anot.warn('action is undefined')
console.warn('action is undefined')
return
}
//必须预定义特效
@ -202,7 +202,7 @@ function createAction(action) {
}
setTimeout(function() {
//用xxx-active代替xxx类名的方式 触发CSS3动画
var time = Anot.root.offsetWidth === NaN
var time = root.offsetWidth === NaN
elem.addClass(option[lower + 'ActiveClass'])
//计算动画时长
time = getAnimationTime(dom)
@ -237,7 +237,7 @@ Anot.applyEffect = function(dom, vdom, opts) {
}
}
getAction(opts)
Anot.directives.effect.update(vdom, curEffect, Anot.shadowCopy({}, opts))
Anot.directives.effect.update(vdom, curEffect, Object.assign({}, opts))
} else if (cb) {
cb(dom)
}

View File

@ -1,4 +1,4 @@
import { Anot } from '../seed/core'
import { Anot, escapeRegExp } from '../seed/core'
import { $$skipArray } from '../vmodel/reserved'
/*
@ -64,10 +64,11 @@ function __repeat(array, isArray, cb) {
}
}
}
export function filterBy(array, search) {
export function filterBy(array, search, ...args) {
var type = Anot.type(array)
if (type !== 'array' && type !== 'object') throw 'filterBy只能处理对象或数组'
var args = Anot.slice(arguments, 2)
if (type !== 'array' && type !== 'object') {
throw 'filterBy只能处理对象或数组'
}
var stype = Anot.type(search)
if (stype === 'function') {
var criteria = search._orig || search
@ -75,7 +76,7 @@ export function filterBy(array, search) {
if (search === '') {
return array
} else {
var reg = new RegExp(Anot.escapeRegExp(search), 'i')
var reg = new RegExp(escapeRegExp(search), 'i')
criteria = function(el) {
return reg.test(el)
}

View File

@ -1,218 +1,100 @@
function toInt(str) {
return parseInt(str, 10) || 0
}
function padNumber(num, digits, trim) {
var neg = ''
/* istanbul ignore if*/
if (num < 0) {
neg = '-'
num = -num
}
num = '' + num
while (num.length < digits) {
num = '0' + num
}
if (trim) {
num = num.substr(num.length - digits)
}
return neg + num
}
function dateGetter(name, size, offset, trim) {
return function(date) {
var value = date['get' + name]()
if (offset > 0 || value > -offset) value += offset
if (value === 0 && offset === -12) {
/* istanbul ignore next*/
value = 12
}
return padNumber(value, size, trim)
}
}
function dateStrGetter(name, shortForm) {
return function(date, formats) {
var value = date['get' + name]()
var get = (shortForm ? 'SHORT' + name : name).toUpperCase()
return formats[get][value]
}
}
function timeZoneGetter(date) {
var zone = -1 * date.getTimezoneOffset()
var paddedZone = zone >= 0 ? '+' : ''
paddedZone +=
padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
padNumber(Math.abs(zone % 60), 2)
return paddedZone
}
//取得上午下午
function ampmGetter(date, formats) {
return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]
}
var DATE_FORMATS = {
yyyy: dateGetter('FullYear', 4),
yy: dateGetter('FullYear', 2, 0, true),
y: dateGetter('FullYear', 1),
MMMM: dateStrGetter('Month'),
MMM: dateStrGetter('Month', true),
MM: dateGetter('Month', 2, 1),
M: dateGetter('Month', 1, 1),
dd: dateGetter('Date', 2),
d: dateGetter('Date', 1),
HH: dateGetter('Hours', 2),
H: dateGetter('Hours', 1),
hh: dateGetter('Hours', 2, -12),
h: dateGetter('Hours', 1, -12),
mm: dateGetter('Minutes', 2),
m: dateGetter('Minutes', 1),
ss: dateGetter('Seconds', 2),
s: dateGetter('Seconds', 1),
sss: dateGetter('Milliseconds', 3),
EEEE: dateStrGetter('Day'),
EEE: dateStrGetter('Day', true),
a: ampmGetter,
Z: timeZoneGetter
}
var rdateFormat = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/
var raspnetjson = /^\/Date\((\d+)\)\/$/
export function dateFilter(date, format) {
var locate = dateFilter.locate,
text = '',
parts = [],
fn,
match
format = format || 'mediumDate'
format = locate[format] || format
if (typeof date === 'string') {
if (/^\d+$/.test(date)) {
date = toInt(date)
} else if (raspnetjson.test(date)) {
date = +RegExp.$1
} else {
var trimDate = date.trim()
var dateArray = [0, 0, 0, 0, 0, 0, 0]
var oDate = new Date(0)
//取得年月日
trimDate = trimDate.replace(/^(\d+)\D(\d+)\D(\d+)/, function(_, a, b, c) {
var array = c.length === 4 ? [c, a, b] : [a, b, c]
dateArray[0] = toInt(array[0]) //年
dateArray[1] = toInt(array[1]) - 1 //月
dateArray[2] = toInt(array[2]) //日
return ''
})
var dateSetter = oDate.setFullYear
var timeSetter = oDate.setHours
trimDate = trimDate.replace(/[T\s](\d+):(\d+):?(\d+)?\.?(\d)?/, function(
_,
a,
b,
c,
d
) {
dateArray[3] = toInt(a) //小时
dateArray[4] = toInt(b) //分钟
dateArray[5] = toInt(c) //秒
if (d) {
//毫秒
dateArray[6] = Math.round(parseFloat('0.' + d) * 1000)
}
return ''
})
var tzHour = 0
var tzMin = 0
trimDate = trimDate.replace(/Z|([+-])(\d\d):?(\d\d)/, function(
z,
symbol,
c,
d
) {
dateSetter = oDate.setUTCFullYear
timeSetter = oDate.setUTCHours
if (symbol) {
tzHour = toInt(symbol + c)
tzMin = toInt(symbol + d)
}
return ''
})
dateArray[3] -= tzHour
dateArray[4] -= tzMin
dateSetter.apply(oDate, dateArray.slice(0, 3))
timeSetter.apply(oDate, dateArray.slice(3))
date = oDate
}
}
if (typeof date === 'number') {
date = new Date(date)
}
while (format) {
match = rdateFormat.exec(format)
/* istanbul ignore else */
if (match) {
parts = parts.concat(match.slice(1))
format = parts.pop()
} else {
parts.push(format)
format = null
}
}
parts.forEach(function(value) {
fn = DATE_FORMATS[value]
text += fn
? fn(date, locate)
: value.replace(/(^'|'$)/g, '').replace(/''/g, "'")
if (!Date.prototype.getFullWeek) {
//获取当天是本年度第几周
Object.defineProperty(Date.prototype, 'getFullWeek', {
value: function() {
let thisYear = this.getFullYear()
let that = new Date(thisYear, 0, 1)
let firstDay = that.getDay() || 1
let numsOfToday = (this - that) / 86400000
return Math.ceil((numsOfToday + firstDay) / 7)
},
enumerable: false
})
//获取当天是本月第几周
Object.defineProperty(Date.prototype, 'getWeek', {
value: function() {
let today = this.getDate()
let thisMonth = this.getMonth()
let thisYear = this.getFullYear()
let firstDay = new Date(thisYear, thisMonth, 1).getDay()
return Math.ceil((today + firstDay) / 7)
},
enumerable: false
})
return text
}
var locate = {
AMPMS: {
0: '上午',
1: '下午'
},
DAY: {
0: '星期日',
1: '星期一',
2: '星期二',
3: '星期三',
4: '星期四',
5: '星期五',
6: '星期六'
},
MONTH: {
0: '1月',
1: '2月',
2: '3月',
3: '4月',
4: '5月',
5: '6月',
6: '7月',
7: '8月',
8: '9月',
9: '10月',
10: '11月',
11: '12月'
},
SHORTDAY: {
'0': '周日',
'1': '周一',
'2': '周二',
'3': '周三',
'4': '周四',
'5': '周五',
'6': '周六'
},
fullDate: 'y年M月d日EEEE',
longDate: 'y年M月d日',
medium: 'yyyy-M-d H:mm:ss',
mediumDate: 'yyyy-M-d',
mediumTime: 'H:mm:ss',
short: 'yy-M-d ah:mm',
shortDate: 'yy-M-d',
shortTime: 'ah:mm'
if (!Date.isDate) {
Object.defineProperty(Date, 'isDate', {
value: function(obj) {
return typeof obj === 'object' && obj.getTime ? true : false
},
enumerable: false
})
}
//时间格式化
if (!Date.prototype.format) {
Object.defineProperty(Date.prototype, 'format', {
value: function(str) {
str = str || 'Y-m-d H:i:s'
var week = ['一', '二', '三', '四', '五', '六', '日']
var dt = {
fullyear: this.getFullYear(),
year: this.getYear(),
fullweek: this.getFullWeek(),
week: this.getWeek(),
month: this.getMonth() + 1,
date: this.getDate(),
day: week[this.getDay()],
hours: this.getHours(),
minutes: this.getMinutes(),
seconds: this.getSeconds()
}
var re
dt.g = dt.hours > 12 ? dt.hours - 12 : dt.hours
re = {
Y: dt.fullyear,
y: dt.year,
m: dt.month < 10 ? '0' + dt.month : dt.month,
n: dt.month,
d: dt.date < 10 ? '0' + dt.date : dt.date,
j: dt.date,
H: dt.hours < 10 ? '0' + dt.hours : dt.hours,
h: dt.g < 10 ? '0' + dt.g : dt.g,
G: dt.hours,
g: dt.g,
i: dt.minutes < 10 ? '0' + dt.minutes : dt.minutes,
s: dt.seconds < 10 ? '0' + dt.seconds : dt.seconds,
W: dt.fullweek,
w: dt.week,
D: dt.day
}
for (let i in re) {
str = str.replace(new RegExp(i, 'g'), re[i])
}
return str
},
enumerable: false
})
}
export function dateFilter(stamp, format) {
var oDate = stamp
if (!Date.isDate(oDate)) {
var tmp = +oDate
if (tmp === tmp) {
oDate = tmp
}
oDate = new Date(oDate)
if (oDate.toString() === 'Invalid Date') {
return 'Invalid Date'
}
}
return oDate.format(str)
}
locate.SHORTMONTH = locate.MONTH
dateFilter.locate = locate

View File

@ -19,15 +19,13 @@ var keys = {
right: 39,
down: 40
}
for (var name in keys) {
;(function(filter, key) {
eventFilters[filter] = function(e) {
if (e.which !== key) {
e.$return = true
}
return e
for (let name in keys) {
eventFilters[name] = function(e) {
if (e.which !== keys[name]) {
e.$return = true
}
})(name, keys[name])
return e
}
}
export { eventFilters }

View File

@ -1,17 +1,16 @@
import { Anot } from '../seed/core'
import { numberFilter } from './number'
import { sanitizeFilter } from './sanitize'
import { xss } from './xss'
import { dateFilter } from './date'
import { filterBy, orderBy, selectBy, limitBy } from './array'
import { eventFilters } from './event'
// import { eventFilters } from './event'
import { escapeFilter } from './escape'
var filters = (Anot.filters = {})
Anot.composeFilters = function() {
var args = arguments
Anot.composeFilters = function(...args) {
return function(value) {
for (var i = 0, arr; (arr = args[i++]); ) {
for (let arr of args) {
var name = arr[0]
var filter = Anot.filters[name]
if (typeof filter === 'function') {
@ -36,37 +35,25 @@ Anot.mix(
lowercase(str) {
return String(str).toLowerCase()
},
truncate(str, length, end) {
//length新字符串长度truncation新字符串的结尾的字段,返回新字符串
if (!str) {
return ''
}
str = String(str)
if (isNaN(length)) {
length = 30
}
end = typeof end === 'string' ? end : '...'
return str.length > length
? str.slice(0, length - end.length) + end /* istanbul ignore else*/
: str
truncate(str, len, mark) {
len = len || 30
mark = typeof mark === 'string' ? mark : '...'
return str.slice(0, len) + (str.length <= len ? '' : mark)
},
camelize: Anot.camelize,
date: dateFilter,
escape: escapeFilter,
sanitize: sanitizeFilter,
xss,
number: numberFilter,
currency(amount, symbol, fractionSize) {
return (
(symbol || '\u00a5') +
numberFilter(
amount,
isFinite(fractionSize) ? /* istanbul ignore else*/ fractionSize : 2
)
numberFilter(amount, isFinite(fractionSize) ? fractionSize : 2)
)
}
},
{ filterBy, orderBy, selectBy, limitBy },
eventFilters
{ filterBy, orderBy, selectBy, limitBy }
// eventFilters
)
export { Anot }

View File

@ -1,34 +1,18 @@
import { Anot } from '../seed/core'
function toFixedFix(n, prec) {
var k = Math.pow(10, prec)
return '' + (Math.round(n * k) / k).toFixed(prec)
}
export function numberFilter(number, decimals, point, thousands) {
//https://github.com/txgruppi/number_format
//form http://phpjs.org/functions/number_format/
//number 必需,要格式化的数字
//decimals 可选,规定多少个小数位。
//point 可选,规定用作小数点的字符串(默认为 . )。
//thousands 可选,规定用作千位分隔符的字符串(默认为 , ),如果设置了该参数,那么所有其他参数都是必需的。
number = (number + '').replace(/[^0-9+\-Ee.]/g, '')
var n = !isFinite(+number) ? 0 : +number,
prec = !isFinite(+decimals) ? 3 : Math.abs(decimals),
sep = typeof thousands === 'string' ? thousands : ',',
dec = point || '.',
s = ''
/**
* @number 必需要格式化的数字
* @decimals 可选规定多少个小数位
* @thousands 可选规定用作千位分隔符的字符串默认为 , 如果设置了该参数那么所有其他参数都是必需的
*/
export function numberFilter(number, decimals = 0, thousands = '') {
var num = +number || 0
var d = !isFinite(+decimals) ? 3 : Math.abs(decimals)
var t = typeof thousands === 'string' ? thousands : ','
var tmp
// Fix for IE parseFloat(0.55).toFixed(0) = 0;
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.')
if (s[0].length > 3) {
s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
tmp = ((d ? num.toFixed(d) : Math.round(num)) + '').split('.')
if (tmp[0].length > 3) {
tmp[0] = tmp[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, t)
}
/** //好像没有用
var s1 = s[1] || ''
if (s1.length < prec) {
s1 += new Array(prec - s[1].length + 1).join('0')
s[1] = s1
}
**/
return s.join(dec)
return tmp.join('.')
}

View File

@ -13,7 +13,7 @@ var rsanitize = {
// <a href="jav ascript:alert('XSS');">IE67chrome</a>
// <a href="jav&#x09;ascript:alert('XSS');">IE67chrome</a>
// <a href="jav&#x0A;ascript:alert('XSS');">IE67chrome</a>
export function sanitizeFilter(str) {
export function xss(str) {
return str.replace(rscripts, '').replace(ropen, function(a, b) {
var match = a.toLowerCase().match(/<(\w+)\s/)
if (match) {

View File

@ -1,5 +1,6 @@
import { root } from '../seed/core'
import { Recognizer } from './recognizer'
var root = Anot.root
var supportPointer = !!navigator.pointerEnabled || !!navigator.msPointerEnabled
// 支持pointer的设备可用样式来取消click事件的300毫秒延迟
if (supportPointer) {

View File

@ -89,7 +89,7 @@ export function addScope(expr, type) {
}
return ''
})
var arg = '[' + Anot.quote(filter.trim()) + bracketArgs + ']'
var arg = '[' + JSON.stringify(filter.trim()) + bracketArgs + ']'
return arg
})
filters = 'Anot.composeFilters(' + filters + ')(__value__)'
@ -119,7 +119,7 @@ export function createGetter(expr, type) {
return new Function('__vmodel__', 'return ' + body + ';')
/* istanbul ignore next */
} catch (e) {
Anot.log('parse getter: [', expr, body, ']error')
console.log('parse getter: [', expr, body, ']error')
return Anot.noop
}
}
@ -131,12 +131,12 @@ export function createGetter(expr, type) {
export function createSetter(expr, type) {
var arr = addScope(expr, type)
var body =
'try{ ' + arr[0] + ' = __value__}catch(e){Anot.log(e, "in on dir")}'
'try{ ' + arr[0] + ' = __value__}catch(e){console.log(e, "in on dir")}'
try {
return new Function('__vmodel__', '__value__', body + ';')
/* istanbul ignore next */
} catch (e) {
Anot.log('parse setter: ', expr, ' error')
console.log('parse setter: ', expr, ' error')
return Anot.noop
}
}

View File

@ -1,4 +1,4 @@
import { Anot, config } from '../seed/core'
import { Anot, config, _decode } from '../seed/core'
import { addScope } from './index'
var rimprovePriority = /[+-\?]/
var rinnerValue = /__value__\)$/
@ -12,7 +12,7 @@ export function parseInterpolate(dir) {
index = index === -1 ? str.length : index
var value = str.slice(0, index)
if (/\S/.test(value)) {
tokens.push(Anot.quote(Anot._decode(value)))
tokens.push(JSON.stringify(_decode(value)))
}
str = str.slice(index + config.openTag.length)
if (str) {

View File

@ -50,7 +50,9 @@ Render.prototype = {
} else if (typeof this.root === 'string') {
vnodes = fromString(this.root) //转换虚拟DOM
} else {
return Anot.warn('Anot.scan first argument must element or HTML string')
return console.warn(
'Anot.scan first argument must element or HTML string'
)
}
this.root = vnodes[0]
@ -136,7 +138,7 @@ Render.prototype = {
var type = attr.match(/\w+/g)[1]
type = eventMap[type] || type
if (!directives[type]) {
Anot.warn(attr + ' has not registered!')
console.warn(attr + ' has not registered!')
}
hasDir = true
}
@ -155,7 +157,7 @@ Render.prototype = {
var templateCaches = Anot.serverTemplates
var temp = templateCaches && templateCaches[$id]
if (temp) {
Anot.log('前端再次渲染后端传过来的模板')
console.log('前端再次渲染后端传过来的模板')
var node = fromString(temp)[0]
for (var i in node) {
vdom[i] = node[i]

View File

@ -13,12 +13,6 @@ Anot.init = function(el) {
Anot.fn = Anot.prototype = Anot.init.prototype
export function shadowCopy(destination, source) {
for (var property in source) {
destination[property] = source[property]
}
return destination
}
export var rword = /[^, ]+/g
export var rnowhite = /\S+/g //存在非空字符
export var platform = {} //用于放置平台差异的方法与属性
@ -39,34 +33,16 @@ export function oneObject(array, val) {
}
var op = Object.prototype
export function quote(str) {
return Anot._quote(str)
}
export var inspect = op.toString
export var ohasOwn = op.hasOwnProperty
export var ap = Array.prototype
var hasConsole = typeof console === 'object'
Anot.config = { debug: true }
export function log() {
if (hasConsole && Anot.config.debug) {
Function.apply.call(console.log, console, arguments)
}
}
export { Cache, directive, directives, delayCompileNodes, root }
export function warn() {
if (hasConsole && Anot.config.debug) {
var method = console.warn || console.log
// http://qiang106.iteye.com/blog/1721425
Function.apply.call(method, console, arguments)
}
}
export function error(str, e) {
throw (e || Error)(str)
}
export function noop() {}
export function isObject(a) {
return a !== null && typeof a === 'object'
return a && typeof a === 'object'
}
export function range(start, end, step) {
@ -104,18 +80,14 @@ export function camelize(target) {
})
}
export var _slice = ap.slice
export function slice(nodes, start, end) {
return _slice.call(nodes, start, end)
}
var rhashcode = /\d\.\d{4}/
//生成UUID http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
export function makeHashCode(prefix) {
/* istanbul ignore next*/
prefix = prefix || 'Anot'
/* istanbul ignore next*/
return String(Math.random() + Math.random()).replace(rhashcode, prefix)
export function makeHashCode(prefix = 'anot') {
return (
prefix +
crypto
.getRandomValues(new Uint8Array(8))
.reduce((a, b) => a + b.toString(16), '')
.slice(0, 12)
)
}
//生成事件回调的UUID(用户通过ms-on指令)
export function getLongID(fn) {
@ -148,9 +120,32 @@ export function createFragment() {
return document.createDocumentFragment()
}
export function _decode(str) {
if (rentities.test(str)) {
temp.innerHTML = str
return temp.innerText || temp.textContent
}
return str
}
var rentities = /&[a-z0-9#]{2,10};/
var temp = document.createElement('div')
shadowCopy(Anot, {
//============== config ============
export var config = {
openTag: '{{',
closeTag: '}}',
rtext: /\{\{(.+?)\}\}/g,
rexpr: /\{\{([\s\S]*)\}\}/
}
export function createAnchor(nodeValue) {
return document.createComment(nodeValue)
}
//============ config ============
Object.assign(Anot, {
Array: {
merge: function(target, other) {
//合并两个数组 Anot2新增
@ -176,78 +171,22 @@ shadowCopy(Anot, {
evaluatorPool: new Cache(888),
parsers: {
number: function(a) {
return a === '' ? '' : parseFloat(a) || 0
return a === '' ? '' : +a || 0
},
string: function(a) {
return a === null || a === void 0 ? '' : a + ''
},
boolean: function(a) {
if (a === '') return a
if (a === '') {
return a
}
return a === 'true' || a === '1'
}
},
_decode: function _decode(str) {
if (rentities.test(str)) {
temp.innerHTML = str
return temp.innerText || temp.textContent
}
return str
}
})
//============== config ============
export function config(settings) {
for (var p in settings) {
var val = settings[p]
if (typeof config.plugins[p] === 'function') {
config.plugins[p](val)
} else {
config[p] = val
}
}
return this
}
var plugins = {
interpolate: function(array) {
var openTag = array[0]
var closeTag = array[1]
if (openTag === closeTag) {
throw new SyntaxError('interpolate openTag cannot equal to closeTag')
}
var str = openTag + 'test' + closeTag
if (/[<>]/.test(str)) {
throw new SyntaxError('interpolate cannot contains "<" or ">"')
}
config.openTag = openTag
config.closeTag = closeTag
var o = escapeRegExp(openTag)
var c = escapeRegExp(closeTag)
config.rtext = new RegExp(o + '(.+?)' + c, 'g')
config.rexpr = new RegExp(o + '([\\s\\S]*)' + c)
}
}
export function createAnchor(nodeValue) {
return document.createComment(nodeValue)
}
config.plugins = plugins
config({
interpolate: ['{{', '}}'],
debug: true
})
//============ config ============
shadowCopy(Anot, {
shadowCopy,
oneObject,
inspect,
ohasOwn,
rword,
version: 1,
vmodels: {},
directives,
@ -258,23 +197,12 @@ shadowCopy(Anot, {
validators,
cssHooks,
log,
noop,
warn,
error,
config,
root,
document,
window,
isObject,
range,
slice,
hyphen,
camelize,
escapeRegExp,
quote,
makeHashCode
})

View File

@ -4,7 +4,7 @@ export var directives = {}
export function directive(name, opts) {
if (directives[name]) {
Anot.warn(name, 'directive have defined! ')
console.warn(name, 'directive have defined! ')
}
directives[name] = opts
if (!opts.update) {

View File

@ -24,8 +24,6 @@ Anot.type = function(obj) {
: typeof obj
}
Anot._quote = JSON.stringify
Anot.isFunction = function(fn) {
return typeof fn === 'function'
}
@ -112,8 +110,9 @@ Anot.mix = Anot.fn.mix = function() {
export function isArrayLike(obj) {
/* istanbul ignore if*/
if (obj && typeof obj === 'object') {
var n = obj.length,
str = inspect.call(obj)
var n = obj.length
var str = inspect.call(obj)
if (rarraylike.test(str)) {
return true
} else if (str === '[object Object]' && n === n >>> 0) {
@ -129,7 +128,9 @@ Anot.each = function(obj, fn) {
var i = 0
if (isArrayLike(obj)) {
for (var n = obj.length; i < n; i++) {
if (fn(i, obj[i]) === false) break
if (fn(i, obj[i]) === false) {
break
}
}
} else {
for (i in obj) {

View File

@ -58,7 +58,7 @@ VElement.prototype = {
for (var i in props) {
var val = props[i]
if (skipFalseAndFunction(val)) {
arr.push(i + '=' + Anot.quote(props[i] + ''))
arr.push(i + '=' + JSON.stringify(props[i] + ''))
}
}
arr = arr.length ? ' ' + arr.join(' ') : ''

View File

@ -1,4 +1,4 @@
import { Anot } from '../seed/core'
import { Anot, _decode } from '../seed/core'
export function VText(text) {
this.nodeName = '#text'
@ -10,7 +10,7 @@ VText.prototype = {
toDOM() {
/* istanbul ignore if*/
if (this.dom) return this.dom
var v = Anot._decode(this.nodeValue)
var v = _decode(this.nodeValue)
return (this.dom = document.createTextNode(v))
},
toHTML() {

View File

@ -43,7 +43,7 @@ Action.prototype = {
try {
return this.getter.call(scope, scope)
} catch (e) {
Anot.log(this.getter + ' exec error')
console.log(this.getter + ' exec error')
}
},

View File

@ -79,9 +79,9 @@ export var Computed = (function(_super) {
}
return true
}
cp.set = function() {
cp.set = function(...args) {
if (this.setter) {
Anot.transaction(this.setter, this.vm, arguments)
Anot.transaction(this.setter, this.vm, args)
}
}
cp.get = function() {

View File

@ -55,7 +55,7 @@ Mutation.prototype = {
},
collect() {
Anot.track(name, '被收集')
// Anot.track(name, '被收集')
reportObserved(this)
},

View File

@ -4,158 +4,151 @@ import { Mutation } from './Mutation'
import { Computed } from './Computed'
import { IProxy, canHijack, createProxy } from './share'
if (typeof Proxy === 'function') {
Anot.config.inProxyMode = true
platform.modelFactory = function modelFactory(definition, dd) {
var clone = {}
for (let i in definition) {
clone[i] = definition[i]
delete definition[i]
}
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)
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]
}
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 }
}
for (let i in $computed) {
vm[i] = $computed[i]
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]
}
}
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)) {
//移除一个属性,分三昌:
//1. 移除监听器
//2. 移除真实对象的对应属性
//3. 移除$track中的键名
delete target.$accessors[name]
delete target[name]
target.$track = wrapIt(target.$track)
.replace(wrapIt(name), '')
.slice(1, -1)
}
return true
},
get(target, name) {
if (name === '$model') {
return platform.toJson(target)
}
//收集依赖
var m = target.$accessors[name]
if (m && m.get) {
return m.get()
}
return target[name]
},
set(target, name, value) {
if (name === '$model' || name === '$track') {
return true
}
if (name in $$skipArray) {
target[name] = value
return true
}
var ac = target.$accessors
var oldValue = ac[name] ? ac[name].value : target[name]
if (oldValue !== value) {
if (!target.hasOwnProperty(name)) {
updateTrack(target, name)
}
if (canHijack(name, value, target.$proxyItemBackdoor)) {
var $computed = target.$computed || {}
//如果是新属性
if (!ac[name]) {
target[name] = value //必须设置用于hasOwnProperty
var isComputed = !!$computed[name]
var Observable = isComputed ? Computed : Mutation
ac[name] = new Observable(name, value, target)
return true
}
var mutation = ac[name]
//创建子对象
mutation.set(value)
target[name] = mutation.value
} else {
target[name] = value
}
}
// set方法必须返回true, 告诉Proxy已经成功修改了这个值,否则会抛
//'set' on proxy: trap returned falsish for property xxx 错误
return true
for (let i in $computed) {
vm[i] = $computed[i]
}
//has 只能用于 in 操作符,没什么用删去
}
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
) {
var definition = before.$model
definition.$proxyItemBackdoor = true
definition.$id =
before.$hashcode + String(after.hashcode || Math.random()).slice(6)
definition.$accessors = Anot.mix({}, before.$accessors)
var vm = platform.modelFactory(definition)
vm.$track = before.$track
for (var i in after.data) {
vm[i] = after.data[i]
}
return vm
}
platform.fuseFactory = function fuseFactory(before, after) {
var definition = Anot.mix(before.$model, after.$model)
definition.$id = before.$hashcode + after.$hashcode
definition.$accessors = Anot.mix({}, before.$accessors, after.$accessors)
return platform.modelFactory(definition)
}
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)) {
//移除一个属性,分三昌:
//1. 移除监听器
//2. 移除真实对象的对应属性
//3. 移除$track中的键名
delete target.$accessors[name]
delete target[name]
target.$track = wrapIt(target.$track)
.replace(wrapIt(name), '')
.slice(1, -1)
}
return true
},
get(target, name) {
if (name === '$model') {
return platform.toJson(target)
}
//收集依赖
var m = target.$accessors[name]
if (m && m.get) {
return m.get()
}
return target[name]
},
set(target, name, value) {
if (name === '$model' || name === '$track') {
return true
}
if (name in $$skipArray) {
target[name] = value
return true
}
var ac = target.$accessors
var oldValue = ac[name] ? ac[name].value : target[name]
if (oldValue !== value) {
if (!target.hasOwnProperty(name)) {
updateTrack(target, name)
}
if (canHijack(name, value, target.$proxyItemBackdoor)) {
var $computed = target.$computed || {}
//如果是新属性
if (!ac[name]) {
target[name] = value //必须设置用于hasOwnProperty
var isComputed = !!$computed[name]
var Observable = isComputed ? Computed : Mutation
ac[name] = new Observable(name, value, target)
return true
}
var mutation = ac[name]
//创建子对象
mutation.set(value)
target[name] = mutation.value
} else {
target[name] = value
}
}
// set方法必须返回true, 告诉Proxy已经成功修改了这个值,否则会抛
//'set' on proxy: trap returned falsish for property xxx 错误
return true
}
//has 只能用于 in 操作符,没什么用删去
}
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) {
var definition = before.$model
definition.$proxyItemBackdoor = true
definition.$id =
before.$hashcode + String(after.hashcode || Math.random()).slice(6)
definition.$accessors = Anot.mix({}, before.$accessors)
var vm = platform.modelFactory(definition)
vm.$track = before.$track
for (var i in after.data) {
vm[i] = after.data[i]
}
return vm
}
platform.fuseFactory = function fuseFactory(before, after) {
var definition = Anot.mix(before.$model, after.$model)
definition.$id = before.$hashcode + after.$hashcode
definition.$accessors = Anot.mix({}, before.$accessors, after.$accessors)
return platform.modelFactory(definition)
}

View File

@ -18,17 +18,17 @@ import { Computed } from './Computed'
Anot.define = function(definition) {
var $id = definition.$id
if (!$id) {
Anot.error('vm.$id must be specified')
console.error('vm.$id must be specified')
}
if (Anot.vmodels[$id]) {
Anot.warn('error:[' + $id + '] had defined!')
console.warn('error:[' + $id + '] had defined!')
}
var vm = platform.modelFactory(definition)
return (Anot.vmodels[$id] = vm)
}
/**
* 在未来的版本,Anot改用Proxy来创建VM,因此
* Anot改用Proxy来创建VM,因此
*/
export function IProxy(definition, dd) {
@ -39,16 +39,12 @@ export function IProxy(definition, dd) {
this.$events = {
__dep__: dd || new Mutation(this.$id)
}
if (Anot.config.inProxyMode) {
delete this.$mutations
this.$accessors = {}
this.$computed = {}
this.$track = ''
} else {
this.$accessors = {
$model: modelAccessor
}
}
delete this.$mutations
this.$accessors = {}
this.$computed = {}
this.$track = ''
if (dd === void 0) {
this.$watch = platform.watchFactory(this.$events)
this.$fire = platform.fireFactory(this.$events)
@ -106,14 +102,14 @@ export function canHijack(key, val, $proxyItemBackdoor) {
if ($proxyItemBackdoor) {
if (!$proxyItemBackdoorMap[key]) {
$proxyItemBackdoorMap[key] = 1
Anot.warn(`ms-for中的变量${key}不再建议以$为前缀`)
console.warn(`ms-for中的变量${key}不再建议以$为前缀`)
}
return true
}
return false
}
if (val == null) {
Anot.warn('定义vmodel时' + key + '的属性值不能为null undefine')
console.warn('定义vmodel时' + key + '的属性值不能为null undefine')
return true
}
if (/error|date|function|regexp/.test(Anot.type(val))) {
@ -140,7 +136,7 @@ platform.createProxy = createProxy
platform.itemFactory = function itemFactory(before, after) {
var keyMap = before.$model
var core = new IProxy(keyMap)
var state = Anot.shadowCopy(core.$accessors, before.$accessors) //防止互相污染
var state = Object.assign(core.$accessors, before.$accessors) //防止互相污染
var data = after.data
//core是包含系统属性的对象
//keyMap是不包含系统属性的对象, keys

View File

@ -1,14 +1,8 @@
import { Anot, config } from '../seed/core'
import { Anot } from '../seed/core'
Anot.pendingActions = []
Anot.uniqActions = {}
Anot.inTransaction = 0
config.trackDeps = false
Anot.track = function() {
if (config.trackDeps) {
Anot.log.apply(Anot, arguments)
}
}
/**
* Batch is a pseudotransaction, just for purposes of memoizing ComputedValues when nothing else does.
@ -38,7 +32,7 @@ export function propagateChanged(target) {
export function reportObserved(target) {
var action = Anot.trackingAction || null
if (action !== null) {
Anot.track('征收到', target.expr)
// Anot.track('征收到', target.expr)
action.mapIDs[target.uuid] = target
}
}
@ -52,7 +46,7 @@ export function collectDeps(action, getter) {
targetStack.push(preAction)
}
Anot.trackingAction = action
Anot.track('【action】', action.type, action.expr, '开始征收依赖项')
// Anot.track('【action】', action.type, action.expr, '开始征收依赖项')
//多个observe持有同一个action
action.mapIDs = {} //重新收集依赖
var hasError = true,
@ -62,7 +56,7 @@ export function collectDeps(action, getter) {
hasError = false
} finally {
if (hasError) {
Anot.warn('collectDeps fail', getter + '')
console.warn('collectDeps fail', getter + '')
action.mapIDs = {}
Anot.trackingAction = preAction
} else {
@ -71,7 +65,7 @@ export function collectDeps(action, getter) {
try {
resetDeps(action)
} catch (e) {
Anot.warn(e)
console.warn(e)
}
}
return result

View File

@ -7,13 +7,13 @@ export function validateDOMNesting(parent, child) {
if (parentChild) {
if (parentTag === 'p') {
if (pNestChild[tag]) {
Anot.warn(
console.warn(
'P element can not add these childlren:\n' + Object.keys(pNestChild)
)
return false
}
} else if (!parentChild[tag]) {
Anot.warn(
console.warn(
parentTag.toUpperCase() +
'element only add these children:\n' +
Object.keys(parentChild) +