项目开发规范(前端)
项目开发规范(前端)
一、使用JSX代替SFC进行组件开发
1.1 前言
自从vue2以来,vue官方就推出了一套专属的模板语法进行页面(组件)的开发即SFC(Single File Component)。得益于SFC所来的红利,使得前端开发人员在入门vue开发或者说是MVVM开发变得非常简单。随着社区对JSX需求的声音越来越大,以及对TypeScript更加友好的支持。vue团队在vue3.0更新之后对使用JSX的开发方式进行了更加友好的优化,使得即便在vue中也能更加方便的使用JSX。
在公司中推广使用JSX开发的好处:
从VUE到React的平滑过渡:目前大部分的前端开发对React的熟练程度并不高,而一部分业务的技术选型React无论是成熟度与社区活跃度都优于VUE。所以在公司中推行使用JSX,意在使不熟悉React的同事在一段时间之后也能快熟上手进行开发。
更接近JavaScript:JSX是一种JavaScript的语法拓展,它更加接近于普通的JavaScript代码,而不是模板语法。这使得使用JSX可以更直观的编写组件逻辑,无需在模板中遵循特定的语法规则。
更好的组织代码:使用JSX配合Composition API可以将在原本SFC中必须写在template标签或script标签中的内容在一个文件或多个文件中进行拆分。这使得组件的结构更加清晰和易于维护。
1.2 编写HTML
1.2.1 在页面中展示一段HTML的完整语法
首先使用JSX语法进行VUE的开发,我们需要新建一个拓展名为jsx的文件。然后从vue中导入defineComponent ,并在setup中返回HTML片段。
import {defineComponent} from 'vue'
const App = defineComponent({
setup() {
return () => {
return (
<div>
Hello Vue With JSX
</div>
)
}
}
})
export default App1.2.2 简化语法
虽然setup函数最后返回的是一个函数,我们必须在函数内返回HTML内容。但是如果setup最后只会返回一段HTML片段,那么上面的代码可以简写为:
import {defineComponent} from 'vue'
const App = defineComponent({
setup() {
return () => (
<div>
Hello Vue With JSX
</div>
)
}
})
export default App1.2.3 在setup返回值中对HTML内容进行分片
如果我们需要在setup中对HTML内容进行分片,那么在setup中返回值格式必须是完整格式。我们可以在返回值函数中的函数体内定义更多的HTML片段。
import {defineComponent} from 'vue'
const App = defineComponent({
setup() {
return () => {
const Hobbies = (
<ul>
<li>唱</li>
<li>跳</li>
<li>RAP</li>
</ul>
)
return (
<div>
<p>爱好</p>
<Hobbies />
</div>
)
}
}
})
export default App我们需要注意以下几个部分:
文件拓展名必须是jsx,例如:
App.jsx一个HTML片段中只能存在一个根标签
1.2.3 定义响应式变量与使用插值表达式
在SFC中定义响应式变量的方式有很多种,主要取决于是否在script标签中声明setup标记。但是在JSX中,我们只能在setup中定义响应式变量。
在SFC中我们使用两个大括号的方式来进行插值,但是在JSX中只使用一个大括号来进行插值。并且如果我们使用ref来定义响应式变量,那么在模板插值时必须显示的调用value属性。
import {defineComponent, ref} from 'vue'
const App = defineComponent({
setup() {
const name = ref('laube')
return () => {
return (
<div>
My name is {name.value}
</div>
)
}
}
})
export default App1.2.4 事件监听
在SFC中,我们通常使用v-on或@ 来进行事件的监听。在JSX中,我们需要通过onXXX 对事件进行监听。
import {defineComponent, ref} from 'vue'
const App = defineComponent({
setup() {
function handleBtnClick() {
alert('button clicked')
}
return () => {
return (
<div>
<button onClick={handleBtnClick}>按钮</button>
</div>
)
}
}
})
export default App1.2.5 条件渲染
在SFC中,我们一般使用v-show或v-if来进行条件渲染。这两个VUE内置指令在面对复杂条件判断时会显得比较吃力,我们可能还会搭配计算属性等其他手段进行判断。但是在JSX中,我们只需要按照传统的JS判断方式即可,判断的返回值内容可以定义为JSX片段。
使用if/else
setup() {
const changeName = ref(false)
function handleBtnClick() {
changeName.value = !changeName.value
}
function element() {
if (changeName.value) {
return <h1>Laube</h1>
} else {
return <h1>Cal</h1>
}
}
return () => {
return (
<div>
{element()}
<button onClick={handleBtnClick}>切换</button>
</div>
)
}
}使用三元运算符
上面的代码等价于如下
setup() {
const changeName = ref(false)
function handleBtnClick() {
changeName.value = !changeName.value
}
return () => {
return (
<div>
{changeName.value
? (
<h1>laube</h1>
)
: (
<h1>Cal</h1>
)
}
<button onClick={handleBtnClick}>切换</button>
</div>
)
}
}1.2.6 循环渲染
循环渲染使用JS数组的map函数即可,不用使用v-for
setup() {
const hobbies = ref([
'唱',
'跳',
'篮球'
])
function element() {
return hobbies.value.map(h => <li>{h}</li>)
}
return () => {
return (
<ul>
{element()}
</ul>
)
}
}上面的代码等价于
setup() {
const hobbies = ref([
'唱',
'跳',
'篮球'
])
return () => {
return (
<ul>
{hobbies.value.map(h => <li>{h}</li>)}
</ul>
)
}
}1.2.7 属性绑定
属性绑定与插值一样也是使用大括号包裹,不用使用v-bind
setup() {
const target = 'https://www.baidu.com'
return () => {
return (
<a href={target}>百度</a>
)
}
}1.2.8 style绑定
无论是不是使用SFC,之前定义style行内样式只需要在style属性中书写对应的CSS内容即可。在JSX中,我们需要在style属性后写两个大括号,在大括号中书写CSS内容。需要注意的是,在JSX中行内样式的样式名需要以驼峰的方式书写,样式与样式之间使用逗号分隔。例如下面的背景色样式,在SFC中为background-color 在JSX中则为backgroundColor 。
setup() {
return () => {
return (
<div style={{ width: '100px', height: '100px', backgroundColor: 'red' }}></div>
)
}
}我们可以发现,其实本质上我们给style属性传递了一个对象作为参数。只不过这个对象中的属性都是CSS样式
1.2.9 class绑定
在React的世界中,目前最流行的JSX CSS解决方案有两种:
CSS Module
CSS-IN-JS
上述这两种解决方案在VUE中均有实现,主要注意的是CSS Module方案在vite内部已被支持,如果是使用webpack进行项目构建还需进行单独配置。
1.2.9.1 CSS Module
CSS Module方案是指将CSS进行模块化,CSS文件最终导出一个对象。通过类似使用对象属性的方式对class属性进行赋值。
使用CSS Module方案必须为每个JSX文件(组件)创建对应的CSS文件,且文件后缀必须是.module.css 。如果使用SASS等CSS预处理器,则需要将最后的.css后缀修改为对应的后缀名即可。
首先我们创建一个名为App.module.css的文件
.container {
width: 100px;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
}
.form-title {
color: red;
font-size: 12px;
font-weight: 700;
}然后JSX中用过ESM语法将App.module.css导入
import {defineComponent, ref} from 'vue'
import styles from './App.module.css'
const App = defineComponent({
setup() {
return () => {
return (
<div class={styles.container}>
<p class={styles['form-title']}>标题</p>
</div>
)
}
}
})
export default App上面的示例代码中可以看到,在导入的模块化CSS文件之后就可以在class 属性中进行使用。需要注意的是,我们在CSS文件中定义两种不同风格的样式名,分别是container和form-title 。在使用这两种样式名时需要循序JS中对象属性的使用方式,在属性名中出现中横线时需要通过中括号的方式进行调用。
1.2.9.2 CSS-IN-JS
CSS-IN-JS是一种解决方案的统称,它的主要思想是在JS文件中书写和处理CSS样式,这样的好处是可以更为方便的通过JS变量来对CSS样式进行动态修改。在这个解决方案下已经衍生出了多个优秀的第三方插件。目前较为流行的styled component 。
在React的工作环境中,我们可以直接通过npm i styled-components 进行插件的安装。但是在VUE的环境下,我们需要安装vue3-styled-components 。
import {defineComponent, ref} from 'vue'
import styled from "vue3-styled-components";
const FormContainer = styled.div width: 100px; height: 100px; display: flex; align-items: center; justify-content: center; .form-title { color: red; font-size: 12px; font-weight: 700; }
const App = defineComponent({
setup() {
return () => {
return (
<FormContainer>
<p class='form-title'>标题</p>
</FormContainer>
)
}
}
})
export default App从上面的实例中可以看到,首先我们导入了vue3-styled-components ,并且定义了一个div样式组件FormContainer 。我们需要类似使用组件的方式来使用FormContainer,即把它作为一个标签名。并且还可以通过类似SASS或LESS一样在内部对子元素的样式进行定义。
1.2.9.3 class绑定总结
在上面两个小结中,向大家介绍了两种目前使用广泛的JSX CSS解决方案。这两种解决的方案的取舍,需要更具项目本身而定,在开发B端这种本身并不会出现大量CSS变化的项目时一般可以采用CSS Module 方案,而在面对C端项目时更多的会优先考虑更灵活的CSS-IN-JS方案。
需要注意的是在上面仅仅只是向大家展示了这两种解决方案最基本的使用方式,即如何定义样式。更多的使用方式则需要通过文档等资料自行学习。
1.2.10 双向绑定
JSX语法中的双向绑定与SFC中基本类似
SFC中的语法
<el-input v-model="inputVal" />JSX中的语法
<el-input v-model={inputVal.value} />1.2.11 插槽
1.2.11.1 插槽的定义
JSX中没有<slot> 标签,插槽的定义需要使用双大括号进行包裹。
setup(props, { slots }) {
return () => {
return (
<div>{ slots.default?.() }</div>
)
}
}如果需要使用具名插槽,则需要将default 修改为插槽的名字。
1.2.11.2 插槽的使用
我们可以通过使用v-slots来进行插槽的使用
setup() {
return () => {
return (
<MyComponent
v-slots={{
default: () => <p>默认插槽</p>,
mySlots: () => <p>具名插槽</p>
}}
/>
)
}
}二、前端开发规范
2.1 通用内容
2.1.1 约定
以下所有内容为全公司开发人员必须遵守的开发准则。
2.1.2 示例代码
gitlab仓库中zh-basic-frontend为示例项目以供大家参考
2.1.3 开发工具
WebStore(推荐)
visual Studio Code
VS Code必装插件
ESLint
EditorConfig for VS Code
vscode-styled-components
上述插件会配置到项目.vscode工作区目录中,可以通过vscode的提示按照工作区推荐插件。
2.1.4 Git提交
项目使用了husky和commitlint来规范项目GIT提交,需要使用npm run commit命令来执行git提交操作。
2.2 技术选型
2.2.1 B端技术选型
Vue3.X
Element-Plus
Pinia
Vite
MicroApp
2.2.2 小程序技术选型
taro
NutUI
2.2.3 APP技术选型
ReactNative
Ant Design Mobile
2.3 目录结构
-- 项目名
|
| -- .husky // git hook
| -- .vscode // vscode工作区配置
| -- public // public目录
| -- src // 源码目录
| -- api // 接口目录
| -- assets // 静态资源目录
| -- components // 自定义组件目录
| -- hooks // 自定义hooks目录
| -- layout // 项目布局目录
| -- pages // 页面目录
| -- User // 用户模块
| -- UserPage.jsx // 用户模块主页面
| -- components // 用户模块组件
| -- UserTable.jsx // 用户表格组件
| -- UserEdit.jsx // 用户编辑组件
| -- UserInfo.jsx // 用户详情组件
| -- UserSearch.jsx // 用户搜索组件
| -- router // 路由配置目录
| -- stores // pinia store 目录
| -- utils // 工具类目录2.4 命名规范
代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。正确的英文拼写和语法可以让阅读者易于理解,避免歧义。只有在非常特殊的情况下才能使用拼音命名。
2.4.1 项目命名
项目命名全部采用小写字母,以中划线分隔。最后由frontend结尾以区分前后端项目。
正例:zh-项目名-frontend
2.4.2 目录命名
普通目录:
普通目录采用小写字母,以中划线分隔,有复数结构时要采用复数命名法。
组件目录:
pages中的子目录全部采用大驼峰的方式命名并于开发的功能模块同名,比如用户模块的目录名称为:Usercomponents中的子目录全部采用大驼峰的方式命名,例如:UserPage、BreadCrumb
2.4.3 文件命名
静态资源文件命名
项目命名全部采用小写字母,以中划线分隔
组件命名
pages目录中的页面级别组件的组件名由功能模块名+单词Page组成,例如:UserPagecomponents目录中的自定义组件文件名统一定义为index.jsx,使用其所在目录区分具体组件
2.5 开发范式
2.5.1 页面逻辑的封装
在src目录中有一个hooks目录,我们在这个目录中创建用于封装业务逻辑的全局hook,命名格式为use-模块名.js 。我们将把例如发送http请求、页面业务逻辑等都封装在全局hook中方便复用。
2.5.2 页面开发
以用户模块开发为例,首先在pages目录中创建User子目录。再在User子目录中创建文件UserPage.jsx 、UserPage.styled.js与components 目录。
- page
| -- User
| -- UserPage.jsx
| -- UserPage.styled.js
| -- componentsUserPage.jsx
在这里UserPage.jsx 主要起到一个页面展示与功能中控的作用,例如:展示表格、控制弹窗(抽屉)的展示、加载(重新请求)数据等。我们尽量在开发时保证UserPage.jsx 文件中功能的单一,即只做控制不处理逻辑。
UserPage.styled.js
在项目开发中我们将采用styled-components方式开发组件样式,如果需要用到CSS样式时,一般在页面组件或自定义组件所在目录中创建一个XXX.styled.js用于导出样式组件。
页面组件的样式文件命名为:页面名称.styled.js
自定义组件的样式文件命名为:index.styled.js
components目录
在这里的components目录中主要用户存放一些页面组件的一些二级组件,例如搜索组件、表格组件、编辑组件和详情组件等。
page
| – User
| – UserPage.jsx
| – components
| - UserSearch.jsx
| - UserTable.jsx
| - UserEdit.jsx
| - UserInfo.jsx
2.5.3 CSS样式开发
由于我们采用styled-componetns进行组件样式开发,所以样式组件的变量名使用大驼峰命名,子集样式采用小写字母,以中划线分隔。如下所示:
import styled from 'vue3-styled-components'
export const Container = styled.div .title { // .... } .form-wrapper { // .... }




