handsome_sai头像

Vue 避坑指南:HTML 大小写问题与驼峰自动转换的终极解析

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:

  1. 在 HTML 标签里写任何属性(不管是传数据还是绑事件),一律用小写字母加短横线(-),绝对不会出错。
  2. 在 JavaScript 里面,变量名、方法名老老实实用驼峰命名(camelCase)。
  3. 重点: 如果你要在 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

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--