sync 修饰符
在这个修饰符的背后,vue
会做两步处理。看下面的代码:
<video :title.sync="aa"></video>
<!-- 上述代码会被转述为以下代码 -->
<video :title="aa.b" @update:title="aa.b = $event"></video>
<!-- 如果是动态属性 -->
<video :[title].sync="aa"></video>
<!-- 上述代码会被转述为以下代码 -->
<video :[title]="aa.b" @update:+(title)="aa.b = $event"></video>
复制代码
在这其中,=
右侧的值主要分为三种情况:
a
a.b
a[b]/a[0]
针对上面的三种情况,会出现不同的处理策略。
处理
处理表达式主要分为两种情况
- 单值非链式表达式,如
a
,b
- 链式表达式,如:
a.b
或a[b]
此类的表达式- 对于链式表达式,需要解析出末尾的表达式,使用 $set 进行响应式处理。防止属性没有进行响应式处理而导致不能正常更新
- 基本上面两种情况,最终能得到的如下结果:
- 对于单值表达式会得到
a = $event
- 对于链式表达式会得到
$set(a, b, $event)
- 需要注意的是
b
可以是动态值
- 需要注意的是
- 对于单值表达式会得到
coding
// 根据值得类型解析出赋值表达式
function genAssignmentCode(value, assignment) {
const res = parseModel(value);
if (res.key === null) {
// 这里说明 value 是 a
return `${a} = ${assignment}`;
} else {
return `$set(${res.exp}, ${res.key}, ${assignment})`;
}
}
let str, chr, len, index, expressionStartPos, expressionEndPos;
function parseModel(val) {
val = val.trim();
len = val.length;
// 表示没有动态表达式
// 这里表示 a[b].c
if (val.indexOf("[") < 0 || val.lastIndexOf("]") < len - 1) {
if ((index = val.lastIndexOf(".")) > -1) {
// 说明是 a.b 这样子的表达式
return {
exp: val.slice(0, index),
key: `"${val.slice(index + 1)}"`,
};
} else {
return {
exp: val,
key: null,
};
}
}
// 说明存在动态表达式 a[b]/a[0]
str = val;
index = expressionStartPos = expressionEndPos = 0;
while (!endOf()) {
chr = next();
// 表示 [ 开头的字符串
if(chr === 0x5B){ // 0x5B === '['
parserBracket(chr)
}
}
return {
exp: val.slice(0, expressionStartPos),
key: val.slice(expressionStartPos + 1, expressionEndPos)
}
}
function endOf() {
return index >= len;
}
function next(){
// 每次读取一个字符
return str.charCodeAt(++index)
}
function isStringStart (chr: number): boolean {
// 0x22 代表 " 0x27 表示 '
return chr === 0x22 || chr === 0x27
}
function parserString(chr){
const stringQuote = chr // 记录开始字符 "/'
while(!endOf()){
chr = next()
if(chr === stringQuote){
break
}
}
}
// 解析出中括号中的变量
function parserBracket(chr) {
let inBracket = 1
expressionStartPos = index
while(!endOf()){
chr = next()
if(isStringStart(chr)){
parserString(chr)
continue;
}
if(chr === 0x5B) inBracket++ // [
if(chr === 0x5D) inBracket-- // ]
if(inBracket === 0){
expressionEndPos = index
break
}
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END