2018-2020
面向对象编程
封装
function Cat (name, color) {
this.name = name;
this.color = color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function () { console.log("吃老鼠") };
// 生成实例
var cat1 = new Cat("大毛", "黄色")
构造函数的继承
function Animal() {
this.species = "猫科动物";
}
- 构造函数绑定
function Cat(name, color) {
Animal.apply(this, arguments);
this.name = name;
this.color = color;
}
// ...
- prototype模式
// ...
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat("大毛", "黄色");
// ...
第一行将Cat的prototype对象指向一个新Animal实例 任何一个prototype对象都有一个constructor属性指向它的构造函数。原先指向Cat,加了第一行后,指向了Animal 每个实例也有constructor属性,之后也指向了Animal
Cat.prototype.constructor == Animal; // true
cat1.constructor == Cat.prototype.constructor; // true
cat1.constructor == Animal; // true
这显然会导致继承链的紊乱,所以要加上第二行,手动纠正,将他指向Cat
- 直接继承
- 利用空对象继承 将Animal改写,然后建立一个空对象
function Animal () {};
Animal.prototype.species = "猫科动物";
var F = function () {};
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
可以封装一下
function extend (Child, Parent) {
var F = function () {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Cat;
Child.uber = Parent.prototype; // 向上一层的意思,可以直接调用父对象。备用性质
}
extend(Cat, Animal);
- 拷贝继承
非构造函数的继承
- Object方法
var Chinese = {
nation: '中国';
}
var Doctor = {
career = "医生";
}
建立一个Object函数
function object (o) {
function F () {};
F.prototype = o;
return new F();
}
var Doctor = object(Chinese);
// 先继承,然后加上属性
Doctor.career = "医生";
页面跳转不记录历史
var urlReplace = function (element) {
if (!element) {
return;
}
var href = element.href;
if (href && /^#|javasc/.test(href) === false) {
if (history.replaceState) {
history.replaceState(null, document.title, href.split('#')[0] + '#');
location.replace('');
} else {
location.replace(href);
}
}
}
$(".link").click(function () {
urlReplace(this);
})
[].forEach.call
方法
可以用于遍历document.querySelectorAll()的NodeList.
实际相当于Array.prototype.forEach.call(...)
[1, 2, 3].forEach.call(["a", "b", "c"], function (item, i, arr) {
console.log(i + ":" + item);
})
// 0:"a"
// 1:"b"
// 2:"c"
关于闭包的概念
变量的作用域
全局变量和局部变量
函数内部可以直接读取全局变量
函数外部无法读取函数内的局部变量
闭包
能够读取其他函数内部变量的函数。
"定义在一个函数内部的函数"
将函数内部和函数外部连接起来的一座桥梁
function f1 () {
var n=999;
function f2(){
return n;
}
return f2;
}
var result = f1();
result(); // 999
// f2就是一个闭包
用途:1、可以读取函数内部的变量 ;2、让这些变量的值始终保持在内存中 ;
function f1 (asd) {
var n = 999;
nAdd = function () {
n += 1
}
function f2 () {
console.log(n);
}
return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000
跨域
JSONP
只能使用GET请求,并要求返回javascript。 因为浏览器允许跨域引用js资源
let script = document.createElement('script)
script.src = 'http://..../login?=username=simon&callback=callback'
document.body.appendChild(script)
function callback (res) {
console.log(res)
}
CORS
浏览器需要支持HTML5 当本域向外域发起请求后,浏览器先检测外域的
Access-Control-Allow-Origin
是否包含本域
Nginx 反向代理
nodejs 中间件代理
可参考 https://segmentfault.com/a/1190000011145364
框架
按照情况选择框架
组件
组件树 组件可以是一个函数
- 纯展型组件
- 接入型组件 container
- 交互型组件 各类加强版的表单组件,强调复用
- 功能型组件
<router-view>
<transition>
作为一种扩展,抽象机制
组件状态(state) jsx v.s. 模板
- JSX 适合多逻辑场景
- Javascript Templating 适合少逻辑场景 colocation
- 该放一起的放一起 Separation of Concerns
- 关注点分离
变化侦测和渲染机制
Declarative Programming 声明式编程
描述数据跟dom的关系
Imperative Programming 命令式编程
就是干,jquery式的,拿到dom下命令。不易维护。变成意大利面条式编程
view = render(state)
通过state数据早出view(DOM)Virtual DOM
已经有很多简单的virtual dom库
通过暴力的遍历比对,来判断哪个数据变了
状态管理
- Flux、Redux、MobX、Vuex; Rx.js
本质是 从原事件,映射到状态的迁移,映射到状态的改变,然后再映射到UI的变化。
Paradigm 范式,思维方式
cycle.js 全都是流
Elm
路由
组件路由解耦。本质上是把url映射到组件树结构的过程
hash模式,history模式,兼容
重定向,懒加载
跳转需要钩子,取消加载使跳转无效
原生app的路由,类似于3D卡片叠加的。上面的卡片关闭后,浏览看下一张卡片
css方案
- 跟js完全解耦,靠预处理器和比如BEM这样的规范来保持可维护性,偏传统
- CSS Modeules,通过编译来避免css类名的全局冲突
- CSS-in-JS方案,比较激进
- Vue的单文件组件css,或者Angular的组件css(写在装饰器里)
- 传统css的一些问题
- 作用域
- Critical css 直出,(应该按需加载)
- Atomic css 原子类css。多个class,一个基本class,再各个不同的class
- 分发复用 放包里面
- 跨平台复用 变成js,然后动态style绑定
构建工具
- 解决的问题
- 任务的自动化
- 开发体验和效率(新语言功能,语法糖,hot reload)
- 部署相关的需求
- 编译时优化
- PostHTML
- PostCSS
- Babel
- AST
- gulp,grunt等用的少了
- wabpack
-关于部署 张云龙,讲关于部署
服务端数据通信
- REST,围绕资源
- Rx.js很适合处理事件
- fetch
- ssr
跨平台渲染
新规范
技术方案都是先有问题,再有思路,同时伴随着取舍。
调试技巧
console 调试
console.table
查看复杂对象
console.table([{a: 1, b:2}, {a: 3, b:4}])
console.time
记录运行时间
console.time('Time1');
console.timeEnd('Time1');
console.trace
获取函数的堆栈情况
console.trace()
console.todo
个性化console.log()
信息
console.todo = function(msg) {
console.log('%c%s%s%s', 'color: yellow; background-color: black;', '–', msg, '–');
};
console.important = function(msg) {
console.log('%c%s%s%s', 'color: brown; font-weight: bold; text-decoration: underline;', '–', msg, '–');
};
console.todo("This is something that' s need to be fixed");
console.important('This is an important message');
将minify的代码还原
在浏览器下,点击{}来结构化代码
查看某个函数调用和其参数值
使用monitor函数可以获取到函数运行时传入的参数值。但是,有一个不足在于并没有指明该函数的形参个数
监控节点元素变化并中断
在浏览器节点上右键,Break on , 然后选定要监控的变化类型:Subtree Modifications, Attributes Modifications, Node Removal
概要
面向对象编程(OOP)
原型,继承
函数式编程(FP)
- 纯功能
- 避免副作用
- 简单功能组成
类继承 和 原型继承 之间的区别
- 类继承 : 创建紧密耦合,或层次分类
- 原型继承:连续继承,原型委派,功能继承,对象组合
原型继承比类继承更简单灵活
函数式编程 与 面向对象编程 的优缺点
OOP优点: 容易理解,易于解释方法调用的含义,命令式的
OOP缺点: 对象和行为通常在同一个实体上被粘合。实体可能被任意数量的非确定性顺序的函数随机访问
FP优点: 避免任何共享的状态或副作用。 功能倾向于从根本简化并且容易重组复用
FP缺点: 过度使用可读性降低 简洁,但是不具体
双向数据绑定 和 单项数据流 的不同
双向数据绑定 以为这UI字段被动态的绑定到数据模型上,UI改变,数据改变,反之也是 会导致难以遵循和理解的副作用
数据流 数据总是单一方向流动,他是确定性的
什么是异步编程,为什么很重要
同步意味着禁止条件和函数调用,代码从上到下依次执行,阻塞长时间任务
异步意味着引擎在事件循环中运行。当需要阻塞操作时,请求被启动,并且代码保持运行而不阻塞。当响应准备就绪,就会触发中断,然后运行事件处理诚信,控制流将继续。 这样一个单线程可以处理许多并发操作
非常适合用户界面代码,有利于服务器的性能
浏览器重排(reflow)重绘(repaint)
网页生成过程
- HTML 被 HTML解析器解析成DOM树
- css 被 css解析器解析成CSSDOM树
- 结合DOM树和CSSDOM树,生成一个渲染树(Render tree)
- 生成布局(flow)
- 将布局绘制(paint)
重排
重新生成布局,重新排列元素
重绘
某些元素的外观被改变
webpack http-proxy 504
修改匹配的路径后面加 /**
proxy: {
'/api/**': {
// ...
}
}
浏览器往返缓存
参考 -> 浏览器往返缓存(Back/Forward cache)问题的分析与解决
// disable bfcache
try {
var bfWorker = new Worker(window.URL.createObjectURL(new Blob(['1'])));
window.addEventListener('unload', function () {
// 这里绑个事件,构造一个闭包,以免 worker 被垃圾回收导致逻辑失效
bfWorker.terminate();
});
}
catch (e) {
// if you want to do something here.
}
开发心得
更新于:2020-10-22
开发移动端时,最好把状态都控制在 strore 里,你永远不知道什么时候这个组件要共享/被其他组件更新数据
组件,或者页面中的单独的小子组件,可以新开一个当前组件/页面的文件夹,放在里面,你永远不知道什么时候复杂度就上来了
- Test.jsx
转变成
- Test
- index.jsx
- TestAC.jsx
- TestBC.jsx