vue中:表示,深入理解vue
如果你写过vue,对v型装订这个指令一定不陌生。下面小编将从源码层面去带大家剖析一下v型装订背后的原理,需要的小伙伴可以参考下面章的具体内容
目录
一、v-bind关键源码分析1、虚拟绑定化的属性统一存储在哪里:属性映射与属性列表2,解析HTML,解析出属性集合attrs,在开始回调中返回3、在开始回调中创建ASTElement,createASTElement(.属性,)4、创建后元素会生成属性列表和属性映射5、属性的数据类型定义6、绑定属性获取函数二、如何获取v型装订的值1、v-bind:键源码分析2、v-bind:标题源码分析3、v-bind:类源码分析4、五型装订:风格源码分析v绑定:text-content.prop源码分析6、虚拟绑定的修饰符骆驼. sync源码分析
一、v-bind关键源码分析
1、v-bind化的属性统一存储在哪里:attrsMap与attrsList
p v-bind:title=vBindTitle/p
假设为p标签v型装订化了标题属性,我们来分析标题属性在某视频剪辑软件中是如何被处理的。
vue在拿到这个html标签之后,处理title属性,会做以下几步:
解析HTML,解析出属性集合attrs,在开始回调中返回
在开始回调中创建ASTElement,createASTElement(.属性,)
创建后元素会生成属性列表和属性图
至于创建之后是如何处理虚拟绑定:标题这种普通的属性值的,可以在下文的虚拟绑定:src源码分析中一探究竟。
2、解析HTML,解析出属性集合attrs,在start回调中返回
函数handleStartTag(匹配){
.
const l=match.attrs.length
常量属性=新数组(l)
对于(设I=0;I l;i ) {
const args=match.attrs[i]
.
attrs[i]={
名称:args[1],
value: decodeAttr(value,shouldDecodeNewlines)
}
}
.
if (options.start) {
//在这里上传到开始函数
options.start(标记名、属性、一元、匹配开始、匹配结束)
}
}
3、在start回调中创建ASTElement,createASTElement(... ,attrs, ...)
//解析歌舞伎町
parseHTML(模板,{
.
开始(标签、属性、一元、开始、结束){
let element:as element=createasteelement(tag,attrs,currentParent) //注意此处的属性列表
}
})
4、创建后ASTElement会生成attrsList和attrsMap
//创建大西洋时间元素
导出函数createASTElement(
标签:字符串,
attrs: ArrayASTAttr,//属性对象数组
parent:as element void//父元素也是元素
):作为元素{//返回的也是元素
返回{
类型:1,
标签,
属性列表:属性,
attrsMap: makeAttrsMap(attrs),
rawAttrsMap: {},
父母,
儿童:[]
}
}
5、attrs的数据类型定义
//声明一个阿斯塔特属性抽象语法树对象数据类型
声明类型ASTAttr={
名称:字符串;//属性名
值:任意;//属性值
动态?布尔型;//是否是动态属性
开始?数字;
结束?数字
};
6、绑定属性获取函数
绑定属性获取函数getBindingAttr 和 属性操作函数 getAndRemoveAttr
getBindingAttr及其子函数getAndRemoveAttr在处理特定场景下的v型装订十分有用,也就是"虚拟绑定如何处理不同的绑定属性"章节很有用。这里将其列举出来供下文虚拟绑定:键源码分析;虚拟绑定:src源码分析;v绑定:类源码分析;虚拟绑定:样式源码分析;虚拟绑定:数据集。支柱源码分析源码分析参照。
导出函数getBindingAttr(
艾尔:作为一个元素,
名称:字符串,
getStatic?布尔型
):字符串{
常量动态值=
getAndRemoveAttr(el,: name)
getAndRemoveAttr(el, v-bind: name )
if (dynamicValue!=null) {
返回解析过滤器(动态值)
} else if (getStatic!==假){
const静态值=getAndRemoveAttr(El,name)
if (staticValue!=null) {
返回JSON.stringify(staticValue)
}
}
}
//注意:这只是从数组(属性列表)中删除了属性,所以它
//不会被过程属性处理。
//默认情况下,它不会将其从映射(属性图)中移除,因为映射是
编译期间需要。
导出函数getAndRemoveAttr(
艾尔:作为一个元素,
名称:字符串,
removeFromMap?布尔型
):字符串{
让瓦尔
if ((val=el.attrsMap[name])!=null) {
const list=el.attrsList
对于(设i=0,l=list.lengthI li ) {
如果(列表[我].name===name) {
list.splice(i,1) //从属性列表删除一个属性,不会从属性图删除
破裂
}
}
}
if (removeFromMap) {
删除埃尔。属性地图[名称]
}
返回值
}
二、如何获取v-bind的值
以下面代码为例从源码分析某视频剪辑软件是如何获取v型装订的值。
会从记下几个场景去分析:
常见的键属性
绑定一个普通超文本标记语言属性:标题
绑定班级和风格
绑定一个文档对象模型属性:文本内容
vBind:{
key: new Date(),
标题:"这是一个超文本标记语言属性v-bind”,
类:" { borderRadius: isBorderRadius } "
样式:" { minHeight: 100 px ,maxHeight} "
文本内容:"你好,vue v-bind "
}
差异
v-bind:key=vBind.key
v-bind:title=vBind.title
v-bind:class=vBind.class
v-bind:style=vBind.style
绑定:文本内容。prop= vbind。文本内容
/
/div
1、v-bind:key源码分析
函数processKey (el) {
const exp=getBindingAttr(el, key )
if(exp){
.
el.key=exp
}
}
过程键函数中用到了getBindingAttr函数,由于我们用的是v-bind,没有用:所以const动态值=getAndRemoveAttr(El, v-bind: key );getAndRemoveAttr(el, v-bind:key )函数到属性图中判断是否存在v-bind:key ,取这个属性的值赋为英国压力单位并从从属性列表删除,但是不会从属性图删除,最后将 v-bind:key 的值,也就是英国压力单位作为动态值,之后再返回解析过滤后的结果,最后将结果设置为过程键中将元素的关键属性。然后存储在片段中,至于片段是什么,在上面的源码中可以看到。
2、v-bind:title源码分析
标题是一种"非某视频剪辑软件特殊的"也就是普通的超文本标记语言属性。
函数处理属性(el){
const list=el.attrsList
.
if (bindRE.test(name)) { //v-bind
name=name.replace(bindRE,)
值=parseFilters(值)
.
addAttr(el,name,value,list[i],)
}
}
出口常量宾德雷=/^:^\.^v-bind:/
导出函数addAttr(El:as元素,name: string,value: any,range?范围,动态?布尔){
常量属性=动态
?(El。动态属性 (El。动态属性=[]))
:(el.attrs (el.attrs=[]))
attrs。push(rangesettitem({ name,value,dynamic },range))
el.plain=false
}
通过阅读源码我们看出:对于原生的属性,比如标题这样的属性,vue会首先解析出名字和值,然后再进行一系列的是否有修饰语的判断(修饰符的部分在下文中会详细讲解),最终向更新元素的attrs,从而属性列表和属性图也同步更新。
3、v-bind:class源码分析
钢性铸铁的班级在前端开发的展现层面,是非常重要的一层。因此某视频剪辑软件在对于班级属性也做了很多特殊的处理。
函数转换节点(El:as元素,options: CompilerOptions) {
const warn=选项。警告 基本警告
const static Class=getAndRemoveAttr(El, Class )
if (staticClass) {
埃尔。静态类=JSON。stringify(静态类)
}
const class binding=getBindingAttr(El, class ,false /* getStatic */)
如果(类绑定){
el.classBinding=classBinding
}
}
在跨节函数中,会通过getAndRemoveAttr得到静态类,也就是foo在getBindingAttr得到绑定的类,也就是v-bind:class=vBind.class 即v-bind:class= { borderRadius:isBorderRadius } ,将元素的类绑定赋值为我们绑定的属性供后续使用。
4、、v-bind:style源码分析
风格是直接操作样式的优先级仅次于重要的,比班级更加直观的操作样式的一个超文本标记语言属性。某视频剪辑软件对这个属性也做了特殊的处理。
函数转换节点(El:as元素,options: CompilerOptions) {
const warn=选项。警告 基本警告
const static Style=getAndRemoveAttr(El, Style )
if (staticStyle) {
埃尔。静态风格=JSON。stringify(解析样式文本(静态样式))
}
const style binding=getBindingAttr(El, style ,false /* getStatic */)
if (styleBinding) {
el.styleBinding=styleBinding
}
}
在transfromNode函数中,你会通过getAndRemoveAttr得到静态样式,即style= { fontsize: 12px } ;获取getBindingAttr中的绑定样式,即v-bind:style=vBind.style ,即v-bind: class={minheight: 100 px ,maxHeight} ,其中maxHeight是一个变量,它将ASTElement的styleBinding赋值为我们的绑定属性,以备后续使用。
5、v-bind:text-content.prop源码分析
文本是DOM对象的固有属性,因此可以通过prop来识别。如果我们想直接通过vue设置一个DOM prop,可以在DOM节点上修改。
下面我们来看源码。
函数处理属性(el) {
const list=el.attrsList
.
if (bindRE.test(name)) { //v-bind
if(修饰符){
if (modifiers.prop!isDynamic) {
name=camelize(名称)
if(name=== innerHtml )name= innerHtml
}
}
if (modifiers modifiers.prop) {
addProp(el,name,value,list[i],isDynamic)
}
}
}
导出函数add prop(El:as element,name: string,value: string,range?范围,动态?布尔){
(el.props (el.props=[]))。push(rangesettitem({名称,值,动态},范围))
el.plain=false
}
道具?ArrayASTAttr
从上面的源代码我们可以看到,v-bind中的text-content:text-content . prop一开始是驼峰化成textContent的(这是因为DOM属性都是驼峰格式),vue也有兼容innerHtml错误写法的意图。然后通过prop identifier将textContent属性添加到ASTElement的props中,这里的props本质上也是一个ASTAttr。
有一个很值得思考的问题:为什么要这么做?HTML属性和HTML属性的异同?
没有HTML属性可以直接修改DOM的文本内容,需要单独标识。
比通过js手动更新dom的文本节点更快,省去了查询DOM然后替换文本内容的步骤。
你可以在标签上看到我们有v-bind的哪个属性,非常直观。
其实v-bind:title可以理解为v-bind:title.attr,v-bind:text-content.prop,但是vue默认了HTML属性,没有修饰符。
6、v-bind的修饰符.camel .sync源码分析
骆驼只是驼峰,很简单。酪同步没那么简单。它将被扩展到一个更新父组件绑定值的v-on监听器。
其实一开始我也是被这个搞得不知所措。sync修饰符,但是在仔细阅读。同步的成分并结合实际工作,你会发现它的威力。
父母
v-bind:foo=parent.foo
v-on:update foo= parent . foo=$ event
/父母
在vue中,父组件传递给子组件的props不能被子组件直接通过this.props.foo=newFoo修改。除非我们在这个组件中。$emit(updateFoo ,newFoo),然后使用v-on作为父组件中的事件来侦听updateFoo事件。为了提高可读性,可以将$emit的名称改为update:foo,然后改为v-on:update:foo。
有没有更简洁的写法?那是我们的。我是同步操作员。它可以缩写为:
Parent v-bind:foo . sync= Parent . foo /Parent
那就通过这个。子组件中的$emit(update:foo ,new foo);要触发,注意这里的事件名必须是update:xxx的格式,因为在vue的源代码中,使用了的属性。sync修改器将自己生成一个v-on:update:xxx监视器。
下面我们来看源码:
if (modifiers.camel!isDynamic) {
name=camelize(名称)
}
if (modifiers.sync) {
syncGen=genAssignmentCode(值,` $event `)
如果(!isDynamic) {
addHandler(el, update:${camelize(name)} `,syncGen,null,false,warn,list[i])
//Hyphenate是一个断字函数,其中camelize是一个驼峰函数。
if(连字符(名称)!==camelize(name)) {
addHandler(el, update:${hyphenate(name)} `,syncGen,null,false,warn,list[i])
}
}否则{
//带有动态事件名称的处理程序
addHandler(el,` update: (${name})`,syncGen,null,false,warn,list[i],true)
}
}
通过阅读源代码我们可以看到,对于v-bind:foo.sync的属性,vue会判断该属性是否是动态的。如果不是动态属性,先给它加一个驼峰监视器,再给它加一个连字符监视器,比如v-bind:foo-bar.sync,first v-on:update:fooBar,然后v-on:update:foo-bar。通过addHandler添加V-on监控。如果是动态属性,就不会驼峰,也不会断字。通过addHandler老老实实的听那个动态属性的事件(el,update:${name},).
一句话,同步:sync是语法上的糖。将v-bind和v-on简化为v-bind.sync和this。$emit(update:xxx )。我们为子组件提供了一种快速更新父组件数据的方法。
关于带你了解vue中v-bind的这篇文章到此为止。有关vue中v-bind的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。