当代前端应该怎么写这个hello world?

javascript admin 1900 0 评论

前言

大概16年的时候我们队react进行了简单的学习:从DOM操作看Vue&React的前端组件化,顺带补齐React的demo,当时我们只是站在框架角度在学习,随着近几年前端的变化,想写个hello world似乎变得复杂起来,我们今天便一起来看看现代化的前端,应该如何做一个页面,今天我们学习react首先说一下React的体系圈

无论Vue还是React整个体系圈十分的完备,就一个中级前端想要提高自己,完全就可以学习其中一个体系,便可以收获很多东西,从而突破自身

从工程化角度来说,前端脚手架,性能优化,构建等等一系列的工作可以使用webpack处理,这里又会涉及到SSR相关工作,稍微深入一点便会踏进node的领域,可以越挖越深

从前端框架角度来说,如何使用React这种框架解决大型项目的目录设计,小项目拆分,代码组织,UI组件,项目与项目之间的影响,路由、数据流向等等问题处理完毕便会进步很大一步

从大前端角度来说,使用React处理Native领域的问题,使用React兼容小程序的问题,一套代码解决多端运行的策略,比如兼容微信小程序,随便某一点都值得我们研究几个月

从规范来说,我们可以看看React如何组织代码的,测试用例怎么写,怎么维护github,怎么做升级,甚至怎么写文档,都是值得学习的

从后期来说,如何在这个体系上做监控、做日志、做预警,如何让业务与框架更好的融合都是需要思考的

react体系是非常完善的,他不只是一个框架,而是一个庞大的技术体系,优秀的解决方案,基于此,我们十分有必要基于React或者Vue中的一个进行深入学习

也正是因为这个庞大的体系,反而导致我们有时只是想写一个hello world,都变得似乎很困难,于是我们今天就先来使用标准的知识写一个demo试试

文章对应代码地址:https://github.com/yexiaochai/react-demo

演示地址:https://yexiaochai.github.io/react-demo/build/index.html

脚手架

现在的框架已经十分完备了,而且把市场教育的很好,一个框架除了输出源码以外,还需要输出对应脚手架,直接引入框架源文件的做法已经不合适了,如果我们开发react项目,便可以直接使用框架脚手架创建项目,就react来说,暂时这个脚手架create-react-app比较常用,他有以下特点:

① 基本配置为你写好了,如果按照规范来可做到零配置

② 继承了React、JSX、ES6、Flow的支持,这个也是类React框架的标准三件套

③ 因为现在进入了前端编译时代,服务器以及热加载必不可少,一个命令便能运行

首先,我们一个命令安装依赖:

然后就可以使用脚手架创建项目了:

直接浏览器打开的方法也不适用了,这里开发环境使用一个node服务器,执行代码运行起来:

系统自动打开一个页面,并且会热更新,看一个项目首先看看其package.json:

所以当我们执行npm run start的时候事实上是执行node_modules/react-script目录下对应脚本,可以看到项目目录本身连webpack的配置文件都没有,所有的配置全部在react-scripts中,如果对工程配置有什么定制化需求,执行

就将node_modules中对应配置拷贝出来了,可随意修改:

也可以安装个服务器,可以直接运行build文件中的代码:

我们的代码开始比较简单,只写一个hello world就行了,所以把多余的目录文件全部删除之,修改下index.js代码:

这个代码不难,我想关键是,这个代码写完了,突然就开服务器了,突然就打包成功了,突然就可以运行了,这个对于一些同学有点玄幻,这里就有必要说一下这里的webpack了

webpack

我们说框架的脚手架,其实说白了就是工程化一块的配置,最初几年的工程化主要集中在压缩和优化、到requireJS时代后工程化变得必不可少,当时主要依赖grunt和gulp这类工具,后续为了把重复的工作杀掉工程化就越走越远了,但是和最初其实变化不大,都是一点一点的将各种优化往上加,加之最近两年typescript一击es6新语法需要编译进行,我们就进入了编译时代

webpack已经进入了4.X时代,一般一个团队会有一个同事(可能是架构师)对webpack特别熟悉,将脚手架进行更改后,就可以很长时间不改一下,这个同事有时候主要就做这么一件事情,所以我们偶尔会称他为webpack配置工程师,虽然是个笑话,从侧门也可以看出,webpack至少不是个很容易学习的东西,造成这个情况的原因还不是其本身有多难,主要是最初文档不行,小伙伴想实现一个功能的时候连去哪里找插件,用什么合适的插件只能一个个的试,所以文档是工程化中很重要的一环

