Vue: HTML 区分大小写的解决方法

创建于 2016-02-06  ·  48评论  ·  资料来源: vuejs/vue

问题

所以众所周知,HTML 是不区分大小写的。 myProp="123"被解析为myprop="123" ,这导致了 Vue.js 中的警告,您必须使用my-prop="123"来引用 JavaScript 中声明为myProp的道具

此外,我们还需要对自定义组件应用相同的映射 - 例如,当您定义组件时:

import MyComponent from './my-component'

export default {
  components: {
    MyComponent // es2015 shorhand
  }
}

您必须在模板中使用<my-component>而不是<MyComponent>

这里令人讨厌的部分是因为 Vue.js 依赖于浏览器来预解析模板,当 Vue.js 开始编译它时,案例信息已经丢失了。

理念

如果我们调整匹配逻辑以使事情正常进行会怎样? 例如,使这成为可能:

<MyComponent :myProp="msg"></MyComponent>

为什么?

除了在我们的代码中消除驼峰式与 kebab-case 的不一致之外,还有一些实际原因让我们更喜欢组件和道具的 PascalCase/camelCase:

  1. 道具需要在模板和 JavaScript 中作为属性引用。 里面有连字符会让人很尴尬。 ( myPropthis['my-prop']
  2. 当我们导入另一个组件时,变量名不能是kebab case。 例如,您可以使用import MyComp from './my-comp'my-comp根本不是有效的变量名。 使用 ES2015 对象文字速记,您只需执行components: { MyComp }即可。
  3. 大写的组件名称与常规元素相比更突出,从而更清楚哪些标签是自定义组件,哪些标签不是。

技术细节

底层实现是,当我们处理 props 和组件选项时,我们将它们规范化为小写。 这样,它们在内部匹配过程中简单地变为mycomponentmyprop ,但您仍然可以在应用程序代码中使用所需的大小写。 (实际上用户甚至不需要了解这些内部信息)

潜在的担忧:

  1. 向后兼容性。 小写转换可以与当前的 kebab-case 转换一起完成,因此两种语法可以共存,不会中断。
  2. myPropMyProp在模板中将被视为相同的东西。 但是,在同一个组件中有两个 props 或两个组件仅按大小写区分是没有任何意义的,我们可以很容易地检测和警告这种用法。
  3. 我们是否也应该对自定义事件应用相同的规则? 例如:

html <MyComponent @myEvent="handleIt"></MyComponent>

这基本上意味着事件名称变得不区分大小写,这比 props 和组件名称具有更大的含义,因为这会影响纯 JavaScript 中的事件系统使用。 将所有事件名称标准化为小写是否有意义? 同样,似乎很少有两个事件仅按大小写进行区分(例如,在同一个应用程序中同时拥有myEventmyevent做不同的事情),但我确实希望得到关于此的反馈。

discussion

最有用的评论

提交到内存的一条规则: HTML = kebab-case, JavaScript = camelCase

HTML 我的意思是属性和标签。 当您使用v-bind时,属性值是 JavaScript 表达式,因此适用第二个语句。

所有48条评论

<MyComponent :myProp="msg"></MyComponent>

+
我经常想这样写来看看组件和标签之间的区别

+1

将所有事件名称标准化为小写是否有意义?

是的! 这是有道理的,因为它使代码更具可读性。 我总是将事件名称保持小写,用破折号分隔它们,而不是驼峰式。 我认为为驼峰事件名称添加警告也很好。

这是否意味着 Vuejs 将远离 HTML 规范,采用类似 Angular 的方法

是否存在一些性能问题?

关于潜在问题的一些想法:

  1. 只要存在向后兼容性,无论最终决定如何,我都会很酷,但可能会继续使用 kebab case 方法
  2. 骆驼式和低骆驼式之间缺乏区别可能会让一些人感到困惑。 一般来说, var CamelCase将引用一个类,而var camelCase将引用一个非类变量var camelCase = new CamelCase(); 。 但是,我认为这不是问题,因为您不希望创建以组件命名的类。
  3. 我同意创建两个仅通过案例区分的独特事件将是非常糟糕的编程。

我最大的担忧是与人们的编码方式产生了奇怪的不一致。 例如,所有这些都是有效且相同的: :myprop="" :myProp="" :mYpRoP="" :my-prop=""

👎 在标记中保留 kebab-case,在代码中保留骆驼大小写。 它是 HTML 规范的一部分,对于那些来自其他框架或已经学习标准的人来说,忽略大小写将是一个更大的学习曲线。

我同意@Teevio ,一致性会丢失

HTML 使用 kebab-case 并且 ECMAScript 是一种驼峰式语言,这是一个公认的社区标准。 我们应该将它们分开而不是_hiding_(在 react 中,您可以对呈现自定义属性做出反应的唯一方法是通过 data-* 和 aria-*,这会强制一致性)。

向 _beginner_ 解释为什么(例如通过 MDN 链接甚至这里)camelCase <-> kebab-case 将极大地帮助初学者理解 HTML。

同意 Evan 的观点,可读性和代码一致性更重要!
+1

对我来说,在 HTML 中包含 camelCase 看起来真的很奇怪。

HTML就是HTML,JS就是JS

当前版本刚刚好

已经使用 Vue 6 个月了,那 - 仍然让我每次都喜欢 :( 没什么大不了的,因为 Vue 的警告非常好,我知道我做了什么,但我可以完全理解这里的想法,并支持它+1

+1 向后兼容性。

+1
我同意。 我们需要保持向后兼容性。

将所有事件名称标准化为小写是否有意义?

我同意@azamat-sharapov

@Teevio Vue 组件大致是类:当您执行var MyComp = Vue.extend({ .. })时,您可以执行var myComp = new MyComp() 。 至于多重有效语法问题,它已经存在: :my-prop:MY-PROP:mY-pRop现在都可以正常工作,因为 HTML 只是丢弃了所有案例信息。 与提议的功能没有太大不同。 就像所有的风格争论一样,一切都是关于选择一种风格并坚持下去。

回复@jamesxv7 @moe-szyslak @jonagoldman和其他担心脱离 HTML 标准的人:在 HTML 中编写 camelCase 标签/属性是完全有效的,只是标签/属性名称匹配将以不区分大小写的方式执行. 这就是规范所说的

在 HTML 语法的文档中:

HTML 元素的标签名称可以用小写和大写字母的任意组合编写,这些字母与本文档的 HTML 元素部分中给出的元素名称不区分大小写; 也就是说,标签名称不区分大小写。
HTML 元素的属性名称可以用小写和大写字母的任意组合编写,这些字母与本文档 HTML 元素部分中给出的属性名称不区分大小写; 也就是说,属性名称不区分大小写。

因此,如果使用 PascalCase/camelCase 可以提高代码的一致性/可读性,那么这样做完全符合规范。 这可能并不适合所有人,但如果您更喜欢 kebab-case,您可以继续使用它。

特别是@jamesxv7 :这与 Angular 2 所做的不同。 Angular 2 通过引入定制的 HTML 解析器使他们的模板区分大小写。 相反,Vue 实际上遵循规范,使 JS 对应项不区分大小写。

我更喜欢将烤肉串保存在 html 中。 我喜欢一致性的想法,但我更喜欢规范合规性的想法。

找到 camelCase 标签:. HTML 不区分大小写。 利用反而。 Vue 会自动将其与 JavaScript 中使用 camelCase id 定义的组件进行匹配。

这个警告已经非常简洁地说明了组件注册的工作方式。 也就是说,正如其他人所提到的,我认为在 HTML 中允许 camelCase 很棒,只要仍然可以选择继续编写 kebab。

@yyx990803 是的,同意。 只是想尽可能多地提出反对它的论点,但老实说,我没有任何可以坚持的观点。 就像你提到的那样,归根结底,我们正在争论风格选择。 我个人认为,只要我们能够坚持我们已经拥有的东西,同时可以选择使用新东西(但不是被迫),我对提到的变化很满意。

如果 kebab-case 仍然有效并且使用 camelCase/PascalCase 是一种不会破坏 BC 的选项,那么当我使用它们时,我不能反对添加。 这不是强迫我做不同事情的改变。 这只是一个新的选择。

我唯一能说或建议的就是确保这个选项有据可查,并且 - 干得好,埃文一如既往!

斯科特

也许我们可以从中做出选择:警告或忽略。
假设我有一个组件: myComponent
我在 html 中将其称为mycompOnent我个人更喜欢警告,例如:
we found something that would match "myComponent": "mycompOnent" (line 152), use "my-component" instead
当然,道具也是如此。
我认为以后的可读性比第一次尝试的工作更重要。

我还偶然发现了 kebab-case/camelCase 问题。 但真正的问题是我没有收到任何警告,出了什么问题;)

默认可能是没有警告并且它只是工作,这与我无关。
我认为警告也应该只在调试模式下可见

诸如atone vs a-tone vs at-one类的东西呢? 我想它们虽然很少见。

@simplesmiler kebab case props 仍将使用旧规则与区分大小写的匹配。

这不会提高 Web 标准的透明度。 自定义元素规范规定名称应包含连字符: <my-component/>

@simplesmiler说的怎么样: addOneadDone将执行相同的代码。 这对于事件的实现来说尤其令人讨厌,

并且由于 html 不区分大小写,所以我们不要从库中引入大小写的概念。 这种实现只会促进 html 中的大小写,在我看来这是一个坏主意。

此外,我们在文件名中使用连字符分隔。 我们是否也应该将它们移除,然后开始添加外壳?

最后:让 hypen 和 case 系统共存可以为团队中的新开发人员促进不同的编码风格。

我更喜欢@paulpflug的方法; 在这方面适当的警告会有很大帮助。

我不喜欢制作 HTML Pascal/Camel 案例。 它打破了网络标准,我知道保持一致性很好。

通过试图让事情变得最细微的一致,你又增加了一层复杂性。 它也可能是诱人的不良做法。 一个库应该提倡遵守标准而不是误导开发人员,因为有一天他们可能不得不在一个不使用 Vue 的地方工作,导致不理解为什么 HTML 的解析方式不同。

我完全同意@paulpflug :添加警告意味着生产代码的工作量减少,并使开发人员回到编写有效代码的轨道上。

关于为什么不应该实施的一个很好的论证案例:http: //eisenbergeffect.bluespire.com/on-angular-2-and-html/

这通常是人们不喜欢 Angular 2 的一个突出原因。我完全同意保持库符合标准。 它曾经是为 HTML 区分大小写而起草的,但由于太多的问题和打开了太多灵活性的情况而被抛弃了。

@blake-newman:关于这个,我想@yyx990803已经在之前的评论中谈到过。

@jamesxv7那条评论总结得很好; Evan 并没有提议改变 HTML 规范,他提议改变 Vue 定位组件名称的方式。 与其将 kebab 转换为 camel 并找到匹配的组件,它可能会去除破折号(以适应 kebab),然后搜索不区分大小写的组件。 HTML 本身将继续符合规范。 它还允许我们使用我们想要的任何情况。 这对我来说似乎不是一个邪恶或糟糕的选择:)

@yyx990803您是否计划将<MyComponent>样式作为推广样式(即文档和示例将这样编写),还是只是一种选择,而 kebab-case 样式仍将是主要样式?

@blake-newman 确实阅读了此评论- 它确实符合标准:)

@paulpflug @guidobouman :如果您使用最新版本的vue-loadervueify ,则已经有驼峰式标记和属性的警告。 但是,camelCase 检查必须在编译时执行,因为在运行时,由于 HTML 解析器的行为,案例信息已经丢失。 因此,如果您在没有vue-loadervueify的情况下使用 Vue,则不会(也不会)出现任何警告。

@yyx990803 - 但是,链接到 Web 组件的规范 @blake-newman 确实说明了这一点:

自定义元素类型标识自定义元素接口,是必须与 NCName 产生式匹配的字符序列,必须包含 _U+002D HYPHEN-MINUS 字符_,并且_不得包含任何大写 ASCII 字母_

我只是不太确定这与 Vue 组件有什么关系。 在文档中,您确实说过,您尝试松散地遵循 Web 组件标准。

您可能已经注意到 Vue.js 组件与自定义元素非常相似,后者是 Web 组件规范的一部分。 事实上,Vue.js 的组件语法是根据规范松散地建模的。

所以,我想说规范需要先改变,以允许驼峰式和 PascalCase。

斯科特

@smolinari Vue 文档说它是“松散地建模”而不是“严格地”,在我看来,这为这种变化留下了空间。

@yyx990803案例信息可能会丢失,但仍有可能出现警告。
当我在模板中编写 'mycOmponent' 时,它将被解析为mycomponent但预期是my-component然后 Vue(在调试模式下)应该在 $ my-component mycomponent $ my-component并警告我错误的用法。 丢失的案件信息在这里无关紧要。
可以选择抑制警告并直接匹配(等于您建议的行为)。

-1 迁移到 camelCase/PascalCase。 在 HTML 中看到类似 JS 的语法会有点不和谐。 同样的原因我不能忍受 jsx。
+1 @paulpflug的建议。 如果问题出在新手入门上,为什么不发出警告通知用户问题呢?

@paulpflug 听起来确实是一个有效的想法!

我同意,有一个警告说'mycomponent' is missing, did you mean 'my-component'?感觉比无声替换要好。

@yyx990803是否可以在全局选项 api 上执行此操作?
例如
Vue.config.kebab = true (默认)-> <my-component :my-prop="msg"></my-component>
Vue.config.kebab = false -> <MyComponent :myProp="msg"></MyComponent>

@yyx990803
只是想知道,我们追求的理想是什么?
正如@rpkilby所说, <MyComponent myCustomProp="myProp" data-name="prop" aria-label="Close" onclick="myDialog.close()">看起来很奇怪。

本质上,问题的存在是因为 js 和 html 是不同的技术,使用不同的命名系统。 在两种技术中使用相同的案例(烤肉串或骆驼)会将怪异从一个地方转移到另一个地方,但潜在的问题将持续存在
所以我相信,我们能做的最好的就是划清界限。 和当前行,即 html 上下文中的 kebab case 和 js 上下文中的 camleCase(和 PascalCase)非常好

所以 IMO,我们应该只支持当前的约定,而不是寻找更好的约定。 当然,使用警告来帮助初学者

@prog-rajkamal 是的,我现在倾向于只执行警告。

我现在投票:+1:也只是添加警告。

斯科特

:+1: 用于添加警告

:+1: 也用于警告

通过 ccf9bede6bc39fb62e43e1efe98136c5f35dae6b & d7b55c4ee8491dbd853e28a1527050d2d1e7deab 关闭

一个警告会很棒。 我只花了一个小时试图弄清楚为什么我的自定义事件没有得到响应(答案是它有一个驼峰式名称)。

当您有一个相应的组件或道具会响应您的PascalCase组件或道具的kebab-case版本时,会出现警告。 如果你在事件中打错了,Vue 对此无能为力。

或者你的意思是默认的现有事件道具,比如v-on:keyup@keyup简而言之?

@guidobouman在我的模板文件中有<my-component v-on:customEvent="myMethod"> 。 在一个子组件中,我有this.$emit('customEvent'); 。 当然,父母收听的实际事件是customevent而不是customEvent ,但我花了很长时间才弄清楚这一点,因为它不容易调试。 我在想,对于像我这样健忘的人来说,警告骆驼大小写属性不会被这样解析会很好。 也许这已经在上面讨论过了,如果是这样我道歉。

@anthonygore不幸的是这是不可能的,因为浏览器在 Vue 有机会访问它之前将 html 转换为小写。

我的问题是,为什么 Vue 不能为我们转换它? 为什么我们必须记住 kebab-case in

提交到内存的一条规则: HTML = kebab-case, JavaScript = camelCase

HTML 我的意思是属性和标签。 当您使用v-bind时,属性值是 JavaScript 表达式,因此适用第二个语句。

我的问题是,为什么 Vue 不能为我们转换它? 为什么我们必须记住 vue 文件中的 kebab-case? 对于初学者来说,这让事情变得更加尴尬......我只是为此浪费了最后 20 分钟......

浪费了最后 1.5 小时,因为我不只是用谷歌搜索它...... dxmn

此页面是否有帮助?
0 / 5 - 0 等级