分享最新“Vue前端”开发规范心得,值得您拥有!

本文详细介绍了Vue组件开发中的最佳实践,包括数据函数化、组件命名规则、v-for使用key、详尽的prop定义、组件样式作用域、避免v-if-v-for结合等。此外,还推荐了组件命名约定、文件结构、单文件组件规范等,以增强代码可读性和复用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

一、强制方法

1) 组件数据

组件的 data 必须是一个函数。
当在组件中使用 data 属性的时候 (除了 new Vue 外的任何地方),它的值必须是返回一个对象的函数。
正例:

// In a .vue file
export default {
 data () {
 return {
 foo: 'bar'
 }
 }
}
// 在一个 Vue 的根实例上直接使用对象是可以的,
// 因为只存在一个这样的实例。
new Vue({
 data: {
 foo: 'bar'
 }
})

反例:

export default {
 data: {
 foo: 'bar'
 }
}

2)组件名为多个单词

组件名应该始终是多个单词的,根组件 App 除外。
正例:

export default {
 name: 'TodoItem',
 // ...
}

反例:

export default {
 name: 'Todo',
 // ...
}

3)为v-for设置键值

总是用 key 配合 v-for。
在组件上_总是_必须用 key 配合 v-for,以便维护内部组件及其子树的状态。甚至在元素上维护可预测的行为,比如动画中的对象固化 (object constancy),也是一种好的做法。
正例:

<ul>
 <li
 v-for="todo in todos"
 :key="todo.id"
 >
 {{ todo.text }}
 </li>
</ul>

反例:

<ul>
 <li v-for="todo in todos">
 {{ todo.text }}
 </li>
</ul>

4)Prop定义

Prop 定义应该尽量详细。
在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。
正例:

props: {
 status: String
}
// 更好的方法!
props: {
 status: {
 type: String,
 required: true,
 validator: function (value) {
 return [
 'syncing',
 'synced',
 'version-conflict',
 'error'
 ].indexOf(value) !== -1
 }
 }
}

反例:
// 这样做只有开发原型系统时可以接受使用!
props: ['status']

5)为组件样式设置作用域

对于应用来说,顶级 App 组件和布局组件中的样式可以是全局的,但是其它所有组件都应该是有作用域的。
这条规则只和单文件组件有关。你不一定要使用 scoped 特性。设置作用域也可以通过 CSS Modules,那是一个基于 class 的类似 BEM 的策略,当然你也可以使用其它的库或约定。
不管怎样,对于组件库,我们应该更倾向于选用基于 class 的策略而不是 scoped 特性。
这让覆写内部样式更容易:使用了常人可理解的 class 名称且没有太高的选择器优先级,而且不太会导致冲突。
正例:

<template>
 <button class="c-Button c-Button--close">X</button>
</template>
<!-- 使用 BEM 约定 -->
<style>
.c-Button {
 border: none;
 border-radius: 2px;
}
.c-Button--close {
 background-color: red;
}
</style>

反例:

<template>
 <button class="btn btn-close">X</button>
</template>
<style>
.btn-close {
 background-color: red;
}
</style>
<template>
 <button class="button button-close">X</button>
</template>
<!-- 使用 `scoped` 特性 -->
<style scoped>
.button {
 border: none;
 border-radius: 2px;
}
.button-close {
 background-color: red;
}
</style>

6)避免 v-if 和 v-for 用在一起

永远不要把 v-if 和 v-for 同时用在同一个元素上。
一般我们在两种常见的情况下会倾向于这样做:
为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,请将 users 替换为一个计算属性 (比如 activeUsers),让其返回过滤后的列表。
为了避免渲染本应该被隐藏的列表 (比如v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ul, ol)。
正例:

<ul v-if="shouldShowUsers">
 <li
 v-for="user in users"
 :key="user.id"
 >
 {{ user.name }}
 </li>
</ul>

反例:

<ul>
 <li
 v-for="user in users"
 v-if="shouldShowUsers"
 :key="user.id"
 >
 {{ user.name }}
 </li>
</ul>

二、强烈推荐(增强可读性)

1)基础组件名

应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V。
正例:

components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue

反例:

components/
|- MyButton.vue
|- VueTable.vue
|- Icon.vue

2)组件文件

只要有能够拼接文件的构建系统,就把每个组件单独分成文件。
当你需要编辑一个组件或查阅一个组件的用法时,可以更快速的找到它。
正例:

components/
|- TodoList.vue
|- TodoItem.vue

反例:

Vue.component('TodoList', {
 // ...
})
Vue.component('TodoItem', {
 // ...
})

3)单文件组件文件的大小写