这里再简单介绍下webpack,webpack是现在最常用的JavaScript程序的静态模块打包器(module bundler),他的特点就是以模块(module)为中心,我们只要给一个入口文件,他会根据这个入口文件找到所有的依赖文件,最后捆绑到一起,这里盗个图:

这里几个核心概念是:

① 入口 – 指示webpack应该以哪个模块(一般是个js文件),作为内部依赖图的开始

② 输出 – 告诉将打包后的文件输出到哪里,或者文件名是什么

③ loader – 这个非常关键,这个让webpack能够去处理那些非JavaScript文件,或者是自定义文件,转换为可用的文件,比如将jsx转换为js,将less转换为css

test就是正则标志,标识哪些文件会被处理;use表示用哪个loader

④ 插件(plugins)

插件被用于转换某些类型的模块,适用于的范围更广,包括打包优化、压缩、重新定义环境中的变量等等,这里举一个小例子进行说明,react中的jsx这种事实上是浏览器直接不能识别的,但是我们却可以利用webpack将之进行一次编译:

Hello,Webpack

这里我们来做个小demo介绍webpack的低阶使用,我们先建立一个文件夹webpack-demo,先建立一个文件src/index.html

然后我们建立一个js文件src/index.js以及src/data.js以及style.css

这个时候轮到我们的webpack登场,以及会用到的几个加载器(这里不讲安装过程):

① webpack-cli是命令行工具,有了他我们就需要在他的规则下写配置即可,否则我们要自己在node环境写很多文件操作的代码

② loader结尾的都是文件加载器,读取对应的文件需要对应的加载器,比如你自己定义一个.tpl的文件,如果没有现成的loader,你就只能自己写一个

③ 其中还有个node服务器,方便我们调试

因为我们这里的import是es6语法,浏览器不能识别,所以需要安装babel解析语言:

然后我们在package.json中加入一行代码:

这个时候就可以创建webpack文件了:

然后执行webpack命令便构建好了我们的文件:

可以看到,只要找到我们的入口文件index.js,便能轻易的将所有的模块打包成一个文件,包括样式文件,我们关于webpack的介绍到此为止,更详细的介绍请看这里:https://juejin.im/entry/5b63eb8bf265da0f98317441

我们脚手架中的webpack配置实现相对比较复杂,我们先学会基本使用,后面点再来怎么深入这块,因为现有的配置肯定不能满足我们项目的需求

页面实现

这里为了更多的解决大家工作中会遇到到问题,我们这里实现两个页面:

① 首页,包括城市列表选择页面

② 列表页面,并且会实现滚动刷新等效果

页面大概长这个样子(因为这个页面之前我就实现过,所以样式部分我便直接拿过来使用即可,大家关注逻辑实现即可):

我们这里先捡硬骨头坑,直接就来实现这里的列表页面,这里是之前的页面,大家可以点击对比看看

组件拆分

react两个核心第一是摆脱dom操作,第二是组件化开发,这两点在小型项目中意义都不是十分大,只有经历过多人维护的大项目,其优点才会体现出来,我们这里第一步当然也是拆分页面

这里每一个模块都是一个组件,从通用性来说我们可以将之分为:

① UI组件,与业务无关的组件,只需要填充数据,比如这里的header组件和日历组件以及其中的列表模块也可以分离出一个组件,但看业务耦合大不大

② 页面组件,页面中的元素

工欲善其事必先利其器,所以我们这里先来实现几个组件模块,这里首先是对于新人比较难啃的日历模块,我们代码过程中也会给大家说目录该如何划分

日历组件

日了组件是相对比较复杂的组件了,单单这个组件又可以分为:

① 月组件,处理月部分

② 日部分,处理日期部分

能够将这个组件做好,基本对组件系统会有个初步了解了,我们这里首先来实现日历-日部分,这里我们为项目建立一个src/ui/calendar目录,然后创建我们的文件:

这个时候再执行以下命令便会编译运行:

虽然不知为什么,但是我们的代码运行了,大概就是这么一个情况:),接下来我们开始来完善我们的代码,日历组件,我们外层至少得告诉日历年和月,日历才好做展示,那么这里出现了第一个问题,我们怎么将属性数据传给组件呢?这里我们来简单描述下react中的state与props

state是react中的状态属性,定义一个正确的状态是写组件的第一步,state需要代表组件UI的完整状态集,任何UI的改变都应该从state体现出来,判断组件中一个变量是不是该作为state有以下依据:

① 这个变量是否是从父组件获取,如果是,那么他应该是一个属性

② 这个变量是否在组件的整个生命周期不会变化,如果是,那么他也是个属性

