代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
/*
匹配 ) 或 . 或 + 或 - 或 _ 或 $ 或 ]
*/
var validDivisionCharRE = /[\w).+\-_$\]]/;
/*处理value 解析成正确的value,把过滤器 转换成vue 虚拟dom的解析方法函数 比如把过滤器 ' ab | c | d' 转换成 _f("d")(_f("c")(ab))
* 表达式中的过滤器解析 方法
* @param {*} exp
*/
console.log(parseFilters(' ab | c | d')) //转化成 _f("d")(_f("c")(ab))
function parseFilters(exp) {
// 是否在 ''中
var inSingle = false;
// 是否在 "" 中
var inDouble = false;
// 是否在 ``
var inTemplateString = false;
// 是否在 正则 \\ 中
var inRegex = false;
// 是否在 {{ 中发现一个 culy加1 然后发现一个 } culy减1 直到culy为0 说明 { .. }闭合
var curly = 0;
// 跟{{ 一样 有一个 [ 加1 有一个 ] 减1
var square = 0;
// 跟{{ 一样 有一个 ( 加1 有一个 ) 减1
var paren = 0;
var lastFilterIndex = 0;
var c, prev, i, expression, filters;
for (i = 0; i < exp.length; i++) {
prev = c;
c = exp.charCodeAt(i);
console.log('c ='+exp[i])
console.log('c === 0x7C='+(c === 0x7C))
console.log('exp.charCodeAt(i + 1) !== 0x7C='+(exp.charCodeAt(i + 1) !== 0x7C) )
console.log('exp.charCodeAt(i - 1) !== 0x7C='+(exp.charCodeAt(i - 1) !== 0x7C))
console.log('curly='+(curly))
console.log('!curly='+(!curly))
console.log('square='+(square ))
console.log('!square='+(!square ))
console.log('!paren='+(!paren))
console.log('最后一个='+( c === 0x7C && // pipe
exp.charCodeAt(i + 1) !== 0x7C &&
exp.charCodeAt(i - 1) !== 0x7C && !curly && !square && !paren))
if (inSingle) {
// ' \
if (c === 0x27 && prev !== 0x5C) {
inSingle = false;
}
} else if (inDouble) {
// " \
if (c === 0x22 && prev !== 0x5C) {
inDouble = false;
}
} else if (inTemplateString) {
// `
if (c === 0x60 && prev !== 0x5C) {
inTemplateString = false;
}
} else if (inRegex) {
// 当前在正则表达式中 /开始
// / \
if (c === 0x2f && prev !== 0x5C) {
inRegex = false;
}
} else if (
// 如果在 之前不在 ' " ` / 即字符串 或者正则中
// 那么就判断 当前字符是否是 |
// 如果当前 字符为 |
// 且 不在 { } 对象中
// 且 不在 [] 数组中
// 且不在 () 中
// 那么说明此时是过滤器的一个 分界点
c === 0x7C && // |
exp.charCodeAt(i + 1) !== 0x7C &&
exp.charCodeAt(i - 1) !== 0x7C && !curly && !square && !paren
) {
/*
如果前面没有表达式那么说明这是第一个 管道符号 "|"
再次遇到 | 因为前面 expression = 'message '
执行 pushFilter()
*/
if (expression === undefined) {
// first filter, end of expression
// 过滤器表达式 就是管道符号之后开始
lastFilterIndex = i + 1;
// 存储过滤器的 表达式
expression = exp.slice(0, i).trim(); //这里匹配如果字符串是 'ab|c' 则把ab匹配出来
console.log(expression)
// debugger
} else {
pushFilter();
}
} else {
switch (c) {
case 0x22:
inDouble = true;
break // 匹配"
case 0x27:
inSingle = true;
break // 匹配'
case 0x60:
inTemplateString = true;
break // 匹配`
case 0x28:
paren++;
break // 匹配(
case 0x29:
paren--;
break // 匹配)
case 0x5B:
square++;
break // 匹配[
case 0x5D:
square--;
break // 匹配]
case 0x7B:
curly++;
break // 匹配 {
case 0x7D:
curly--;
break // 匹配 }
case 0x5C:
break // 匹配 \
case 0x2f:
break; // 匹配 /
case 0x7C: // 匹配 |
break;
}
if (c === 0x2f) { // /
var j = i - 1;
var p = (void 0);
// find first non-whitespace prev char
//查找第一个非空白的prev字符
for (; j >= 0; j--) {
p = exp.charAt(j);
if (p !== ' ') {
break
}
}
if (!p || !validDivisionCharRE.test(p)) {
inRegex = true;
}
}
}
}
if (expression === undefined) {
expression = exp.slice(0, i).trim();
} else if (lastFilterIndex !== 0) {
pushFilter();
}
// 获取当前过滤器的 并将其存储在filters 数组中
// filters = [ 'filterA' , 'filterB']
function pushFilter() {
(filters || (filters = [])).push(exp.slice(lastFilterIndex, i).trim());
lastFilterIndex = i + 1;
}
if (filters) {
console.log(filters)
for (i = 0; i < filters.length; i++) {
//把过滤器封装成函数 虚拟dom需要渲染的函数
expression = wrapFilter(expression, filters[i]);
}
}
console.log(expression)
//返回值
return expression
}
/*
生成过滤器的 表达式字符串
如上面的
exp = message
filters = ['filterA','filterB(arg1,arg2)']
第一步 以exp 为入参 生成 filterA 的过滤器表达式字符串 _f("filterA")(message)
第二步 以第一步字符串作为入参 生成第二个过滤器的表达式字符串 _f("filterB")(_f("filterA")(message),arg1,arg2)
=> _f("filterB")(_f("filterA")(message),arg1,arg2)
* @param {string} exp 上一个过滤器的值 没有就是 表达式的值
* @param {string} filter
* @returns {string}
*/
console.log(wrapFilter('abc','defg(hijk)')) //结果 _f("defg")(abc,hijk)
function wrapFilter(exp, filter) {
var i = filter.indexOf('('); //返回字符串第一次出现索引的位置
console.log('i='+i)
if (i < 0) {
// _f: resolveFilter
return ("_f(\"" + filter + "\")(" + exp + ")") //闭包
} else {
//name 是 从字符串开始到(结束的字符串,不包含(
var name = filter.slice(0, i); //截取字符串 arrayObject.slice(start,end)
console.log('==name==')
console.log(name)
//args是从(开始匹配,到字符串末端,不包含(
var args = filter.slice(i + 1); //如果 end 未被规定,那么 slice() 方法会选取从 start 到数组结尾的所有元素。
console.log('==args==')
console.log(args)
return (
"_f(\"" + name + "\")(" + exp +
(
args !== ')' ?
',' + args
: args
)
)
}
}
var defaultTagRE = /\{\{((?:.|\n)+?)\}\}/g; //匹配viwe 视图中的{{指令}}
var regexEscapeRE = /[-.*+?^${}()|[\]\/\\]/g; //匹配特殊符号 - 或者. 或者* 或者+ 或者? 或者^ 或者$ 或者{ 或者} 或者( 或者) 或者| 或者[ 或者] 或者/ 或者\
/**
* Create a cached version of a pure function.
*/
/**
* Create a cached version of a pure function.
* 创建纯函数的缓存版本。
* 创建一个函数,缓存,再return 返回柯里化函数
* 闭包用法
*/
/***********************************************************************************************
*函数名 :cached
*函数功能描述 : 创建纯函数的缓存版本。 创建一个函数,缓存,再return 返回柯里化函数 闭包用法
*函数参数 : fn 函数
*函数返回值 : fn
*作者 :
*函数创建日期 :
*函数修改日期 :
*修改人 :
*修改原因 :
*版本 :
*历史版本 :
***********************************************************************************************/
/*
* var aFn = cached(function(string){
*
* return string
* })
* aFn(string1);
* aFn(string2);
* aFn(string);
* aFn(string1);
* aFn(string2);
*
* aFn 函数会多次调用 里面就能体现了
* 用对象去缓存记录函数
* */
function cached(fn) {
var cache = Object.create(null);
return (function cachedFn(str) {
var hit = cache[str];
return hit || (cache[str] = fn(str))
})
}
var buildRegex = cached(function (delimiters) {
var open = delimiters[0].replace(regexEscapeRE, '\\$&'); //$& 与 regexp 相匹配的子串。 这里的意思是遇到了特殊符号的时候在正则里面需要替换加多一个/斜杠
var close = delimiters[1].replace(regexEscapeRE, '\\$&');
return new RegExp(open + '((?:.|\\n)+?)' + close, 'g') // 匹配开始的open +任意字符或者换行符+ close 全局匹配
});
//匹配view 指令,并且把他转换成 虚拟dom vonde 需要渲染的函数,比如指令{{name}}转换成 _s(name)
//比如字符串 我叫{{name}},今年{{age}},数据{{data.number}}个手机 转换成 我叫+_s(name)+,今年+_s(age)+,数据+_s(data.number)+个手机
function parseText(
text, //字符串
delimiters //被修改默认的标签匹配
) {
var tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE; // 如果delimiters不存在则 用默认指令 {{}},如果修改成其他指令则用其他指令
if (!tagRE.test(text)) { //判断字符串是否含有指令
return
}
var tokens = [];
var rawTokens = [];
var lastIndex = tagRE.lastIndex = 0;
var match, index, tokenValue;
while ((match = tagRE.exec(text))) { //循环能匹配上的指令,全局匹配代码:的时候会有个lastIndex 执行exec方法后,lastIndex就会记录匹配的字符串在原始字符串中最后一位的索引加一,
console.log('match=')
console.log(match)
console.log('match.index='+match.index)
console.log('lastIndex='+lastIndex)
index = match.index; //当前匹配上的字符串位置,也可以是上一次匹配出来的位置
// push text token
if (index > lastIndex) { //
rawTokens.push(tokenValue = text.slice(lastIndex, index)); //截取匹配到字符串指令前面的字符串,并添加到rawTokens
tokens.push(JSON.stringify(tokenValue)); //添加匹配到字符串指令前面的字符串
}
// tag token
//处理value 解析成正确的value,把过滤器 转换成vue 虚拟dom的解析方法函数 比如把过滤器 ' ab | c | d' 转换成 _f("d")(_f("c")(ab))
var exp = parseFilters(match[1].trim()); //
tokens.push(("_s(" + exp + ")")); //把指令转义成函数,便于vonde 虚拟dom 渲染 比如指令{{name}} 转换成 _s(name)
rawTokens.push({'@binding': exp}); //绑定指令{{name}} 指令转换成 [{@binding: "name"}]
lastIndex = index + match[0].length; // 上一次匹配出来的字符串的位置+上一次字符串的长度 比如字符串 我叫{{name}},今年{{age}},数据{{data.number}}个手机 这时候lastIndex 等于10
}
console.log(lastIndex)
console.log(text.length)
if (lastIndex < text.length) { //拼接最后一个字符, 数据{{data.number}}个手机 把个手机 的字符串连接起来
rawTokens.push(tokenValue = text.slice(lastIndex)); //截取字符串。到最后一位
tokens.push(JSON.stringify(tokenValue)); //拼接最后一位字符串
}
return {
expression: tokens.join('+'), //把数组变成字符串,用加号链接 比如数组为 ['我叫','_s(name)',',今年','_s(age)',',数据','_s(data.number)','个手机'] 变成 我叫+_s(name)+,今年+_s(age)+,数据+_s(data.number)+个手机
tokens: rawTokens
}
}
console.log(parseText('我叫{{name}},今年{{age}},数据{{data.number}}个手机'))
// console.log(parseText('{{name}}这个'))
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。