前端架构设计1:代码核心

现在的前端领域, 随着JS框架, UI框架和各种库的丰富, 前端架构也变得十分的重要. 如果一个大型项目没有合理的前端架构设计, 那么前端代码可能因为不同的开发人员随意的引入各种库和UI框架, 导致代码量变得异常臃肿, 最终结果可能是代码变得无法维护, 页面性能低下,不得已只能推翻重构. 所以我们需要在项目开始前, 同样的需要对前端代码进行架构, 一旦前端架构师设计出所有前端开发人员都要遵循的检验机制, 建立起系统设计的规范, 那么项目就拥有了可以衡量代码质量的标准, 前端开发人员也能享受到更高效的工作流. 所以, 前端架构的定义可以用以下一句话来总结:

前端架构是一系列工具和流程的集合, 旨在提升前端代码的质量, 并实现高效, 可持续的工作流.

本系列的前端架构文章, 将分别围绕前端架构的四个核心展开, 分别是代码, 流程, 测试, 文档.

前端架构的四个核心

(一) 代码

归根到底, 所有的网站都是由一堆文本文件和资源文件组成的. 当我们面对制作网站所产生的大量代码时, 就会发现为代码和资源设定一个期望是多么重要. 在代码部分, 我们会专注于如果实现系统架构中的HTML, CSS, JavaScript.

(二) 流程

现在早已过了FTP上传文件的时代, 那么现在重要的是思考怎么用工具和流程构建一个高效且避免出错的工作流. 工作流变得越来越复杂, 那些用于它们的工具也同样如此. 这些工具在提高生产力, 加快效率和保持代码一致性上带来了惊人的效果, 但也伴随着过度工程化和抽象化的风险. 所以, 现有的工作流是需要改变的.

(三) 测试

要构建一个可扩展和可持续优化的系统, 必须保证新代码和老代码能够很好的兼容. 我们的代码不会独立存在, 它们都是大型系统中的一部分. 创建覆盖面广泛的测试方案, 能确保老代码还能正常运作.

(四) 文档

一般而言, 如果不是团队中的重要成员要离开, 我们几乎都不会意识到文档的重要性. 等到那个时候, 大家将不得不停下手头的工作, 优先编写所有的文档. 作为前端机构师, 你要善于在项目开发的同时编写良好的文档.

代码核心

(一) HTML

在前端的架构中, HTML作为页面的基础是十分重要的. 如果初始的HTML写得很烂, 将要写出很多不必要的CSS和JavaScript来弥补. 反之, 如果如果初始的HTML写得足够好, 就能写出根据可扩展性和可维护的CSS和JavsScript.

首先我们来看一些初级的前端工程师可能写出的HTML代码:

<div id="header" class="clearfix"> <div id="header-screen" class="clearfix"> <div id="header-inner" class="container-12 clearfix"> <div id="nav-header" role="navigation"> <div class="region" region-navigation> <div class="block block-system block-menu"> <div class="block-inner"> <div class="content"> <ul class="menu"> <li class="first leaf"> <a href="#">菜单1</a> </li> <li class="second leaf"> <a href="#">菜单2</a> </li> </ul> </div> </div> </div> </div> </div> </div> </div> 

这类"div乱炖"的代码, 是很多初级的前端为应付切页面的工作写出来的. 只是单纯为了还原psd图, 而完全你不考虑HTML的可读性和可维护性.

随后, 在HTML5之后, 标签的语义化受到了大家的重视, 采用语义化的标签, 不仅增加了代码的可读性, 也有利于SEO. HTML语义化标签的使用,这也是在前端架构中需要考虑到的,下面我们来看一下使用语言化标签写的这段代码:

 <header><section><nav> <ul> <li> <a href="#"> 菜单1 </a> </li> <li> <a href="#"> 菜单2 </a> </li> </ul> </nav> </section> </header> 

但是如果我们的页面的菜单有数10项的时候, 就会额外添加<li><a href="#">菜单N</a></li>, 这类重复的工作量完全可以交给Mustache这类模板引擎来解决, 已Vue中的模板引擎语法来写HTML, 会减少很多的工作量 :

