xinglie / xinglie.github.io

blog
https://xinglie.github.io
153 stars 22 forks source link

再谈attribute和property #100

Open xinglie opened 2 years ago

xinglie commented 2 years ago

attribute和property最早让人熟知应该是jQuery中的attr和prop方法吧,当初很多人分不清楚该在什么情况下用哪个方法,好像都可以。

https://stackoverflow.com/questions/5874652/prop-vs-attr

这里我们不再讨论它们之间的区别及使用场景,假设您已经熟知了这些基础知识。

我们接下来讨论下在当前流行的虚拟dom中如何控制和修改attribute或property

从attribute到property

有了数据驱动界面的开发思路,目前都是开发者操纵数据,数据+模板dsl交由框架完成界面的渲染。用户能控制的只是attribute,很少去操作property。

从attribute到property的映射环境会自动帮我们完成,比如

<input disabled />

一个禁用输入的输入框,添加disabled属性即可,通过读取输入框的property(disabled)可以得到true或false,获取是否禁用。而attribute中的值都是字符串,我们无法通过字符串的truefalse表达输入框是否禁用,如

<input disabled="false" />

输入框依然是禁用状态。如果非禁用,只能移除disabled这个attribute

常见框架是如何表达添加或删除attribute

以react为例,如果要表达删除一个attribute,它的值为false即可,这里之所以可以用flase是因为jsx,也即把dsl写在了js里,这个false不是字符串,如

<input disabled={ trueOrFlaseValue } />

如果要表达任意的attribute添加或删除,需要这样

<div data-custom={trusy?trusyExpr:false}></div>

react中需要计算的attribute是不能用引号引起来的。

在magix中,因为dsl采用了标准的html,所以attribute都是使用双引号引起的。

<input disbaled="{{=trueOrFlaseValue}}"/>

首先{{= epxr }}表达式表示输出内容,毕竟要有输出,拿到输出值后才能进行下一步的添加或删除attribute的操作

但因为双引号的存在,即使trueOrFlaseValue返回true或false,上述dsl的最终结果是

<input disbaled="false"/>

依然无法表达disabled需要移除,这是字符串的false,不是property中的false。我们必须要增加新的表达式语法或dsl写法,来告诉编译器或框架这里的true或false要当成property中的true或false处理。因此在magix中需要写成

<input disbaled="{{=trueOrFlaseValue}}?"/>

这里引入了?来表达前面的表达式返回布尔值。同时也支持如果表达a成立,则添加属性b,同时b的值为c的写法,如下

<div b="{{=a}}?{{=c}}"/>

以上表示:如果a为trusy,则添加b attribute,同时它的值是c。如果a为falsy,则删除b attribute

为了开发方便,magix同时引入了??来表达有值,即表达式计算结果不为null或undefined。

<td colspan="{{=tdColspan}}??"></td>

如果tdColspan不为null或undefined,则添加colspan atteribute,同时它的值为tdColspan。同样它也支持下面的写法

<td colspan="{{=tdColspan}}??2"></td>

表达tdColspan不为null或undefined,则添加colspan atteribute,同时它的值为固定的2

关于?或??的位置

是不是把?或??写在{{ }} 里会更好一些?

首先写在{{ }}里面会不太好表达colspan="{{=tdColspan??}}2",个人还是认为 colspan="{{=tdColspan}}??2"表示更好。 其次{{ }} 中的尽量设计为合法的js表达式,而tdColspan??并不是,容易造成理解上的困难