Vue Props 小秘密:冒号 (😃 和短横线 (-) 到底听谁的?🤔
哈喽,各位 Vue 探索者!👋
你是否曾经在写组件时,对着一堆 props 感到困惑:
- 为什么
label-width要用短横线,而autosize却不用? - 为什么原生的
maxlength也不用短横线? - 为什么
:autosize前面要加个冒号? - 最奇怪的是,给一个简单的
0为什么也要写成:min="0"?
如果你对这些问题点头如捣蒜,那么恭喜你!你不是一个人在战斗。今天,就让我们带上放大镜 🔎,一起把 Vue Props 的这些“潜规则”弄个明明白白!
第一站:HTML 世界 vs. JS 世界 🌉 (多单词的连接规则)
首先,我们来解决最基本的问题:label-width (kebab-case) 和 labelWidth (camelCase) 的关系。
想象一下,你的 Vue 组件是座连接两个世界的桥梁:
-
<template>模板世界:这里是 HTML 的地盘。HTML 属性不区分大小写。为了清晰地表示多单词属性,HTML 的通用语言是kebab-case(短横线命名法),比如font-size。 -
<script>脚本世界:这里是 JS 的地盘。JS 区分大小写,并且变量命名规范是camelCase(驼峰命名法)。你总不能写let label-width = '100px'吧,JS 会以为你要做减法呢!😅
Vue 就是那个聪明的翻译官 🗣️。当它在模板里看到由多个单词组成的 label-width 时,会自动把它翻译成脚本里 props 定义的 labelWidth。
✅ 规则 #1: 对于多个单词组成的自定义 prop,在模板中请使用 kebab-case。
第二站:原生 Attribute 的“特权” 👑
“等等!” 你可能会说,“那为什么 maxlength 就不用写成 max-length 呢?”
问得好!因为 maxlength, placeholder, disabled 这些是 HTML 原生的 Attribute,它们是 Web 世界的“原住民”。
Vue 非常尊重这些原住民,它遵循一个原则:如果一个 prop 的名字和原生 HTML attribute 完全一样,就保持原样使用。
这样做的好处是符合直觉,所有人都知道 <input maxlength="200">,没必要在 Vue 里强行改变它。
✅ 规则 #2: 当 prop 名与原生 HTML attribute 相同时,直接使用原生写法。
第三站:“单身贵族”的自在 ✨ (单个单词的命名)
现在,我们来解答 autosize 的谜题。为什么它既不是 auto-size 也不是 AutoSize?
答案很简单:因为它只有一个单词!
kebab-case 和 camelCase 这两种命名法的存在,就是为了连接多个单词。如果只有一个单词,那它根本就不需要任何“连接符”或“大小写”来分隔。
-
label+width➡️label-width -
show+word+limit➡️show-word-limit -
autosize(一个词) ➡️ 就是autosize
它就像城市名 “London”,你直接写 london 就好,完全不需要画蛇添足地改成 lon-don。
✅ 规则 #3: 对于单个单词组成的 prop,它在模板和脚本中的写法是完全一样的。
第四站:冒号 (😃 的魔法——开启“JS 模式” 🪄
我们已经解决了所有关于名字的困惑,现在来面对最强大的魔法——关于值的冒号 (:),也就是 v-bind 的简写。
当你给一个属性加上冒号,你就在对 Vue 说:
“别把后面的东西当字符串!把它当作真正的 JavaScript 来执行!”
这个冒号就像一个模式切换器,瞬间将你从“HTML 字符串模式”切换到“JavaScript 表达式模式”。
为什么 :min="0" 必须加冒号?
这是最容易混淆的地方!0 看起来那么简单,为什么还要“JS 模式”?
因为数据类型!
| 写法 | 传递的值 | 数据类型 |
|---|---|---|
min="0" |
字符串 '0'
|
String 😥 |
:min="0" |
数字 0
|
Number 😊 |
el-input-number 组件需要用 min 来做数学比较。用数字和数字比较才是最安全、最准确的。如果你传了个字符串 '0',虽然 JS 的隐式转换有时能“蒙混过关”,但这是潜在 bug 的温床!
✅ 规则 #4: 当你想传递非字符串类型的值(数字、布尔值、对象、数组、变量等)时,必须使用冒号 (:)。
终极备忘录:一张图搞定所有! 📋
| 当你想传递… | 需要冒号 (😃 吗? | Prop 命名法 | 示例 |
|---|---|---|---|
| 固定的字符串 | ❌ 不需要 | 多单词用 kebab-case
|
label-width="140px" |
| 原生 Attribute | ❌ 不需要 | 原生写法 | maxlength="200" |
| 数字 (Number) | ✅ 必须 | 单/多单词均可 | :min="0" |
| 布尔值 (Boolean) | ✅ 必须 | 单/多单词均可 | :disabled="true" |
| 对象 (Object) | ✅ 必须 | 单/多单词均可 | :autosize="{...}" |
| 数组 (Array) | ✅ 必须 | 单/多单词均可 | :options="['A', 'B']" |
| 变量或表达式 | ✅ 必须 | 单/多单词均可 | :user-name="user.name" |
决策流程图 🧭
下面这张图可以帮助你快速做出决策:
组件通信时序图 📬
看看当父组件传递一个 Prop 给子组件时,Vue 在幕后都做了些什么:
Prop 状态图 🚦
一个 Prop 在组件生命周期中可能经历的状态:
组件关系类图 🏛️
从类的角度看父子组件和 Props 的关系:
实体关系图 (ERD) 🔗
组件、Prop 和数据类型之间的实体关系:
附录:英文缩写全称
- JS: JavaScript (一种高级的、解释型的编程语言,是万维网的核心技术之一)
- HTML: HyperText Markup Language (超文本标记语言,用于创建网页的标准标记语言)
- ERD: Entity Relationship Diagram (实体关系图)
思维导图总结 🧠
-
Vue Props 使用指南
-
核心困惑点
- 为什么 prop 命名风格不统一?
- 为什么有时需要加冒号 (
:)?
-
第一部分:Prop 的命名规则 (The Name)
-
规则 1:多单词自定义 Prop
- 模板 (
<template>):kebab-case(短横线),如label-width - 脚本 (
<script>):camelCase(驼峰),如labelWidth - 角色:Vue 自动翻译 🌉
- 模板 (
-
规则 2:原生 HTML Attribute
- 规则:保持原生写法
- 示例:
maxlength,placeholder - 角色:尊重 Web 标准 👑
-
规则 3:单单词 Prop
- 规则:无需转换,保持原样
- 示例:
autosize,type - 角色:命名法的基础 ✨
-
规则 1:多单词自定义 Prop
-
第二部分:Prop 的赋值规则 (The Value)
-
核心:冒号 (
:) = 开启“JS 模式” 🪄 -
场景 1:传递纯字符串
- 规则:不加冒号
- 示例:
label="备注"
-
场景 2:传递非字符串
- 规则:必须加冒号
- 示例:
-
数字:
:min="0"(传递的是 Number0) -
布尔值:
:disabled="true" -
对象:
:autosize="{...}" -
数组:
:options="['A']" -
变量:
:user="currentUser"
-
数字:
-
核心:冒号 (
-
总结:两步决策法
-
第一步 (看值):我要传的是不是纯字符串?
- 是 -> 不加冒号。
- 否 -> 必须加冒号。
-
第二步 (看名):如果没加冒号,Prop 名是什么?
-
多单词 -> 用
kebab-case。 - 单单词或原生 -> 直接写。
-
多单词 -> 用
-
第一步 (看值):我要传的是不是纯字符串?
-
核心困惑点
恭喜你,探索者!你已经成功通关了 Vue Props 的所有关卡。希望这篇详尽的指南能成为你工具箱里的一件利器!
Happy Coding! 💻🚀