Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

组件名称校验错误 #7237

Closed
jingsam opened this issue Dec 14, 2017 · 13 comments
Closed

组件名称校验错误 #7237

jingsam opened this issue Dec 14, 2017 · 13 comments

Comments

@jingsam
Copy link
Contributor

jingsam commented Dec 14, 2017

Version

2.5.10

Reproduction link

iview/iview#2616

Steps to reproduce

pic

What is expected?

不报错

What is actually happening?

报错


v2.5.10 对组件名称校验引入了breaking change,会导致iView的大部分组件报错。

原因在于这个提交644274c将名称校验提取到了统一的函数validateComponentName中,这个函数对组件名称校验前都进行了lowercase。

而原来校验过程并不会对组件名称预先lowercase,而是对HTML、SVG、BuiltinTag做区分对待,参见 element.js

iView从设计初就一直坚持使用大写组件名,从实践中发现CamelCase区分度比camel-case更高,有助于保护程序员的视力😂

关于组件名称,我说说我的理解:

组件名称的校验,主要目的在于让template compiler跳过对标准HTML标签的解析,降低解析负担。例如模板中有大量的div、button标签,对每个标签尝试解析是很大的负担。

这就涉及到一个本质问题,到底哪些标签不应该被解析?

从规范视角、解析器视角、用户视角出发,会得到不同的答案,以下从HTML tag和SVG tag来说明:

规范视角

从规范角度来看,HTML5规定HTML Tag是case-insensitive的,意思是buttonButton是规范有效的标准Tag;SVG规范规定SVG Tag是case-sensitive的,因为SVG遵从XML规范,所以circle是有效的Tag,而Circle不是。

所以从规范视角来看,对HTML标签的判断应该不区分大小写,对SVG的标签的判断应该区分大小写。而element.js的实现中恰好相反,对HTML标签的判断应该区分大小写,对SVG的标签不区分大小写。

解析器视角

对于template compiler来说,它实际上可以区分大小写的。之所以In DOM template中不能区分大小写,是因为浏览器在将HTML片段传给tempalte compiler解析的时候,把tag都抹成为lowercase了,导致大小写信息丢失了。所以你在代码中写的大写标签,经过浏览器处理后,template compiler就看不见了。

之所以对HTML标签进行lowercase处理,是为了匹配方便,总不能对button匹配一次,Button再匹配一次吧。而SVG标签是区分大小写的,所以浏览器对SVG内的标签不做lowercase处理,而是传递给SVG engine处理。对于SVG engine来说,理论上应该拒绝Circle的解析,但实现上为了照顾某些粗心的程序员,估计会做容错处理(猜想,未做证实)。

所以从解析器视角来看,HTML和SVG标签应该都不区分大小写。

用户视角

从用户视角来讲,当他声明一个Button,他的本意到底是说这是一个自定义组件,还是说他手抖了写错了,本意是表示button

当用户在template String中明确写了一个大写标签,我认为有很大的可能性他想表达这个组件是自定义组件。毕竟,现有的各种处理HTML的工具软件输出的HTML是大写标签的,也没见过哪个开发者有用大写表示HTML tag的癖好。

对SVG标签来讲,我还没调查是不是有处理SVG的工具软件输出大写标签,例如有的输出<svg>,有的输出<SVG>。我觉得这块应该遵守规范,输出标签应该按照SVG规范来,即所谓的“宽进严出”。

所以从用户视角来说,HTML和SVG都应该区分大小写。

总结

前面我说了从规范视角、解析器视角和用户视角,会得出不同的结果。那到底按照哪种方式跟好呢?我认为从用户视角是更好的。从用户视角意味着,template compiler能够最大化的反映开发者的本意,减少开发者理解的负担。虽然,template尽量遵守HTML规范,但它本质不是HTML,所以当HTML规范不符合应用场景时,我们应该打破它。

@delenzhang
Copy link

依照这个说明,是想提issue给vue,去修复这个机制?

@icarusion
Copy link

其实关于 iView 标签命名的规范,我和 @jingsam 也是讨论过已久。希望 Vue.js 能够修复,我个人倾向于以下几个原因:

  • 大部分人使用的是 webpack
  • iView 一开始借鉴的 AntDesign,我认为像 ButtonTable 这样的组件命名,更自由,表意,加前缀显得不好看
  • Vue.js 文档中也有过对这种用法的强烈推荐 比如在 webpack 中,推荐使用 MenuItem 而不是 menuitem
  • 觉得 Vue.js 可以对两种环境做区分,不对 webpack 下的标签名做小写转换即可
  • 最后,iView 确实有很多用户在使用,确实也是 Vue.js 生态里重要的一部分,强制破坏那么多 API,对用户很不友好

