组件化与React
问题
- 组件化的理解
- JSX的本质
- JSX与vdom的关系
- setState的过程
- React与Vue的认识
知识点
组件化
组件的封装
视图
数据
变化逻辑(数据驱动视图变化)
组件的复用
props传递
复用
I was never there.
MVVM-Model View ViewModel
三者之间的联系,以及对应的代码
ViewModel的理解,联系View与Model

vue如何监听到data的每个属性变化
Vue实现主要依赖于Object.defineProperty
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>Object.defineProperty test</p>
<p>响应式</p>
<script type="text/javascript">
var obj = {
name: 'zhangsan',
age: 25
}
console.log(obj)
var obj = {}
var _name = 'shangsan'
Object.defineProperty(obj, 'name', {
get: function () {
console.log('get', _name) // 监听
return _name
},
set: function (newVal) {
console.log('set', newVal) // 监听
_name = newVal
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>Object.defineProperty test</p>
<p>模拟</p>
<script type="text/javascript">
////Vue
// var vm = new Vue({
// el: '#app',
// data: {
// name: 'zhangsan',
// age: 20
// }
// })
//模拟Vue监听name和age
var vm = {}
var data = {
name: 'zhangsan',
age: 20
}
var key, value
for (key in data) {
//命中闭包 新建一个函数 保证key的独立的作用域
(function (key) {
Object.defineProperty(vm, key, {
get: function () {
console.log('get', data[key]) // 监听
return data[key]
},
set: function (newVal) {
console.log('set', newVal) // 监听
data[key] = newVal
}
})
})(key)
}
</script>
</body>
</html>
vue的模板如何被解析,指令如何处理
本质:字符串
有逻辑 v-if v-for
与html格式很像,但是有很大区别/Vue动态 html静态
最终转换为html显示
模板最终转换为JS代码:
有逻辑,必须用JS实现(图灵完备)
转换为html渲染页面,必须用JS实现
模板最后转换成一个JS函数(render函数)
模板字符串——>变成成js渲染函数——>渲染成HTML
vue的模板如何被渲染成html,以及渲染过程
todolist.html
单线程概念,与异步的关系
event-loop的概念
Promise的基本原理与使用
async/await(与Promise的区别与联系 ES7)
总结当前JS解决异步的方案
只有一个线程,同一时间只能做一件事
避免DOM渲染的冲突
JS可以修改DOM解构
JS执行的时候,浏览器DOM渲染会暂停
两段JS也不能同时执行
webworker支持多线程,但是不能访问DOM
异步
问题
没有按照书写顺序执行,可读性差
callback不容易模块化
同步会阻塞代码运行,异步不会
setTimeout
for(var i = 0; i< 5;i++){
setTimeout((function(i){
console.log(i)
})(i), i*1000);
}
// 0 1 2 3 4
(需要等待的时候)
定时任务 setTimeout,setInterval
绑定事件 addEventListener(click等等)
网络请求 ajax和img动态加载
事件轮询,JS实现异步的具体解决方案
过程
同步代码,直接执行
异步函数先放在异步队列中
同步函数执行完毕后,轮询执行异步队列的函数
setTimeout(function() {
console.log(100)
}) //异步队列
console.log(200) //主进程
setTimeout(function() {
console.log(1)
}, 100) //异步队列 100ms后放入
setTimeout(function() {
console.log(2)
}) //异步队列 立刻被放入
console.log(3) //主进程
$.ajax({
url: './data.json',
success: function () {
console.log('a') //ajax加载完成时放入,时间不可确定
}
})
setTimeout(function () {
console.log('b')
}, 100) //100ms 后放入
setTimeout(function () {
console.log('c') //立即放入
})
console.log('d')
//d c a b or d c b a
ES6模块化如何使用,开发环境如何打包
Class和普通构造函数的区别
Promise的基本使用和原理
总结ES6的常用功能
default
node
npm init
npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest //安装babel相关依赖
.babelrc //创建.babelrc文件
{
"presets": ["es2015", "latest"],
"plugins": []
}
npm install -g babel-cli //win管理员模式
babel --version //查看babel版本
./src/index.js //创建文件
babel ./src/index.js //编译
npm install webpack babel-loader --save-d
webpack.config.js //新建,配置
package.json中scripts //配置
npm start
*rollup
没有模块化
AMD成为标准 require.js /(CMD)
前端打包工具,使node.js模块化也可以被使用
ES6想统一现所有模块化标准
node.js积极支持,浏览器端尚未统一
可以自建lib,不要自建标准
function MathHandle(x, y) {
this.x = x
this.y = y
} //构造函数
MathHandle.prototype.add = function () {
return this.x + this.y
}//原型中定义了方法
var m = new MathHandle(1, 2)//实例化了一个m
console.log(m.add())
例子:
class MathHandle {
constructor(x, y) {
this.x = x;
this.y = y;
}
add() {
return this.x + this.y;
}
}
const m = new MathHandle(1, 2);
console.log(m.add());
重点
typeof MathHandle //'function'
MathHandle.prototype.constructor === MathHandle //true 构造函数有显式原型 显式原型的constructor属性等于构造函数本身
m.__proto__ === MathHandle.prototype //true new出来的实例有隐式原型,等于构造函数的显式原型
class MathHandle {
//……
}
重点
typeof MathHandle // 'function' class本身就是function
MathHandle.prototype.constructor === MathHandle // true
m.__proto__ === MathHandle.prototype // true
低级函数的原型赋值给高级构造函数的实例
// 动物
function Animal() {
this.eat = function () {
alert('Animal eat')
}
}
// 狗
function Dog() {
this.bark = function () {
alert('Dog bark')
}
}
// 绑定原型,实现继承
Dog.prototype = new Animal() //初始化一个Animal实例赋值给Dog的显式原型中
var hashiqi = new Dog()
hashiqi.bark()
hashiqi.eat()
Class
class Animal {
constructor(name) {
this.name = name
}
eat() {
alert(this.name + ' eat')
}
}
class Dog extends Animal {
constructor(name) {
super(name) // 注意 !!!extends super
this.name = name
}
say() {
alert(this.name + ' say')
}
}
const dog = new Dog('哈士奇')
dog.say()
dog.eat()
class语法上贴合面向对象的写法
class实现继承上更加简单 易理解
易于写java等后端语言的使用
本质语法糖,使用prototype
适用于异步编程
箭头函数“绑定”this
Vue.js
React.js
Angular.js
Model
View
Controller
Model 服务端,数据来源
View 页面
ViewModel 框架,如vue.js,核心

数据驱动页面(data->view),页面变了也能将js中保存的变量做相应的改变(view->data),这个过程是自动的。

(data->view):Object.defineProperty(核心API,目前最新的框架),可以监听data的变化,然后有个回调函数,在回调函数中做处理
(view->data):通过input事件,只不过框架执行了我们看不到
defineProperty.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Object.defineProperty</title>
</head>
<body>
<script type="text/javascript">
var obj1 = {};
var descriptor = Object.create(null); // 没有继承的属性
// 默认没有 enumerable,没有 configurable,没有 writable
descriptor.value = 'static';
Object.defineProperty(obj1, 'key', descriptor);
console.log(obj1);
</script>
<script type="text/javascript">
// 显式
var obj2 = {};
Object.defineProperty(obj2, 'key', {
enumerable: true,
configurable: false,
writable: false,
value: 'static',
});
console.log(obj2);
</script>
</body>
</html>
Reflect.defineProperty的区别Reflect.defineProperty返回Bool值 ES6
Object.defineProperty返回对象 ES5
useObjectdefineProperty.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>双向绑定</title>
</head>
<body>
手写一个简单的双向绑定<br/>
<input type="text" id="model"><br/>
<div id="modelText"></div>
</body>
<script type="text/javascript">
var model = document.querySelector("#model");
var modelText = document.querySelector("#modelText");
var defaultName = "defaultName";
var userInfo = {}
model.value = defaultName;
Object.defineProperty(userInfo, "name", {
get: function () {
return defaultName;
},
set: function (value) {
defaultName = value;
model.value = value;
console.log("-----value");
console.log(value);
modelText.textContent = value;
}
})
userInfo.name = "new value";
var isEnd = true;
model.addEventListener("keyup", function () {
if (isEnd) {
userInfo.name = this.value;
}}, false)
//加入监听中文输入事件
model.addEventListener("compositionstart", function () {
console.log("开始输入中文");
isEnd = false;
})
model.addEventListener("compositionend", function () {
isEnd = true;
console.log("结束输入中文");
})
</script>
</html>
即观察者模式
有一个监听者,监听data的变化,通知观察者列表,watcher会更新view

Vue生命周期

React生命周期:实例化Mounting、存在期Updating和销毁时Unmounting

即时错误(代码错误)
资源加载错误(css,js加载出错)
try.catch
window.onerror
object.onerror
window.onerror捕捉不到object.onerror因为后者捕捉到错误后不会在冒泡
performance.getEntries()
Error事件捕获
###跨域的JS运行错误可以捕获吗?错误提示是什么?如何处理
在script标签增加crossorigin属性
设置js资源响应头Access-Control-Allow-Origin:*
采用Ajax通信方式上报
利用Image对象上报
error.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>错误监控</title>
<script type="text/javascript">
window.addEventListener('error', function (e) {
console.log('捕获', e);
}, false);
</script>
</head>
<body>
<script src="//badu.com/test.js" charset="utf-8"></script>
<script type="text/javascript">
(new Image()).src = 'http://baidu.com/tesjk?r=tksjk';
</script>
</body>
</html>
dns-prefetch x-dns-prefetch-control资源文件在浏览器中存在的备份/副本
浏览器不询问服务器,直接使用本地的缓存
Expires 服务器的绝对时间,与浏览器时间可能存在偏差
Cache-Control 跟的是相对时间,以秒为单位,在3600S内直接使用缓存
都下发的话,以后者为准
浏览器发送请求询问服务器是否可以使用本地缓存文件
Last-Modified 服务器下发的
If-Modified-Since 请求的 带着的
If-None-Match
Etag Hash值
Last-Modified常与If-Modified-Since一起由客户端将Last-Modified值包括在HTTP头信息中发给服务端进行处理。
通过时间判断数据有没有更新不能很好的确定文件有没有更改;
Etag可以理解为根据文件内容计算的hash值;
ETag常与If-None-Match或者If-Match一起,由客户端通过HTTP头信息(包括ETag值)发送给服务端处理。
同步任务优先于异步任务。
在同步队列被执行完之前,任何异步的操作都不会被执行
console.log(1);
console.log(2);
setInterval和setTimeout
DOM事件
ES6中的promise
运行栈运行的是同步任务。
浏览器识别了事件是一个异步任务,他不会把他放在运行栈里,而是拿走。
拿走了之后也不是立马放在异步队列中,同步任务执行完以后,再放入异步队列。
运行栈里没有任务了,就开始执行异步任务。
执行完后如果运行栈里没有任务了,再监听异步队列。
这个循环的过程就是EventLoop

DTD(Document Type Definition 文档类型定义)
用来定义XML或者(X)HTML的文件类型
浏览器会使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式
声明文档类型和DTD规范
告诉浏览器当前文档包含的是哪个DTD
用于文件的合法性验证,如果文件代码不合法,那么浏览器解析会出错
HTML5
HTML5 不基于 SGML,所以不需要引用 DTD
<!DOCTYPE html>
HTML4 strict 严格模式
该DTD包含所有HTML元素和属性,但不包括展示性和废弃的元素(如font)
HTML4 Transitional 传统模式
该DTD包含所有HTML元素和属性,包括展示性和废弃的元素

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置
增加/删除/修改DOM节点时,会导致Reflow或Repaint
移动DOM位置,或者做动画
修改CSS样式
Resize窗口(移动端无)/滚动
修改网页的默认字体
各种盒子位置/大小/其他属性如颜色 字体大小等确定之后,浏览器于是把这些元素按照自己的特性绘制
DOM改动
CSS改动
要改变的节点添加到一个片段了,一次repaint