<template><header><section> <nav> <ul> <li v-for="(item, index) in navList" :key="index"> <a href="#"> {item} </a> </li> </ul> </nav> </section> </header> </template> <script> export default { data() { navList:['菜单1','菜单2','菜单3','菜单4','菜单5','菜单6','菜单7','菜单8','菜单9','菜单10'] } } </script> 

你也可以使用Handlebars, Jade, artTemplate各种模板引擎到你的项目中, 当然这些都是需要取决于前端架构师前期的所选择的技术选型. 做为前端架构师, 需要评估HTML产生的过程, 你对内容的顺序, 使用的元素和CSS类名有多大的控制权? 这些元素在将来改动起来会有多大难度? 模板的易用性? 你可以通过系统做出更改, 还是需要手动处理? 通过回答这些问题, 可能会颠覆你自己构建HTML和CSS的方法.

(二) CSS

构建CSS现在有很多成熟的方法, 例如使用新的命名空间, 扩充数据属性或在JavaScript里面定义CSS. 这些方法你可以从BootStrap, ElementUI这类UI框架中找到影子. 下面, 介绍3种比较常用的方法.

1.OOCSS方法(Object-Oriented CSS 面向对象的CSS)

  <div class="toggle simple"><div class="toggle-control open"> <h1 class="toggle-title">标题</h1> </div> <div class="toggle-details open"> 详细内容 </div> </div> 

上面这段代码就展示了如何使用OOCSS方法创建一个可切换的HTML代码, OOCSS有两个主要的原则:

  • 分离结构和外观
  • 分离容器和内容

分离结构和外观
这里的toggle用来控制结构, simple用来控制外观,这就是分离结构和外观的表现. 这样可以实现外观的复用, 例如当前的simple皮肤使用直角, 而complex皮肤可能使用圆角, 还加了阴影.

分离容器和内容
这里使用toggle-title就是分离容器和内容的表现, 无论toggle-title的容器是用的<h1>还是<h2>或者是<div>, 一旦加上了toggle-title这个类名, 那么该容器均已该类名所定义的样式呈现内容.

2.SMACSS方法(Scalable and Modular Architecture for CSS 模块化架构的可扩展的CSS)

<div class="toggle toggle-simple"><div class="toggle-control is-active"> <h2 class="toggle-title">标题2</h2> </div> <div class="toggle-detail is-active"> 详细内容 </div> </div> 

上面的这段代码基本展示了如何使用SMACSS方法,在我个人的理解中, OOCSS更多的其实是提供了一种CSS构建思想, 该思想要求将结构和外观分离, 将容器和内容分离. 但是并没有提供一套完整的CSS构建规范, 而SMACSS是提供了一套样式系统, 该样式系统有5个具体类别:

  • 基础: 如果不添加CSS类名, 标记会以什么外观呈现
  • 布局: 把页面分成一些区域
  • 模块: 设计中的模块化, 可复用的单元
  • 状态: 描述在特定的状态或情况下, 模块或布局的的显示方法
  • 主题: 一个可选的视觉外观层, 可以让你更换不同主题

基础

//base.css
body, form { margin: 0; padding: 0; } a { color: #039; } a:hover { color: #03F; } 

在基础代码中, 应该规定的是页面中的一些通用样式,例如将bodymarginpadding设置为0 , 设置a标签的颜色等. 类似于某些人常用的initial.css文件.

布局

//layout.css
#header, #article, #footer { width: 960px; margin: auto; } #article { border: solid #CCC; border-width: 1px 0 0; } 

这里的布局指的是页面中一些通用的布局组件, 例如头部, 侧边栏, 主体和底部这些. 这些布局组件会在多个页面通用, 所以最好把其放入到一个css文件中. 方便复用. 在SMACSS中, 推荐将布局容器的顶级标签设置为id, 这样确保了每个页面中拥有唯一持有该样式的布局容器, 也方便其css和js选择器的使用. 当然, 你也可以使用一个唯一的类名替代id.

模块

//module.css//module1
.module1 > h2 { padding: 5px; } .module1 span { padding: 5px; } //module2 .module2 > h2 { padding: 10px; } .module2 span { padding: 10px; } 

模块是指页面中可以单独分离并提取出来复用的部分, 例如导航条, 侧边栏, 对话框或一些widget等. 所以, 模块禁止使用id, 而应该采用类名的方式.

状态

<div id="header" class="is-collapsed"> <form> <div class="msg is-error"> There is an error! </div> <label for="searchbox" class="is-hidden">Search</label> <input type="search" id="searchbox"> </form> </div> 

State 负责定义元素不同的状态下,所呈现的样式. 上面的一段代码中,已is-开头的就是表示状态的类名, is-collapsedis-error等类名不会单独使用, 而是和前面的布局模块一起使用. 下面的代码, 就是在tab栏模块和状态一起使用:

//state.css
.tab {background-color: purple; color: white; } .is-tab-active { background-color: white; color: black; } 

主题

// module-name.css
.mod {border: 1px solid; } //theme.css .mod { border-color: blue; } 

这里的主题理解为皮肤更加合适, 已上面的代码为例, 在module-name.css中定义了边框除颜色之外的样式, 在theme.css文件中定义了该边框的颜色, 这样的好处就是, 如果定义其他颜色的类名去覆盖这些有颜色的样式, 那么就可以通过类名去切换皮肤的颜色. 达到更换主题的效果.

更多关于SMACSS的方法, 请参考: https://smacss.com/book

3.BEM方法(Block Element Modifier 块元素修饰符)

<div class="toggle toggle--simple"><div class="toggle__control toggle__control--active"> <h2 class="toggle__title">标题3</h2> </div> <div class="toggle__details toggle__details--active"> ... </div> ... </div> 

BEM是由Yandex提出的给一个CSS命名方法, 该方法要求使用一个CSS类名, 尽可能使用以下三者组成:

  • 块名: 所属组件的名称
  • 元素: 元素在块里面的名称
  • 修饰符: 任何与块或元素相关联的的修饰符

块名
这里的块名很多初学者会以为是inline-block中的块, 其实这里的块名指的是一个独立的模块或组件. 例如一个<header>可以用做一个模块, <header>中的<nav>可以用作一个模块. 模块之间是可以相互嵌套的. 上面的示例代码中 ,toggle就是一个独立的模块

元素
元素是指无法用在其他块名中的部分, 在BEM方法中, 元素跟在块名后面使用__连接, 之所以约定使用双下划线是因为方便在块名中使用单下划线命名. 上面示例代码中的toggle__controltoggle__title就是块名+元素的命名方式.

修饰符
修饰符与SMACSS中的状态类似, 在BEM方法中, 修饰符需要跟在元素后面使用--连接. 有的人会觉得这种写法会使得代码冗余, SMACSS使用is-active同样可以表示同样的作用, 为什么上面的代码要使用toggle__details--active呢? 其实, 如果单独看openis-active这两个名字, 我们并不知道它们的含义是什么, 但是当看到一个toggle__details--active的类名, 我们就知道它是表示: 这个元素的名称是details, 位置在toggle组件里, 状态为active.

(三) JavaScript

1.框架的选择
这里我不想陷入Angular, React, Vue三大框架之争. 我是一个Vue的开发者, 我深知MVVM框架给我们开发者带了极大的便利, 不用再以jQuery不停的操作DOM的形式去开发, 而是只关注数据的改变, 以数据去驱动DOM的改变. 这能够把更多的时间放入到业务逻辑的处理上.

就目前三大框架的生态系统来看, 大部分业务三大框架实现起来其实并没有什么大的差别,框架的选择更多的取决于项目中团队人员的偏好和学习成本. 比如Vue的学习成本就相比于Angular要小太多. 虽然我是一个Vue的开发者, 但我不得不说在React中使用JSX的语法让写代码变得很愉快.

这里我还想说的是: 其实你很可能不需要任何的框架!

有很多成功的网站只不过是采用了一些模板语法, 加上少量手动创建的Sass文件和几十个Javascript函数创建而成. 当项目的规模足够庞大, 需要牺牲代码文件体积大小去换取框架所带来的开发效率的提高时, 再考虑评估引入哪类JS框架和UI框架, 否则不要轻易放弃精简方案.

2.选择一套JavaScript代码规范

每个人写代码的方式是不同的, 有些人可能喜欢用==, 但有的喜欢用===; 有的人可能习惯给每个变量使用var去声明, 但有的喜欢使用一个var加逗号运算符去同时声明多个变量. 这些代码习惯可能并不会对程序运行造成影响. 但是在大型业务中, 面临多个开发者共同开发时, 如果没有一套代码规范, 那么就会出现代码难以维护, 难以阅读的情况. 为了让新加入的团队成员也能够快速熟悉相关的代码, 并且让代码可以维护, 一套Javascript代码规范不论是开发大型项目和小型项目, 都是必须的.

如果公司没有代码定制自己的代码规范, 可以使用大公司所制定的代码规范, 这里向大家推荐以下三个代码规范:

  • Airbnb JavaScript Style Guide

    Airbnb JavaScript Style Guide
    Airbnb JavaScript Style Guide

    Airbnb的Javascript号称是"最合理的编写JavaScript代码的方式", 也是互联网中最流行的JavaScript代码规范, 它在Github上足有6万star, 几乎覆盖了JavaScript的每一项语言特性.

     

  • Google JavaScript Style Guide

    oogle JavaScript Style Guide
    oogle JavaScript Style Guide

    Google的JavaScript代码规范相比于Airbnb代码规范更加全面, 它不仅从代码美感,性能角度和代码特性对编写Js代码进行了规范, 同时也对Js的命名, 导入方式, Js代码文档进行了规范. 在Introduction中, Google团队表明, 在项目中全部使用了Google的Js规范, 才能被叫做Google Style的代码!

     

  • JavaScript Standard Style Guide

    JavaScript Standard Style Guide
    JavaScript Standard Style Guide

    standard JS是一个功能强大的 JavaScript 代码规范, 自带 linter 和自动代码纠正, 无需配置, 自动格式化代码. 可以在编码早期就发现代码中的低级错误. 这个代码规范被很多知名公司所采用, 比如 NPM、GitHub、mongoDB 等.

     

下面截取部分airbnb的ES5规范, 来对比一下使用了规范和未使用规范的区别:

数组
  • 使用直接量创建数组
//bad
var items = new Array() //good var items = []; 
  • 拷贝数组时, 使用slice
var len = items.length;
var itemsCopy = [];
var i;// bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice(); 
  • 使用slice将类数组对象转换成数组
function trigger() { var args = Array.prototype.slice.call(arguments); } 
字符串
  • 使用单引号''包裹字符串
//bad 
var name = "LITANGHUI"//good var name = 'LITANGHUI' 
  • 程序化生成的字符串使用join连接而不是使用连接符。尤其是 IE 下
var items;
var messages;
var length;
var i; messages = [{ state: 'success', message: 'This one worked.' }, { state: 'success', message: 'This one worked as well.' }, { state: 'error', message: 'This one did not work.' }]; length = messages.length; // bad function inbox(messages) { items = '<ul>'; for (i = 0; i < length; i++) { items += '<li>' + messages[i].message + '</li>'; } return items + '</ul>'; } // good function inbox(messages) { items = []; for (i = 0; i < length; i++) { // use direct assignment in this case because we're micro-optimizing. items[i] = '<li>' + messages[i].message + '</li>'; } return '<ul>' + items.join('') + '</ul>'; } 
比较运算符 & 等号
  • 优先使用 ===和 !==而不是 ==和 !=
  • 使用快捷方式
// bad
if (name !== '') {// ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... } 
空白
  • 使用 2 个空格作为缩进
// bad
function () { ∙∙∙∙var name; } // bad function () { ∙var name; } // good function () { ∙∙var name; } 
  • 大括号前放一个空格
// bad
function test(){ console.log('test'); } // good function test() { console.log('test'); } // bad dog.set('attr',{ age: '1 year', breed: 'Bernese Mountain Dog' }); // good dog.set('attr', { age: '1 year', breed: 'Bernese Mountain Dog' }); 
  • 使用空格把运算符隔开
// bad
var x=y+5;// good var x = y + 5; 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/538090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用法向量求点到平面距离_支持向量机(SVM)

最近完成的一个项目用到了SVM&#xff0c;之前也一直有听说支持向量机&#xff0c;知道它是机器学习中一种非常厉害的算法。利用将近一个星期的时间学习了一下支持向量机&#xff0c;把原理推了一遍&#xff0c;感觉支持向量机确实挺厉害的&#xff0c;尤其是核函数变换可以把一…

TortoiseSVN 1.9.5安装 与 Eclipse4.4.2中安装SVN插件 图解详解

原文链接&#xff1a;http://blog.csdn.net/chenchunlin526/article/details/54631458 Eclipse svn 插件官网&#xff1a;http://subclipse.tigris.org/ Eclipse svn 插件更新网站&#xff1a;https://github.com/subclipse/subclipse/wiki -------------------------------…

虚拟服务器关机返回用户信息,在Linux服务器关机前向用户显示一条自定义消息...

在先前的文┞仿中&#xff0c;我们说清楚明了 Linux 中 shutdown、poweroff、halt、reboot 敕令的不合之处&#xff0c;并揭示了在用不合的选项履行这些敕令时它们实际做了什么。# shutdown 13:25本篇将会向你展示如安在体系关机时向所有的体系用户发送一条自定义的消息。建议浏…

eclipse svn不能忽略文件及文件夹,ignore设置无效 ?

SVN这块做得不好&#xff0c;如果之前提交过此文件&#xff0c;就不能设置忽略该文件了。所以第一次提交的时候要搞清楚再提交。 【 亲测&#xff0c;的确如此&#xff0c;用 Windows -> Preferences -> Team -> Ignored Resources 方法不行。 项目右键--team--设置…

Sonatype Nexus 库被删除的恢复方法

原文连接&#xff1a;https://my.oschina.net/u/178116/blog/519840 --------------------有道云笔记保存---------------------------------------------- 今天在整理公司Maven私服的时候&#xff0c;不小心把Release库删掉了。瞬间冒出冷汗来了&#xff01;公司所有的积累都…

maven私有库配置

不同的项目&#xff0c;不同的私有库1、添加仓库Release 发布&#xff1b; 发行仓库snapshot 快照&#xff0c;开发&#xff0c;调试仓库配置完成2、配置权限默认开通的权限&#xff0c;查看权限给刚才建的两个私有库添加权限配置好后3、创建角色&#xff0c;分配权限添加rolei…

asc desc排序_21.数据库排序?左连接 ?右连接?

更多内容来源&#xff1a;http://mp.weixin.qq.com/mp/homepage?__bizMzA5OTQ1ODE1NQ&hid6&sn843337a7d9931839214ec8f861ac2164&scene18#wechat_redirect1、数据库排序语法 select column_name,column_name from table_name order by column_name,column_name as…

京东ajax怎么用,使用Ajax、json实现京东购物车结算界面的数据交互实例

全选商品单价数量小计操作全选删除选中产品总价&#xff1a;&#xffe5;0body,html,ul,li,a{margin:0;padding:0;font-family:"microsoft yahei";list-style:none;text-decoration:none;}.fl{float:left;}.fr{float:right;}.f12{font-size:12px;}.disl{display:inli…

maven私有库搭建

为什么要搭建maven私有库&#xff1f; 有位博主在2008年时这样写道&#xff1a; 如果没有私服&#xff0c;我们所需的所有构件都需要通过maven的中央仓库和第三方的Maven仓库下载到本地&#xff0c;而一个团队中的所有人都重复的从maven仓库下载构件无疑加大了仓库的负载和浪费…

eclipse maven访问maven私有库

1、Windows本地maven下载 https://maven.apache.org/download.cgi 2、maven setting 文件配置 进入maven 目录下 conf。apache-maven-3.2.3\conf 新建.xml 文件&#xff0c;内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?><set…

入门系列之在Ubuntu 16.04使用Buildbot建立持续集成系统

欢迎大家前往腾讯云社区&#xff0c;获取更多腾讯海量技术实践干货哦~ 本文由angel_郁发表于云社区专栏 介绍 Buildbot是一个基于Python的持续集成系统&#xff0c;用于自动化软件构建&#xff0c;测试和发布过程。 在本教程中&#xff0c;我们将演示如何设置持续集成系统以自动…

strapi 开源api 内容管理平台试用

strapi 是一个开源的api && 内容管理平台&#xff0c;功能操作起来还是比较方便简单的。 安装 使用docker && docker-compose 代码clonegit clone https://github.com/strapi/strapi-docker && cd strapi-docker 启动 docker-compose up -d 访问 首次初…

1.android体系结构介绍

一、Android的介绍 android介绍见百度百科&#xff1a;Android的介绍&#xff0c;度娘把Android介绍的这么清楚&#xff0c;如果谷歌是Android的爹&#xff0c;那度娘就是娘了。 二、Android的架构图 android系统主要分四层&#xff1a; 从上致下&#xff1a; 1、应用层 2、…

2.JVM和DVM之间的区别

1、JVM .java----->.class----->.jar 运行在内存的 栈 栈虚拟机 2、DVM .java----->.class------>.dex-----(加上其它资源文件)---->apk 运行在CPU的 寄存器 寄存器虚拟机 ---------------------------------------------------------- 3、DVM与JVM的区…

Node.js模块以及模块加载机制

2019独角兽企业重金招聘Python工程师标准>>> Node.js中的模块 在Node.js中&#xff0c;以模块为单位划分功能&#xff0c;通过一个完整的模块加载机制使得开发人员可以将应用程序划分为多个不同的部分。模块的使用可以提高代码重用率&#xff0c;提高应用程序的开发…

获取数据库名称dbName

2019独角兽企业重金招聘Python工程师标准>>> Autowired DataSource ds; connection ds.getConnection(); tring dbName connection.getCatalog(); connection.close(); 转载于:https://my.oschina.net/u/2351011/blog/1925838

mysql连接idea详细教程_idea配置连接数据库的超详细步骤

学习时&#xff0c;使用IDEA的时候&#xff0c;需要连接Database&#xff0c;连接时遇到了一些小问题&#xff0c;下面记录一下操作流程以及遇到的问题的解决方法。一、 连接操作简介&#xff1a;介绍如何创建连接&#xff0c;具体连接某个数据库的操作流程。1.1 创建连接打开i…

redis单节点安装

1、下载 redis &#xff1a;https://redis.io/ redis 提供的是 源码包&#xff0c;需要编译。 2、Linux下安装gcc 和 tcl tcl介绍 命令&#xff1a;yum install gcc tcl 3、将redis的源码包&#xff0c;放到 /usr/local/src 下 tar -zxvf redis-4.0.6.tar.gz 4、安装redi…

ManicTime软件破解

这款软件用来记录电脑上程序的运行时间。方便天天用电脑的查看&#xff1a;今天我的时间都去哪儿了&#xff1f; 专业版不免费&#xff0c;而且需要 67 美元。 免费版和专业版的区别 破解补丁和官方软件下载&#xff08;截止博文发布&#xff0c;官方最新版本 版本&#xff1…

mysql根据ID的顺序查找_求救:mysql 如何根据给定的 ID顺序查找结果?

各位大神&#xff0c;现在我遇到了一个难题需要你们的帮助。有下面两个表post表&#xff1a;文章表。record表:记录表&#xff0c;用于记录用户阅读顺序。record表 根据用户的阅读文章顺序用一个字段 postid 记录 post 表的主键ID&#xff0c;既 record.postid 的外键为 post.i…