单文件组件的文件名应该要么始终是单词大写开头 (PascalCase)
正例:

components/
|- MyComponent.vue

反例:

components/
|- myComponent.vue
|- mycomponent.vue

4) 紧密耦合的组件名

和父组件紧密耦合的子组件应该以父组件名作为前缀命名。
如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。
正例:

components/
|- TodoList.vue
|- TodoListItem.vue
|- TodoListItemButton.vue
components/
|- SearchSidebar.vue
|- SearchSidebarNavigation.vue

反例:

components/
|- SearchSidebar.vue
|- NavigationForSearchSidebar.vue

5)单例组件名

只应该拥有单个活跃实例的组件应该以 The 前缀命名,以示其唯一性。
这不意味着组件只可用于一个单页面,而是每个页面只使用一次。这些组件永远不接受任何 prop,因为它们是为你的应用定制的,而不是它们在你的应用中的上下文。如果你发现有必要添加 prop,那就表明这实际上是一个可复用的组件,只是目前在每个页面里只使用一次。
正例:

components/
|- TheHeading.vue
|- TheSidebar.vue

反例:

components/
|- Heading.vue
|- MySidebar.vue

6)模板中的组件名大小写

总是 PascalCase 的
正例:

<!-- 在单文件组件和字符串模板中 -->
<MyComponent/>

反例:

<!-- 在单文件组件和字符串模板中 -->
<mycomponent/>
<!-- 在单文件组件和字符串模板中 -->
<myComponent/>

7)组件名中的单词顺序

组件名应该以高级别的 (通常是一般化描述的) 单词开头,以描述性的修饰词结尾。
正例:

components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue

反例:

components/
|- ClearSearchButton.vue
|- ExcludeFromSearchInput.vue
|- LaunchOnStartupCheckbox.vue
|- RunSearchButton.vue
|- SearchInput.vue
|- TermsCheckbox.vue

8)简单的计算属性

正例:

computed: {
 basePrice: function () {
 return this.manufactureCost / (1 - this.profitMargin)
 },
 discount: function () {
 return this.basePrice * (this.discountPercent || 0)
 },
 finalPrice: function () {
 return this.basePrice - this.discount
 }
}

反例:

computed: {
 price: function () {
 var basePrice = this.manufactureCost / (1 - this.profitMargin)
 return (
 basePrice -
 basePrice * (this.discountPercent || 0)
 )
 }
}

9)完整单词的组件名

组件名应该倾向于完整单词而不是缩写。
正例:

components/
|- StudentDashboardSettings.vue
|- UserProfileOptions.vue

反例:

components/
|- SdSettings.vue
|- UProfOpts.vue

10) 多个特性的元素

多个特性的元素应该分多行撰写,每个特性一行。
正例:

<img
 src="https://vuejs.org/images/logo.png"
 alt="Vue Logo"
>
<MyComponent
 foo="a"
 bar="b"
 baz="c"
/>

反例:

<img src="https://vuejs.org/images/logo.png" alt="Vue Logo">
<MyComponent foo="a" bar="b" baz="c"/>

11)模板中简单的表达式

组件模板应该只包含简单的表达式,复杂的表达式则应该重构为计算属性或方法。
复杂表达式会让你的模板变得不那么声明式。我们应该尽量描述应该出现的是什么,而非如何计算那个值。而且计算属性和方法使得代码可以重用。
正例:

<!-- 在模板中 -->
{{ normalizedFullName }}
// 复杂表达式已经移入一个计算属性
computed: {
 normalizedFullName: function () {
 return this.fullName.split(' ').map(function (word) {
 return word[0].toUpperCase() + word.slice(1)
 }).join(' ')
 }
}

反例:

{{
 fullName.split(' ').map(function (word) {
 return word[0].toUpperCase() + word.slice(1)
 }).join(' ')
}}

12)单文件组件的顶级元素的顺序

单文件组件应该总是让<script>、<template> 和 <style> 标签的顺序保持一致。且 <style> 要放在最后,因为另外两个标签至少要有一个。
正例:

<!-- ComponentA.vue -->
<template>...</template>
<script>/* ... */</script>
<style>/* ... */</style>
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
<think>嗯,用户问的是“文件上传与解析漏洞包括文件上传漏洞、反序列化漏洞、模块引擎漏洞吗”,首先我需要确认用户的问题是否准确。根据之前的对话历史,用户之前要求生成关于Struts2框架漏洞触发路径分类的思维导图,里面将漏洞分为了OGNL表达式注入、文件上传漏洞、组件依赖漏洞和修复建议。 现在用户的问题是关于文件上传与解析漏洞是否包括文件上传漏洞、反序列化漏洞和模块引擎漏洞。这里可能存在一些混淆,因为反序列化漏洞和模板引擎漏洞在之前的分类中被归入“组件依赖漏洞”类别,而文件上传漏洞是单独的一个大类。用户可能误解了文件上传与解析漏洞的范围,认为所有与文件处理或组件相关的漏洞都属于这一类别。 需要明确各个漏洞类型之间的关系。文件上传漏洞主要涉及恶意文件的上传和解析过程中的缺陷,比如文件名或内容类型被注入恶意代码,或者文件解析时的逻辑问题。而反序列化漏洞属于组件依赖问题,通常是因为使用了不安全的反序列化库,如XStream,没有正确限制反序列化的类型,导致攻击者可以执行任意代码。模板引擎漏洞则涉及模板解析时的缺陷,例如Freemarker或Velocity引擎在处理用户输入时未正确过滤,导致OGNL表达式注入。 用户可能是在学习或整理漏洞分类时,对不同类型的归属产生疑问。需要解释清楚,文件上传与解析漏洞通常特指与文件上传功能直接相关的漏洞,而反序列化和模板引擎漏洞更多是组件或依赖库的问题,虽然它们可能在某些情况下与文件处理有关联,但本质上属于不同的类别。 此外,用户可能希望了解这些漏洞是否有重叠或交叉的情况。例如,在文件上传过程中,如果使用了存在缺陷的模板引擎来解析上传的文件内容,可能会导致模板引擎漏洞的触发。但这种情况下,漏洞的根本原因还是模板引擎的处理不当,而不是文件上传本身的逻辑问题。 因此,回答时需要明确指出文件上传与解析漏洞不包括反序列化漏洞和模板引擎漏洞,但某些场景下可能存在关联。同时需要强调分类的重要性,帮助用户正确理解不同漏洞的触发路径和根本原因,以便在防护措施上采取针对性的策略。</think>### 分步解答: **文件上传与解析漏洞**(狭义概念)**并不直接包含反序列化漏洞和模板引擎漏洞**,但三者可能在特定场景下存在关联。具体分类逻辑如下: --- #### **一、文件上传与解析漏洞**(独立类别) - **核心定义**: 与**文件上传功能直接相关**的漏洞,攻击者通过构造恶意文件名、文件内容或利用文件解析逻辑缺陷触发漏洞。 - **典型漏洞**: - **恶意文件名/内容注入**(如S2-045/S2-046) 原理:上传文件时,文件名或`Content-Type`头被解析为OGNL表达式。 - **文件解析逻辑缺陷**(如S2-122) 原理:文件元数据(如路径)拼接至OGNL上下文,导致代码执行。 - **防护重点**: 文件类型校验、内容过滤、解析器安全配置。 --- #### **二、反序列化漏洞**(组件依赖漏洞) - **核心定义**: 因**依赖的第三方库**(如XStream)未限制反序列化类型导致的漏洞,与文件上传无直接关系。 - **典型漏洞**: - **S2-052(CVE-2017-9805)** 原理:攻击者通过构造XML数据触发XStream反序列化漏洞,无需文件上传功能。 - **防护重点**: 配置反序列化白名单,升级安全组件。 --- #### **三、模板引擎漏洞**(组件依赖或二次解析漏洞) - **核心定义**: 因模板引擎(如Freemarker、Velocity)**强制解析用户输入**或**二次解析**导致的漏洞。 - **典型漏洞**: - **S2-053(CVE-2017-12611)** 原理:模板引擎将用户输入强制解析为OGNL表达式。 - **S2-029** 原理:Velocity插件标签属性中注入OGNL表达式。 - **防护重点**: 禁用危险标签、过滤模板输入内容。 --- #### **四、三者的关联性** 1. **文件上传可能触发模板引擎漏洞**: 若上传的文件内容被模板引擎解析(如上传恶意模板文件),可能触发二次解析漏洞。 2. **反序列化漏洞独立存在**: 通常通过HTTP请求中的序列化数据(如XML、JSON)触发,与文件上传无必然关联。 --- ### **总结** - **严格分类**: 文件上传与解析漏洞是独立类别,反序列化漏洞和模板引擎漏洞属于**组件依赖漏洞**。 - **实际场景交叉**: 文件上传功能可能与其他漏洞结合利用(例如上传恶意模板文件+模板引擎漏洞)。 - **防御策略差异**: - 文件上传漏洞:需关注上传功能本身的过滤与校验。 - 反序列化/模板引擎漏洞:需升级依赖库并限制功能权限。 建议通过思维导图明确区分漏洞类型,避免混淆攻击路径与防御重点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小浝仔(๑>؂<๑)

您的鼓励将是我创作的最大激励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值