本文概览
- 自定义指令部分相关源码
- 指令为啥用的是 v- 而不是其他标识
- 魔改 v- 成其他标识
1.自定义指令部分相关源码
位于 createAppAPI 函数闭包里面的 directive 函数
directive(name, directive) {
{
// 判断是否和内置指令重名
validateDirectiveName(name);
}
if (!directive) {
return context.directives[name];
}
if (context.directives[name]) {
warn$1(`Directive "${name}" has already been registered in target app.`);
}
context.directives[name] = directive;
return app;
}
注册一个全局指令
// 注册全局指令
app.directive('color', {
mounted(el, binding, vnode) {
console.log(binding)
el.style.color = binding.value;
}
});
输出 binding
然后在源码里找到这个对象,位于 new Tokenizer() 里面的ondirname函数
搜索ondirname函数的调用链,找到 class Tokenizer 里面的 stateInDirName 函数
继续搜索 stateInDirName 函数的调用链,位于 class Tokenizer 类里面的 parse 函数
这里的 【case 13:】 是不是很突兀?????接着往下看就对了
2.指令为啥用的是 v- 而不是其他标识
我们继续搜索 this.state = 13 找到 handleAttrStart 函数
c === 118 ???啥意思?---------- 不好意思 unicode编码 118 刚好是 v
peek() {
// index 下一个字符的unicode编码
return this.buffer.charCodeAt(this.index + 1);
}
this.peek() === 45???啥意思?---------- 不好意思 unicode编码 45 刚好是 -
那么,组合起来是不是就是 v-,到这里你悟没有!!!!
3.魔改 v- 成其他标识
我字的unicode编码为 25105,将 handleAttrStart 函数修改如下:
handleAttrStart(c) {
// 我 unicode码 25105
if (c === 25105 && this.peek() === 45) {
// if (c === 118 && this.peek() === 45) {
this.state = 13;
this.sectionStart = this.index;
} else if (c === 46 || c === 58 || c === 64 || c === 35) {
this.cbs.ondirname(this.index, this.index + 1);
this.state = 14;
this.sectionStart = this.index + 1;
} else {
this.state = 12;
this.sectionStart = this.index;
}
}
html
<body>
<div id="app">
<span 我-color="'red'" >{{msg}}</span>
</div>
<script>
const { createApp, ref } = Vue
let rootComponent = {
setup() {
const msg = ref("createApp.directive() 自定义指令")
return {
msg,
}
},
}
let app = createApp(rootComponent)
// 注册全局指令
app.directive('color', {
mounted(el, binding) {
console.log(binding)
el.style.color = binding.value;
}
});
app.mount("#app")
</script>
</body>
指令成功渲染