minnsss blog

I was never there.


  • 首页

  • 标签

  • 分类

  • 归档

  • 关于

组件化与React

发表于 2018-09-09 | 分类于 前端

组件化与React

问题

  1. 组件化的理解
  2. JSX的本质
  3. JSX与vdom的关系
  4. setState的过程
  5. React与Vue的认识

知识点

组件化

组件的封装

视图

数据

变化逻辑(数据驱动视图变化)

组件的复用

props传递

复用

React

实现流程

MVVM与Vue

发表于 2018-09-09 | 分类于 前端

MVM与Vue

MVVM与MVC的区别

MVC

MVVM

总结

MVVM-Model View ViewModel

三者之间的联系,以及对应的代码

ViewModel的理解,联系View与Model

MVVM-Vue

Vue实现三要素

响应式

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

render函数

render函数与vdom

渲染

vue的模板如何被渲染成html,以及渲染过程

源码

todolist.html

异步

发表于 2018-09-09 | 分类于 前端

异步

问题

  1. 单线程概念,与异步的关系

  2. event-loop的概念

  3. Promise的基本原理与使用

  4. async/await(与Promise的区别与联系 ES7)

  5. 总结当前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动态加载

event-loop

概念

事件轮询,JS实现异步的具体解决方案

过程

同步代码,直接执行

异步函数先放在异步队列中

同步函数执行完毕后,轮询执行异步队列的函数

实例分析与源码

1 setTimeout无延时

setTimeout(function() {
    console.log(100)
})                          //异步队列
console.log(200)            //主进程
2 setTimeout有延时
setTimeout(function() {
    console.log(1)
}, 100)                     //异步队列 100ms后放入

setTimeout(function() {
    console.log(2)
})                          //异步队列 立刻被放入

console.log(3)              //主进程
3 ajax
$.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

Promise

async/await (ES7)

原型

发表于 2018-09-09

ES6语法

发表于 2018-09-08 | 更新于 2018-09-09 | 分类于 前端

ES6语法

问题

  1. ES6模块化如何使用,开发环境如何打包

  2. Class和普通构造函数的区别

  3. Promise的基本使用和原理

  4. 总结ES6的常用功能

知识点

模块化与开发环境

模块化的基本语法

export
import

default

开发环境配置

babel配置/babel编译语法

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 //编译

Webpack配置/模块化工具

npm install webpack babel-loader --save-d

webpack.config.js //新建,配置

package.json中scripts //配置

npm start

*rollup

JS众多模块化的标准

没有模块化

AMD成为标准 require.js /(CMD)

前端打包工具,使node.js模块化也可以被使用

ES6想统一现所有模块化标准

node.js积极支持,浏览器端尚未统一

可以自建lib,不要自建标准

Class与JS普通构造函数

JS构造函数

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基本语法

例子:

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

Promise原理与使用

适用于异步编程

Callback Hell

Promise语法

ES6的一些常用功能

let/const

多行字符串/模板变量

解构赋值

块级作用域

函数默认参数

箭头函数

箭头函数“绑定”this

rest参数

MVVM框架

发表于 2018-09-08 | 分类于 前端

MVVM框架

MVVM框架

Vue.js

React.js

Angular.js

对MVVM的认识

MVC

Model

View

Controller

MVVM

Model 服务端,数据来源

View 页面

ViewModel 框架,如vue.js,核心

MVVM框架

对比

双向绑定

定义

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

双向绑定

原理

(data->view):Object.defineProperty(核心API,目前最新的框架),可以监听data的变化,然后有个回调函数,在回调函数中做处理

(view->data):通过input事件,只不过框架执行了我们看不到

Object.defineProperty

MDN

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

用法

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生命周期

Vue生命周期

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

React生命周期

源码分析

错误监控

发表于 2018-09-08

错误监控

前端错误的分类

即时错误(代码错误)

资源加载错误(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>

页面性能

发表于 2018-09-08

页面性能

提升页面性能的方法

  1. 资源压缩合并,减少HTTP请求
  2. 非核心代码异步加载 -> 异步加载的方式 -> 异步加载的区别
  3. 利用浏览器缓存 -> 缓存的分类 -> 缓存的原理
  4. 利用CDN
  5. 预解析 浏览器默认预解析(https默认关闭预解析)
    dns-prefetch x-dns-prefetch-control

异步加载

异步加载的方式

  1. 动态脚本加载
  2. defer
  3. async

    异步加载的区别

  4. defer是在html解析完之后才会执行,若是多个,按照加载顺序执行
  5. async是在加载完之后立即执行,若是多个,执行顺序与加载顺序无关

浏览器缓存

资源文件在浏览器中存在的备份/副本

缓存的分类

强缓存

浏览器不询问服务器,直接使用本地的缓存

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值)发送给服务端处理。

JS运行机制

发表于 2018-09-08 | 分类于 前端

JS运行机制

同步任务优先于异步任务。

在同步队列被执行完之前,任何异步的操作都不会被执行

单线程

任务队列

同步任务

console.log(1);

console.log(2);

异步任务

setInterval和setTimeout

DOM事件

ES6中的promise

Event Loop

运行栈运行的是同步任务。

浏览器识别了事件是一个异步任务,他不会把他放在运行栈里,而是拿走。

拿走了之后也不是立马放在异步队列中,同步任务执行完以后,再放入异步队列。

运行栈里没有任务了,就开始执行异步任务。

执行完后如果运行栈里没有任务了,再监听异步队列。

这个循环的过程就是EventLoop

JS中的事件循环

会放入异步任务队列的语句

语句放入异步任务队列的时机

渲染机制

发表于 2018-09-07 | 更新于 2018-09-08 | 分类于 前端

渲染机制

什么是DOCTYPE及作用

DTD

DTD(Document Type Definition 文档类型定义)

用来定义XML或者(X)HTML的文件类型

浏览器会使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式

DOCTYPE

声明文档类型和DTD规范

告诉浏览器当前文档包含的是哪个DTD

用于文件的合法性验证,如果文件代码不合法,那么浏览器解析会出错

常见的DOCTYPE

HTML5

HTML5 不基于 SGML,所以不需要引用 DTD

<!DOCTYPE html>

HTML4 strict 严格模式

该DTD包含所有HTML元素和属性,但不包括展示性和废弃的元素(如font)

HTML4 Transitional 传统模式

该DTD包含所有HTML元素和属性,包括展示性和废弃的元素

浏览器渲染过程

  1. 将HTML解析成DOM树
  2. 将CSS解析成 CSS Rule Tree
  3. 根据DOM树和CSSOM来构造 Rendering Tree
  4. 再下一步就是绘制,即遍历render树,并使用UI后端层绘制每个节点

浏览器渲染过程

重排Reflow

定义

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它该出现的位置

触发Reflow

增加/删除/修改DOM节点时,会导致Reflow或Repaint

移动DOM位置,或者做动画

修改CSS样式

Resize窗口(移动端无)/滚动

修改网页的默认字体

避免触发Reflow

重绘Repaint

定义

各种盒子位置/大小/其他属性如颜色 字体大小等确定之后,浏览器于是把这些元素按照自己的特性绘制

触发Repaint

DOM改动

CSS改动

如果避免最小程度的Repaint

要改变的节点添加到一个片段了,一次repaint

布局Layout

123

minn

25 日志
1 分类
13 标签
© 2018 minn
由 Hexo 强力驱动 v3.7.1
|
主题 — NexT.Pisces v6.3.0