Vue 避坑指南:HTML 大小写问题与驼峰自动转换的终极解析
导语:在学习 Vue 的过程中,很多新手(包括我)都会在“组件传值”和“自定义事件”上遇到明明代码逻辑没问题,但页面就是没反应的灵异事件。这往往是因为踩了 HTML 大小写不敏感的历史遗留坑。今天这篇文章,带你彻底搞懂 Vue 中的命名转换规则!
一、 为什么说“HTML 里不分大小写”?
这是 HTML 语言的规范。浏览器在解析 HTML 标签和属性时,会自动把所有大写字母强制变成小写。
假设你在代码里写了:
v-on:removeByIndex
但在浏览器眼里,它实际看到的是:
v-on:removebyindex
但是,JavaScript 是严格区分大小写的!
如果你在 JS 里执行 this.$emit("removeByIndex"),这里面的 B 和 I 是大写。
当 Vue 去匹配事件时,发现左边是 removebyindex,右边是 removeByIndex,它觉得这俩根本不是一回事,所以直接无视了,导致你的方法没有被触发。
二、 到底哪里会自动转换驼峰?
很多人以为 Vue 会“智能”地把所有带横杠的名字都自动转成驼峰。大错特错!
Vue 官方的自动转换,只针对 Props(接收数据),不针对 Events(自定义事件)。
【场景 A:接收数据(Props)—— 会自动转】
- 你在 JS 里定义:
props: ['componentName'] - 你在 HTML 里写:
v-bind:component-name="..." - Vue 的魔法:它在底层看到 HTML 里的短横线(
-),会自动去掉横杠,把后面的首字母大写,帮你转成驼峰componentName,完美对上。
【场景 B:自定义事件(Events)—— 千万别用驼峰】
- 这就是新手最容易踩的坑。因为 HTML 会把大写变小写,Vue 根本没法对事件名做转换。
- Vue 官方推荐规范:在
$emit发送事件和v-on监听事件时,统一使用短横线(kebab-case)或者全小写。
三、 💡 一张表治好你的“命名混乱”
为了避免混淆,请牢记下面这张表:
| 场景 | HTML 里怎么写 | JS 里怎么写 | 转换规则 |
|---|---|---|---|
| 组件名 | <my-component> | Vue.component('my-component', ...) | 统一用短横线(kebab-case) |
| 接收数据 (Props) | v-bind:user-name="..." | props: ['userName'] | Vue 自动把 HTML 的 - 转成 JS 的驼峰 |
| 发送/监听事件 | @custom-event="..." | this.$emit("custom-event") | 两边都老实用短横线或全小写,绝不转换 |
四、 给前端小白的“防脱发”终极建议
既然 HTML 不认大写,以后在写 Vue 代码时,可以直接养成以下习惯,能帮你省去 90% 的奇葩 Bug:
- 在 HTML 标签里写任何属性(不管是传数据还是绑事件),一律用小写字母加短横线(
-),绝对不会出错。 - 在 JavaScript 里面,变量名、方法名老老实实用驼峰命名(camelCase)。
- 重点: 如果你要在 JS 里定义
props,也千万不要用横杠。比如props: ['user-name']虽然能接住数据,但在模板里写{{ user-name }}会变成减法运算直接报错。请老老实实写props: ['userName']。
学会看控制台报错:遇到绑定没反应,第一时间按 F12 打开浏览器的 Console 控制台。通常会有大段红色的警告(比如 Unknown custom element 或者 Property or method is not defined),顺着报错找,一抓一个准。
以下的代码是学习案例,可以配合代码看这篇文章
<!DOCTYPE html>
<html>
<head>
<mate charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<title>自定义事件</title>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in items" v-bind:item="item" v-bind:index="index"
v-on:remove-by-index="removeItemByIndex(index)"></todo-items>
</todo>
</div>
<script>
//定义todo组件
Vue.component('todo', {
template : '<div><slot name=\'todo-title\'></slot><ul><slot name=\'todo-items\'></slot></ul></div>'
})
//定义todo-title组件
Vue.component('todo-title', {
props:['title'],
template: '<div>{{title}}</div>'
})
//定义todo-tiems组件
Vue.component('todo-items', {
props:['item', 'index'],
template: '<li>{{index}}--{{item}}<button @click="remove">删除</button></li>',
methods:{
remove:function(){
this.$emit("remove-by-index", this.index)
}
}
})
var app = new Vue({
el: '#app',
data: {
title: '姓名',
items: ['张三', '李四', '王五']
},
methods: {
removeItemByIndex:function(index){
alert("1");
this.items.splice(index, 1);
}
}
})
</script>
</body>
</html>
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/handsome_sai/article/details/169170981



