2020年,我们该如何学习 WEB 前端开发?
先通过 w3cschool 等免费学习资源把 HTML、CSS 和 JavaScript 的基本操作学会了
写一个简单的表白页面送给你的女/男朋友,展示一下自己努力的成果,如果没有就当我没说
选择一个可以覆盖多种场景、可以随自己意愿调整难度的项目尝试实现,如博客系统、记账本、Markdown 编辑器等
从 React 和 Vue 这两个框架中选择一个进行学习
学习 Redux、Vuex 或者 MobX 等状态管理工具,并将他们使用到前面的项目中
思考状态管理工具为你的项目带来了什么好处
学习 TypeScript,对前面的项目进行重写,注重对数据结构和类型的控制
学习 Node.js,试着配合数据库实现一个比博客系统更为复杂的 CMS(内容管理系统),如 图书馆管理系统、仓库管理系统
思考在前面使用框架开发的项目中,有哪些代码是重复冗余的,有哪些逻辑是可以在多个组件之间共用的
学习利用 ES2015 或更新的 JavaScript 标准,逐步替换使用框架所编写的代码
思考如何使用纯 JavaScript 对业务组件中的非渲染、非 DOM 相关代码进行抽象
引入单元测试工具,对纯逻辑代码进行测试,争取覆盖率达到 80% 以上
思考不同的代码哲学(OO、FP 等)、不同的代码结构(MVC、MVVM 等)的区别
思考不同的框架之间设计的初衷,思考不同的编程语言中对同一类问题不同解法的区别
我的从 0 开始
第一次知道了可以通过服务器传递 JSON 格式的纯数据,然后前端通过 JavaScript 对数据进行解析,并且结合前端的模板引擎渲染成完整的 HTML;
从这里又可以学习到如何通过 URL 中的 path、query、hash 以及 POST 和 PUT 请求正文等信息向服务器传递信息,服务器通过这些信息动态地对各种数据进行处理并返回结果;
SPA(Single Page Application)开发习惯初见雏形;
接触 Node.js
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
$ ./configure
$ make
$ make install
框架时代
科技的终极目标,就是让人民感觉不到科技。
同样都是目前最流行的框架之一,而且可以预见未来 3~5 年内都是能满足找工作的需求的;
React:引入函数式编程(Functional Programming)的概念,使得写代码的思路更加严谨,更具有可维护性和逻辑可导性;
Vue:将 MVVM 模式变得非常简单易于入手,把 Progressive JavaScript Framework 的定位实践得非常到位。且如今 Vue 3.0 的 Composition API 更是在某种程度上将 Hooks 的玩法实现得比 React Hooks 更优;
工程之路
▐ 工程化协作
版本控制
Git:GitHub、GitLab、Coding……
SVN:BitBucket、Google Code……
代码样式检查工具 JavaScript/TypeScript:ESLint
测试工具
单元测试:Karma、Jest、Mocha……
持续集成:CI
……
▐ 工程化开发工具
依赖包管理工具:npm、yarn
打包工具:webpack、rollup
脚手架工具:create-react-app……
▐ 工程化开发语言
团队之间因为没有良好的技术文档沉淀,信息不对等的情况直接导致代码在没有良好的单元测试时出现逻辑冲突;
第三方依赖库的 API 在设计上大量使用了 JavaScript 松散的特性,导致使用方在引用时频繁出现“迷惑”的状态;
当需要使用 JavaScript 与其他语言(特别是强类型语言)进行交互时,JS 过于松散的习惯会让对接方感到非常迷惑,对于双方的实际接入成本会比前期预估的大得多;
Java 系:Scala.js、ClojureScript
Go 系:GopherJS
Microsoft:TypeScript
Facebook:Flow、Reason
强类型的引入能让我们在写代码的时候从值优先的思维转变成类型优先;
强类型的引入能帮助开发工具(IDE 等)更好地为开发者提供便利性能力,如智能补全、类型检测、编译时检查等等;
TypeScript 可以让 JavaScript 更好地与其他语言进行交互,甚至转换为其他语言;
▐ 工程化通用组件
React:Ant Design、Fusion Design
Vue:Element UI、iView、Ant Design of Vue
逻辑抽象能力
代码逻辑过于冗余;
一旦通用判断逻辑出现变动,需要每一个都进行手动维护;
没有良好的可维护性;
export default {
beastBuff: (state) => {
let arr = [];
if (state.raceCount[0]['beast'] == 2 || state.raceCount[0]['beast'] == 3) {
console.log(`you got 2 beast`)
arr.push(state.racebuffdata[8])
} else if (state.raceCount[0]['beast'] == 4 || state.raceCount[0]['beast'] == 5) {
console.log(`you got 4 beast`)
arr.pop()
arr.push(state.racebuffdata[9])
} else if (state.raceCount[0]['beast'] == 6) {
console.log(`you got 6 beast`)
arr.pop()
arr.push(state.racebuffdata[10])
} else if (state.raceCount[0]['beast'] < 2 && arr.length == 1) {
arr.pop()
}
return arr;
},
caveclanBuff: (state) => {
let arr = [];
if (state.raceCount[1]['caveclan'] == 2 || state.raceCount[1]['caveclan'] == 3) {
console.log(`you got 2 caveclan`)
arr.push(state.racebuffdata[11])
} else if (state.raceCount[1]['caveclan'] == 4) {
console.log(`you got 4 caveclan`)
arr.pop()
arr.push(state.racebuffdata[12])
} else if (state.raceCount[1]['caveclan'] < 2 && arr.length == 1) {
arr.pop()
}
return arr;
},
demonBuff: (state) => {
let arr = [];
if (state.raceCount[2]['demon'] == 1) {
console.log(`you got 1 demon`)
arr.push(state.racebuffdata[5])
} else if (state.raceCount[2]['demon'] < 1 && arr.length == 1) {
arr.pop()
}
return arr;
}
// ...
}
const beastConfig = [
[2, [2, 3], 8],
[4, [4, 5], 9],
[6, [6], 10],
[2]
]
const generateBuff = (rate, configArr) => {
return state => {
const arr = []
for (const [ output, conditions, index ] of configArr) {
if (conditions && index) {
// Buff calculating
const isHit = conditions.some(condition => state.raceCount[0][race] == condition)
if (isHit) {
console.log(`you got ${output} ${race}`)
arr.pop()
arr.push(state.racebuffdata[index])
break
}
} else if (state.raceCount[0][race] < output && arr.length === 1) {
// Last condition
arr.pop()
}
}
return arr
}
}
export default {
beastBuff: generateBuff('beast', [
[2, [2, 3], 8],
[4, [4, 5], 9],
[6, [6], 10],
[2]
]),
caveclanBuff: generateBuff('caveclan', [
[2, [2, 3], 11],
[4, [4], 12],
[2]
]),
// ...
}
更高层次的思考能力
EOF
凡是能用 JavaScript 重写的,终将会使用 JavaScript 重写