从FE视角看大前端

从FE视角看大前端

本文的目标阅读群体是对前端FE感兴趣的Native开发同学, 聚焦在PC和H5浏览器层面, 没怎么涉及Node.js,Electron, 小程序等领域.

试图对前端开发有全景方式的了解, 以及引发大家的兴趣, 有些三端的开发或者语言层面的纵向对比可能并不严谨, 不过这并不妨碍你的理解.

文末对ReactNative做了简单的指引. Enjoy it.

0. 三端对比



如果说iOS是个海贼中的罗宾的话, 不少的开发者通过逆向和越狱等手段想一探女神的真面目.



Android就好比佐罗, 三刀流打通了从系统内核,虚拟机到Framework的三层架构.



前端可以比作乔巴, 往前一步就是萌萌可爱的小鹿制作炫酷的交互, 往后一步也可以化生壮汉扛起后端服务,

0.1 本次分享的目的


  • 但你可能学到很多梗和坑.
  • 能学到一些名词/黑话, 以及使用它们的场景
  • 能了解到前端开发的整个大盘, 并对很多东西产生兴趣

1. 开发工具介绍

作为都是OOP面向职位编程的工程师. 那吃饭的家伙事就很重要. 这个在前端届可以选择的就很多.

当红IDE:

  • vscode, 充分利用V8和MS多年IDE经验,为JS量身打造.
  • webstrom: 最规范的前端开发标准. 体验完备

开发中的黑科技:

  • HMR: 所见即所得, 局部渲染动画, 表单调试简直神器
  • Debug in Chrome: 调试CSS和单步调试JS, chrome dev插件

语言进化:

  • ES: ES6, ES7, ESNext
  • 强类型: TypeScript 3.0
表单编辑时 HMR 局部刷新 https://www.zhihu.com/video/1028597275878166528

2. 开发策略和步骤 - 领导交给活之后如何设计项目

这个一般都是先找个项目改一改, 当你做过几个之后才会想搞个seed之类的. 毕竟量身定做的鞋子才合脚, 而且你可以还要穿着它来跑.

这年头各大框架还都退出了自己的命令行工具来辅助生成Seed, 可见前端开发的dev Firendly. 例如 create-react-app,vue-cli,angular-cli

帮你一键 init, start, test, then build

另外还有很多开箱即用的脚手架包.集成了更多的功能, 我们俗称seed.

seed可以让你开箱即用. 有的甚至还有图形界面.


create-react-app 截屏动画

https://camo.githubusercontent.com/29765c4a32f03bd01d44edef1cd674225e3c906b/68747470733a2f2f63646e2e7261776769742e636f6d2f66616365626f6f6b2f6372656174652d72656163742d6170702f323762343261632f73637265656e636173742e737667camo.githubusercontent.com


Live demo

文件目录结构

my-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
├── public
│   ├── favicon.ico
│   ├── index.html
│   └── manifest.json
└── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    └── s

seed 无外乎也就这么几种东西的组合, 举例如下

  • React-redux-router
  • react-mobx-react-router4-boilerplate
  • typescript-react-mobx-boilerplate
  • webpack2-typescript-react-router-mobx
  • react-mobx-typescript-boilerplate
  • react-mobx-ts-antd
  • react-redux-webpack-ES6-antd

无外乎组件库,路由,语言,数据模型的组合

2.1 组件库

这块有非常多的选择, 但其实好用的并不多. 有大厂出品的, 也有内部定制化非常高的. Antd, MRC.

优秀的组价库有几个特点 非常多的star, 非常多的closed issues 经常的更新, 并在大版本内保持向下兼容性 合理的属性设置, 以及扩展进行修改 优秀的文档, 以及可以在线修改的样例

组件库还可以进化到组件服务化(自定义一些UI活UE的参数), 或者和设计和产品一起推进产品原型规范化

2.2 路由

  • 规则, 下沉, 匹配优先级
  • 进入和离开的Hook, 权限判断
  • history pool
  • 动态注入路由, 按需加载
React.render((
  <Router>
    <Route path="/" component={App}>
      <Route path="about" component={About} />
      <Route path="inbox" component={Inbox} />
    </Route>
  </Router>
), document.body)

2.4 网络

  • 后 Ajax时代, 从原生的XHR到jquery ajax 它是对原生XHR的封装,还支持JSONP
  • fetch/axio 常用网络库 都可以在Node端使用
  • 受限 - 受到浏览器的很大限制, 跨域, cookie设置等
  • 安全 - XSS/CSP,授信iframe 前端安全
  • 一些写法上的注意, 以及重写js的方法,因为都是在客户端注入执行.