thanks :)

@banrikun
Copy link

我也习惯用 TitleCase,但使用 Table / Button 之类作为组件名称时,最好还是加上命名空间吧。

@jingsam
Copy link
Contributor Author

jingsam commented Dec 14, 2017

@icarusion vue-template-compiler不好区分环境,因为在浏览器端还要编译string template和x-template,这两种是区分大小写的。Dom template不能区分大小写是因为浏览器将模板灌到compiler前进行了lowercase,导致compiler不知道你源代码中标签的大小写形式,所以这个不是compiler的锅。我提这个issue的意思是校验名称的时候不能随便就lowercase了,这会导致一大堆好的名字都不能用了,例如为避免Button,必须搞出i-button BasicButton等,害死有命名洁癖的强迫性患者

@liril-net
Copy link

以下只是本人的粗浅见解:

规范视角

规范的制定本身就是为了让开发者去遵守的,虽然有 vue template compiler 进行转义,但是组件库作为一个公用的工具,理应带头维护好这一规范,这样有利于维护一个友好的代码风格。关于 SVG 标签不区分大小写,楼主也指出是因为浏览器解析器本身会进行处理,所以 vue template compiler 并不需要对此进行额外的处理。

解析器视角

vue template compiler 本身的解析器是通过正则来做的解析,所以,解析的时候本身其实是带有相应的大小写的。所以并不存在 button 匹配一次,Button 匹配一次会不会不方便的问题。

为了杜绝这些『粗心』的程序员是不是更应该推行全小写 + kebab 风格,而不是随意命名呢?

所以从解析器视角来看,区分大小写并不是技术的问题。

用户视角

从用户视角来讲,当他从上往下扫一遍代码的时候是 Button 还是 el-button 更能让他发觉这是一个第三方组件,而非浏览器原生的 Tag 呢?

当用户明确写了一个大写标签的时候,怎么能确保这不是输入法自动纠正的首字母大写呢?

对于 SVG,写错大小写就是错的,怎么会有用户写错呢?

总结

无论从哪个角度,我都认为遵守 HTML 规范是一个开发者应当做到的基本准则。要不然规范出来是干什么的?

@liril-net
Copy link

『对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。』

所谓的强烈推荐,有明确说明 DOM 中的风格。

@delenzhang
Copy link

@yyx990803 老大出来说明一下

@Litor
Copy link

Litor commented Dec 14, 2017

我这也遇到这个问题了,Table / Button 这种写法我认为阅读和书写更直观,建议在validateComponentName处理时可以区分大小写。

@LordRobert
Copy link

遇到这个问题,Button这种写法挺好的,简介省事、容易区分。

@Justineo
Copy link
Member

Justineo commented Dec 15, 2017

前面我说了从规范视角、解析器视角和用户视角,会得出不同的结果。那到底按照哪种方式跟好呢?我认为从用户视角是更好的。

这有个前提,是「iView 的老用户已经习惯了违背规范的方式」。因为你也说了,从规范视角出发,<Button><button> 是相同的元素。对于一个新接触 iView 甚至是新接触 Vue 用户,TA 并没有「<Button> 是自定义组件,而 <button> 是原生元素」这样的预设思维。

Vue.js 文档中也有过对这种用法的强烈推荐 比如在 webpack 中,推荐使用 MenuItem 而不是 menuitem

这个条目是「强烈推荐」。而「组件名为多单词」可是「必须」的哦。

最后,iView 确实有很多用户在使用,确实也是 Vue.js 生态里重要的一部分,强制破坏那么多 API,对用户很不友好

我认为这个才是真正能说过去的理由。不是因为这么做有多合理,而是因为它已经广泛存在了。

@zhangwei900808
Copy link

vue.esm.js?efeb:576 [Vue warn]: Do not use built-in or reserved HTML elements as component id: Circle

vue.esm.js?efeb:576 [Vue warn]: Do not use built-in or reserved HTML elements as component id: Switch

@galenyuan
Copy link

说了那么多,其实真正理由只有 iView 确实有很多用户在使用,可与 HTML 规范背道而驰真的是一个 很多用户在使用 的库应该做的事么?

@599316527
Copy link

你有写 <Button> 的理由,Vue 也有对 <Button> 报警告的理由嘛。你一定要用这种不符合 HTML 规范的语法也没人拦着,不就是 warning 嘛,不睬他就是了 🤪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests