Vue JSX中组件名大小写的问题
Vue 官方风格指南
在 Vue 官方的风格指南中,强烈推荐在 JS/JSX 中组件名应该是 PascalCase 的。
JS/JSX 中的组件名应该始终是 PascalCase 的,尽管在较为简单的应用中只使用 Vue.component 进行全局组件注册时,可以使用 kebab-case 字符串。
我原以为在 JSX 中组件名都写成 PascalCase 就好了,然而在使用一些 UI 组件库时,在 render 函数中常常会报某个组件未注册的问题。
例如 iView ,在其官方文档的 快速上手 章节底下,有个 组件使用规范 ,是这样写的:
在非 template/render 模式下(例如使用 CDN 引用时),组件名要分隔,例如 DatePicker 必须要写成 date-picker。
看到这个,我以为这只是这个组件库的规范,于是在报错的时候直接把报错的组件名改成 kebab-case 就好了,也就没再深究。
然而一知半解的下场就是,下次遇到同样的问题,还是会一脸懵逼。
官方示例代码大小写使用情况
我们看到 Vue 官网解释 JSX 的部分有这样一段代码:
1 | import AnchoredHeading from './AnchoredHeading.vue' |
其中 JSX 部分就是 PascalCase 。那为什么在 JSX 中使用 iView 组件时却要 kebab-case ?
而且在 iView 的 table 组件示例中,可以看到这样的代码:
1 | render: (h, params) => { |
我们知道, JSX 最后也会被解析成 h 函数,那么,其中组件名的大小写一定跟 JSX 的解析有关。
所以,我们来看看 Vue 的 JSX 插件 babel-plugin-transform-vue-jsx 怎么说。
来自官方的解释
在 babel-plugin-transform-vue-jsx 的 github README 中,有一段 Component Tip :
If a custom element starts with lowercase, it will be treated as a string id and used to lookup a registered component. If it starts with uppercase, it will be treated as an identifier, which allows you to do:
1 | import Todo from './Todo.js' |
意思就是如果自定义元素是小写开头,就会被当做字符串 id ,会从注册的组件中去查找;如果是大写开头,会被当成一个标识符。
什么意思呢?其实说得不是特别直观,我们直接去看看 PascalCase 跟 kebab-case 分别会被转换成什么样就会明白那段解释了。
Babel Try it out
让我们打开 Babel 官网,点击顶部的 Try it out
。在左侧底部 Add Plugin
把 babel-plugin-transform-vue-jsx
添加进去。
然后输入:
1 | const a = <my-component></my-component> |
马上,我们可以在右侧结果中看到:
1 | ; |
这下清楚了:
- kebab-case 组件名解析成 h 函数时会解析成字符串,自然会去看当前组件有没有注册相应的组件,或者去搜索有没有全局注册的组件。
- PascalCase 组件名解析成 h 函数时会解析成一个标识符,也就是变量,需要你在当前上下文中就定义或者引入这个变量。
结论
那么,在 Vue JSX 里,组件名什么时候用 PascalCase ,什么时候用 kebab-case ,就很明确了:
- 当组件只在全局注册时,一般是使用了组件库,在入口用了
Vue.use
这类,或者自己用了Vue.component
注册的组件,这时候没在当前组件引入时,需要用 kebab-case
例如:
1 | // main.js |
- 当组件在当前组件有引入过时,或者在当前组件定义了的组件,可以直接用 PascalCase ,因为这是直接使用的变量。
例如:
1 | // MyComponent.vue |