③ 这个变量是否是通过其他状态或者属性计算出来的,如果是,那么他也不是一个状态

④ 状态需要在组件render时候被用到

这里的主要区别是state是可变的,而props是只读的,如果想要改变props,只能通过父组件修改,就本章内容,我们将年月等设置为属性,这里先忽略样式的处理,简单几个代码,轮廓就出来了,这里有以下变化:

① 新增common文件夹,放了工具类函数

② 新增static目录存放css,这里的css我们后续会做特殊处理,这里先不深入

于是,我们目录变成了这样:

我们将calendar代码贴出来看看:

样式基本出来了:

这个时候我们需要将月组件实现了,这里贴出来第一阶段的完整代码:




这段代码的效果是:

基础框架结构出来后,我们就需要一点一点向上面加肉了,首先我们加一个选中日期,需要一点特效,这里稍微改下代码,具体各位去GitHub上面看代码了,这段代码就不贴出来了,因为我们这里是写demo,这个日历组件功能完成60%即可,不会全部完成,这里我们做另一个操作,就是在页面上添加一个上一个月下一个月按钮,并且点击日历时候在控制台将当前日期打印出来即可,这里是效果图:

这个时候我们首先为左右两个按钮添加事件,这里更改下代码变成了这个样子,这里贴出阶段代码,完整代码请大家在git上查看




至此,我们日历一块的基本代码完成,完成度应该有60%,我们继续接下来的组件编写

header组件

日历组件结束后,我们来实现另一个UI类组件-header组件,我们这里实现的header算是比较中规中矩的头部组件,复杂的情况要考虑hybrid情况,那就会很复杂了,话不多说,我们先在ui目录下建立一个header目录,写下最简单的代码后,我们的index:

然后是我们的header组件:

于是header部分的框架就出来了,这个时候我们来将之加强,这里也不弄太强,就将后退的事件加上,以及左边按钮加上对应的按钮和事件,这里改造下index和header代码:

就这样按钮和点击时候的事件回调都做好了,这里图标有点丑这个事情大家就别关注了,注意这里是一种规则,设定了规则后按照规则写代码后续会极大提高工作效率,到此我们header部分的代码就完成了,很是轻松加愉快啊!!!

列表组件

列表组件这里涉及到部分业务代码了,因为存在请求后端数据了,于是我们就比较尴尬了,因为我一点点都不想去为了写一个demo而去写建立数据库或者写代码,于是我们这里使用mock搞定数据部分,工欲善其事必先利其器,我们这里首先将数据部分解决掉(PS:因为原来项目的接口不能访问,所以直接胡乱mock数据,这样也许会造成之前做的日历没有多大的意义,事实上数据应该是用日期参数请求的)

现在想做假数据已经有很多成熟的平台了,比如这个:https://www.easy-mock.com,使用起来非常简单,大家去看看他的教程就行,我们这里直接使用之:

现在访问这个url就能看到我们的列表数据:https://www.easy-mock.com/mock/5c29d45956db174d47ce162a/example_copy/train/list#!method=get

在react中我们使用fetch获取数据,这里直接上代码了:

这样就会将我们的数据打印到控制台,但是实际项目中我们不会这样请求数据,而会对他进行两层封装,第一层封装隐藏fetch,让我们无论是ajax或者fetch都可以,第二层是要给他加上缓存功能比如我们的localstorage,包括一些公告参数处理撒的,所以我们会在我们的目录中新增data目录专门用来处理数据请求部分,甚至我们会为没一个数据请求建立一个“实体”,让各个页面重复调用,我这里偷懒就直接将之前微信小程序的请求模块和换成模块拿过来使用即可:

 

这里data目录是,然后可以看到数据请求成功,并且localstrage中有数据了:

有了数据后,我们来完善我们的列表,因为数据原因,我们这里便不做滚动分页功能了,一般来说列表类组件特点还是比较突出的:需要提供一个数据请求模块以及一个数据处理器,最后加一个模板就可以完成所有功能了,这里还是先来实现列表部分代码,这个列表组件因为涉及的业务比较多而且每个页面的列表变化也比较大,我们暂且将之放到ui目录,后续看看这块怎么处理一下,我们依然先在这里建立list目录:

这样一来,我们轻易的就将页面做出来了:

接下来我们使用组件完成其功能,这里我们将代码做一层分离,将列表组件分成两部分,第一部分是不变放在UI中的部分,另一部分是我们要求传入的模板组件,因为每个页面的列表展示都是不一样的,于是我们先实现外层列表,这里就相当于要传递一个组件给另一个组件使用,我们简单的尝试了下可行性:

证明是可行的,其实React早就知道我们有这种骚操作,所以衍生了高阶组件的概率,这里我们简单介绍下

PS:大家可以看到,我们文中的例子都不是生拉硬套的要应用某个知识点是确实有这种需求

高阶组件-继承的应用

参考:https://github.com/sunyongjian/blog/issues/25

高阶组件只是名字比较高阶罢了,其实跟我们上面代码的例子差不多,每个React组件事实上都是一个js对象,我们可以实例化一下他,完成任何骚操作,但是出于规范化和代码可控(在不非常熟悉底层代码的时候,随意使用骚操作,可能会出莫名其妙的BUG,但是也是因为莫名其妙的BUG会导致你更熟悉框架,BUG带来的框架理解有时候优于机械源码阅读,所以在非核心项目上,我们非常建议你骚操作)

上面的说法有点不好理解,这里换个方式说,所谓高阶组件,就是我们有一个组件,这个时候我们会给他传递各种参数,其中一个参数是另一个React组件,并且我们需要在父组件中使用他:

这个例子依旧不够清晰,我们再举个例子:

这里会输出(这里说爸爸可能不太合适,这里应该是个组合关系):

这里核心概念还是这里使用了一个继承解决这个问题:

所以,高阶组件其实并不神秘,就是实现了一个用于继承的组件,然后在子组件里面做业务性操作,在之前属于非常常规的操作,这里推荐看一点老一点的东西,脱离框架的东西,类比帮助大家了解高阶组件:https://www.cnblogs.com/yexiaochai/p/3888373.html,于是这里我们稍微改造下我们的list组件的框架结构:

PS:这里一定要注意,一个项目或者几个项目中,列表的大体HTML结构一定是非常一致的,这里是个规则约定,规则先与代码,先于框架

由此,基本框架就出来了:

我们这里继续完善这个组件即可,这里具体代码各位github上看吧:https://github.com/yexiaochai/react-demo

PS:事实上,我们index.js里面代码已经很多了,应该分离开,但是我们代码已经接近尾声就懒得分离了,大家实际工作中一定要分离

我们代码稍作改造后就变成了这个样子(由于只是demo,对于一些需要计算展示比如筛选硬座票数等未做实现):

至此,我们的demo就结束了,如果有必要可以添加各种筛选条件,比如这里的排序:

比如这里的筛选:

但是我们这里由于是简单的demo加之本篇博客篇幅已经很长了,我们这里就不做实现了,反正也是操作数据,就此,我们业务部分代码结束了,接下来我们来做一点工程化的操作

组件样式问题

可以看到,之前我们的组件样式,全部被我们柔和到了global.css或者index.css中了,对于有些工厂作业做的很好的公司,会具体分出重构工程师(写css的)和程序工程师(写js的)两个岗位,一般是重构同事将css直接交给js同事,这样做起来效率会很高,所以多数情况下,我们全局会有一个样式文件,业务页面会有一个样式文件,这其实没什么大问题,可能出现的问题请大家阅读下这篇文章:【前端优化之拆分CSS】前端三剑客的分分合合,这里其实已经涉及到了一个工作习惯他要求我们做页面的时候就分成模块,做模块的时候要考虑模块的css,这样做也会有一个弊端就是全局性的东西就比较难过了,所以一个大项目的样式相关工作最好由一个资深一点的同事设计规则和公共的点,其次不然很容易各自为战,我们这里完成一个简单的工作,将列表部分的代码从global中分离出来,我们先找到对应的样式代码:

新建一个style.css暂且放到ui/list目录中,其实这个list的样式跟业务代码更有关系,放里面不合适,但是我们这里做demo就无所谓了,这里分离出来后稍作改造即可:

这里未做高阶使用,关于高阶的用法,我们后续有机会再介绍,接下来就是部署以及工程化相关工作了,考虑篇幅,我们后续再继续

结语

本文代码地址:https://github.com/yexiaochai/react-demo

演示地址:https://yexiaochai.github.io/react-demo/build/index.html

可以看到,从组件化一块的设计,React是做的十分好的,我们没花什么时间就把一个简单的页面搭建了出来,实际项目过程中正确的使用React会有很高的效率;另一方面,webpack一块的配置,create-react-app已经完全帮我们做完了,我们只需要按照他的规则来即可,这个黑匣子里面的东西又非常多,我们后续根据实际的项目再深入了解吧,一时之间也说不完,后续我们继续研究如何使用这套代码兼容小程序开发,以及一些工程化问题

转载请注明: 飞嗨_分享互联网 » 当代前端应该怎么写这个hello world?

赞 (0) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽

高效,专业,符合SEO

联系我们