axios({
    method: 'post',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

2.5 数据模型

  • 双向绑定 V.S. 单向数据流 MVVM - FRP
  • pubsub/EventBus, MVC, Singleton, Delegate 都有具体实现



实现双向绑定Proxy比 Object.defineProperty优劣如何?

2.6 H5持久化

浏览器持久化方案对比


3. 在知道了社区和浏览器(大厂)为我们准备了什么, 接下来我们聊一下吃饭的这门语言

You-Dont-Know-JS 系列


  • 入门与进阶
  • 作用域与闭包
  • this与对象原型
  • 类型与文法
  • 异步与性能
  • ES6与未来

3.1 需要先明确一下前端的运行环境. 移动端的web浏览器和PC浏览器

先讲讲宿主环境, webview 分几个大的模块




移动端的浏览器整体结构没有变化. 不过各种解释引擎可能会对移动端做优化.



参考链接:

对比各种浏览器的JS引擎

  • Mozilla: Spidermonkey
  • Chrome: V8
  • Safari: JavaScriptCore
  • Edge: Chakra
  • Node.js: V8 //Node.js不是浏览器是运行时

3.2 数据和运行时

iOS: - 类/属性操作 runtime - 运行时 runloop

JS: - 类/属性操作 Object.defineProperty() setter/getter - 运行时 eventLoop机制 事件和回调机制



var obj = {}; // 创建一个新对象
  // 为新对象添加属性及其属性描述符(数据描述符)
  Object.defineProperty(obj, 'prop', {
    value: 10,
    writable : true,
    enumerable : true,
    configurable : true
  });
  // 此时对象obj拥有了属性prop,值为10,且可修改
  console.log(obj.prop); // 10
  obj.prop = 20;
  console.log(obj.prop); // 20

Android: - runtime: ART - runloop: Looper

3.3 用户交互

都是有冒泡机制, 可交互的view都有简单的click事件, 然后可以自己定义复杂的用户交互.

  • JS: DOMEvent / TouchEvent 事件冒泡 /阻止冒泡,取消默认 (截图)
  • OC: UIResponder / UITouch.
  • Android: EventProcessing / TouchEvent

4. 如果我们再往深入里走一步就来到的语言层面

Let's dive deeper

4.1 原型链

// Letter 是个 Function
function Letter(number) {
  this.number = number;
}

// Letter.prototype 是个 Object
Letter.prototype.getNumber = function() {
  return this.number;
};

let a = new Letter(1);
let b = new Letter(2);
// ...
let z = new Letter(26);

console.log(
  a.getNumber(), // 1
  b.getNumber(), // 2
  z.getNumber(), // 26
);
/* 
1).首先会在a内部属性中找一遍;
2).接着会在a.__proto__(是Letter.prototype)中找一遍
3).如果Letter.prototype中还是没有,此时程序不会灰心,它会继续在Letter.prototype的__proto__中(可能是Object.prototype)中寻找...直至Object的原型对象 null 未知
*/



4.2 样式布局 Flexbox

4.3 语法

4.3.1 数据类型: 7种基本数据类型

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Symbol (ECMAScript 6 新定义)
  • Object

Object 衍生出6种引用类型 - Object 类型 - Array 类型 - Date 类型 - RegExp 类型 - Function 类型 - Array 类型

检测类型

  • typeof: 检测一个变量是不是最基本的数据类型
  • instanceof: 判断一个引用类型的变量具体是不是某种类型的对象.用来判断某个构造函数的 prototype 属性所指向的对象是否存在于另外一个要检测对象的原型链上
// typeof

var a;
typeof a;    // undefined

a = null;
typeof a;    // object

a = true;
typeof a;    // boolean

a = 666;
typeof a;    // number 

a = "hello";
typeof a;    // string

a = Symbol();
typeof a;    // symbol

a = function(){}
typeof a;    // function

a = [];
typeof a;    // object
a = {};
typeof a;    // object
a = /aaa/g;
typeof a;    // object   

// instanceof

({}) instanceof Object              // true
([]) instanceof Array               // true
(/aa/g) instanceof RegExp           // true
(function(){}) instanceof Function  // true

Live demo

4.3.2 lamada

  • JS: 匿名函数
  • OC: block
  • Android: java8 匿名函数

4.3.3 接口 Interface

interface Shape {
    color: string;
}

interface PenStroke {
    penWidth: number;
}

interface Square extends Shape, PenStroke {
    sideLength: number;
}

let square = <Square>{};
square.color = "blue";
square.sideLength = 10;
square.penWidth = 5.0;
  • TS: Interface
  • OC: protocol
  • Android: Interface

4.3.4 变量作用域

ES6之后 有3种修饰作用域的标识符. let/var/const JS中的 this 是运行时决定的, 最终指向的是调用它的对象.并不会向上遍历.

下面这3个都和this有关, thisArg就是this

function.apply(thisArg, [argsArray]) function.call(thisArg, arg1, arg2, ...) function.bind(thisArg[, arg1[, arg2[, ...]]])

// 对象方式实现
var o = {
    user: "追梦子",
    fn:function(){
        console.log(this.user);  //追梦子
    }
}
o.fn();

// 构造函数式实现

function Fn(){
    this.user = "追梦子";
}
var a = new Fn();
console.log(a.user); //追梦子
  • JS: let/var/const 块级作用域, this
  • OC: @public,@protected,@private, self
  • Android: Java变量作用域

5.RN开发的丝滑体验

5.1 debug 举例

Live demo

  • jsmap
  • HMR
  • js call stack

5.2 热修复-H5般的发版体验

  • 动态发布js文件.
  • 结合code-splitting, 替换局部的JS文件

5.3 单元测试/UI测试框架

  • jest: screenshot test
  • detox: UI Test

6. 总结

JS已经不是当年的JS了. 语言进化, 开发体验提升, 编程范式也非常灵活. 然后依靠Lint和测试,覆盖度检查来保证工程质量. 然后借助各种Bridge,跑在各种端和硬件上.


文章最后向 nwind 的一篇雄文 聊聊移动端跨平台开发的各种技术 - FEX 致敬

文章被以下专栏收录