一、Vue原理:4部分:
1.通过document.createDocumentFragment()创建虚拟dom树。
2. 检测数据改变通过object.defineProperty定义的数据拦截,截取到数据的变化。
3.然后通过发布订阅者模式,触发watcher来改变虚拟dom中的具体数据
4. 通过更新虚拟dom的元素值,改变最后渲染的dom树的值,完成双向绑定
二、继承:3种:
Function parent(name){
//属性 this.name = name || ‘parent’;
//实例方法
This.sleep = function(){}
}
//原型方法:
Parent.prototype.eat = function(food){
Console.log(food)
}
1.原型链继承
Function son(){}
Son.prototype = new parent();
Son.prototype.name = ‘son’;
//测试:
Var son = new son();
Console.log(son instanceof parent); //true
Console.log(son instanceof son); //true
2. 构造函数继承
Function son(name){
Parent.call(this);
This.name = name || ‘son’;
}
//测试
Var son = new son();
Console.log(son instanceof parent); //true;
Console.log(son instanceof son); //true
3. 组合继承
Function son(name){
Parent.call(this);
This.name = name || ‘son’
}
Son.prototype = new parent();
//测试
Var son = new son();
Console.log(son instanceof parent); //true;
Console.log(son instanceof son); //true;
4.vue继承:
1. 父组件:
Const component = { template:
父组件</div>
}
子组件继承:extends
Const Comp = Vue.extend(component);
New Comp({
El:”#root”,
Data:{
Text:”1234”
}
})
继承的组件的prop需要通过propsData传入,继承的组件排后面
2.子组件:
Const component2 = {
Extends:component,
Data(){
Return {
Text:1
}
}
}
继承的组件改变父组件的东西,可以用$parent,一般不可改变,可以用this.$parent查看
5. Es5继承实现:
(1) Function son(Parent,Child){
Child.prototype = new Parent();
Child.prototype.constructor = Child;//父类构造函数含参时不可用
}
(2)Function son (Parent,CHild){
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
}
(3) Function son(Parent,Child){
let temp = function(){};
Temp.prototype = Parent.prototype;
Child.prototype = new Temp();
Child.prototype.constructor = Child;
}
6.react继承:
Class Parent extends React.Component{
Constructor(props){
Super(props);
}
}
Class son extends Parent{
Constructor(props){
Super(props);
}
}
三、闭包:闭包就是一级函数调用二级函数,二级函数访问一级函数里的词法作用域里的变量
四、递归:有始有终的循环,使用场景:使用循环ajax请求(我维护的table列表组件,做了一个表头筛选功能,筛选的数据得从后台获取,这个时候需要循环数组发送ajax请求,但ajax是异步的多个请求无法正常返回处理,就用的递归在ajax的回调中重新调用),递归的缺点:如果递归函数的终止条件不明确或者缺少终止条件会导致函数长时间运行,是用户界面处于假死状态。
四、Vue父传子、子传父、非父子传值:
父传子:子组件props创建属性,接收父组件的值
子传父:子组件绑定点击事件,
该事件函数中用$emit触发自定义事件click(){this.$emit(‘abcd’,value)},并传一个参数,
在父组件的子标签中监听该自定义事件并添加该事件的处理方法,<child v-on:abcd=’fn’></child> fn:function(value){console.log(value)}
非父子传值:
公共bus :import Vue from ‘vue’; export default new Vue();
A组件:
import Bus from “./bus.js” <a @click=’giveValue’></a> giveValue:function(){Bus.$emit(‘val’,value)}
B组件:
Import Bus from ‘./bus.js’; Bus.$on(‘val’,data=>{console.log(data)})
五、vue单向数据流、双向数据流:
vue主要由View、Model、ViewModel组成,View和ViewModel不能直接通信
单向数据流:只能从一个方向修改数据,把Model绑定到View,更新Model时View自动更新
双向数据流:由MVVM框架实现,把Model绑定到View的同时View也绑定到Model上,
六、Vue路由守卫:
BeforeEach:导航前置守卫:router.beforeEach((to,from,nect)=>{
To:route:即将进入目标的路由对象;
From:route:当前导航正要离开的路由;
Next:function:next();进行下一个钩子;next(false);终端当前导航;next(‘/’)或next({path:”/”})跳转到不同的地址;next(error)如果传入的参数是一个error实例导航会终止改错误会被传递给router.onErroe()注册过的回调
})
beforeEach:后置守卫:
Router.afterEach((to,from)=>{
})
最后是完整的导航解析流程
导航被触发
在失活的组件里调用离开守卫
调用全局的beforeEach守卫
在重用的组件里调用beforeRouteUpdate守卫
在路由配置里调用beforEnter
解析异步路由组件
在被激活的组件里调用beforeRouteEnter
调用全局的beforeResolve守卫
导航被确认
调用全局的afterEach钩子
触发DOM更新
在创建好的实例调用beforeRouteEnter守卫中传给 next 的回调函数
左右tab切换的时候或者权限的时候用路由守卫
五、高阶组件:
一个组件包裹着另一个react组件,因为要访问其内部属性,所以要用到继承,高阶组件就是一个函数,接收另一个组件做参数并返回一个新组建。
使代码更具有复用性、逻辑性和抽象特征。
为了代码的复用性、减少代码的冗余
应用场景:
Function Autho(RouterComp){
Class AuthoHoc extends Component{
Render(){
Return <RouterComp />
}
} return AuthoHoc;
}
五、React组件通信:
父传子:props;
子传父:利用回调函数、利用自定义事件机制
回调函数:
子组件:
<button onClick={this.props.hide}></button>
父组件:
hideComponent = () => {
Console.log(‘123’)
}
<div><Button hide = {this.hideComponent}></Button></div>
自定义事件机制:
下包:npm install events -s;
src下util建events.js;写:import {EventEmitter} from ‘events’; export default new EventEmitter();
同级组件1:
Import emitter from ‘./events.js’;
Class list1 extends Component{
Constructor(props){
Super(props);
}
componentDidMount(){
//组件装在完成后声明一个自定义事件;
This.eventEmitter = emitter.addListener(‘fn’,(message)=>{
This.setState({
message
})
})
Render(){
Return <div>{this.state.message}</div>
}
}
}
Export default List1;
同级组件2:
Import emitter from ‘./events’;
Class List2 extends Coponent{
handleClick=(message) =>{
Emitter.emit(‘fn’,message);
}
Render(){
Return <button onClick= {this.handleClick.bind(this,’abcd’)}></button>
}
}
App组件:render(){
Return <div><list1/><list2/></div>
}
跨级组件通信:
·层层组件传递props;
·使用context:
孙组件:
Import React,{Component} from “react”;
Import PropTypes from ‘prop-types’;
Class son extends Component{
//子组件声明自己要是用的context;
Static contextTpes = {
Color:PropTypes.string
}
Static propTypes = {
Value:PropTypes.string
}
Render(){
Const {value} =this.props;
Return <li style={{background:this.context.color}}>{value}</li>
}
}
Export default son;
子组件:
Import Son from ‘./son’;
Class Abcd extends Component{
//父组件声明自己支持context;
Static ChildContextTypes = {
Color:PropTypes.string
}
Static propTypes = {
List:PropTypes.array
}
//提供一个函数,用来返回响应的context对象;
getChildContext(){
Return {
Color:”red”
}
}
Render(){
Const {list} = this.props;
Return <div>{
List.map((entry,index)=>{
<Son value={entry.text}></Son>
})
}</div>
}
}
父组件:
Import Son from “./son’;
Const list = [{text:”1”},{text:”2”}];
Export default class App extends Component{
Render(){
Return <div><Son list= {list}></Son></div>
}
}
六、React生命周期:
1、ComponentDidMount();//组件挂载完成之后出发===vue的mounted;
2、ComponentWillMount();//组件挂载之前===vue的beforeMount;
3、ComponentWillReceiveProps(nextProps);//组件将要接收新的props;
componentWillReceiveProps(nextProps){//唯一一个和props相关的生命周期
//旧的props this.props;
//新的props nextProps;
}
4、shouldComponentUpdate(nextProps,nextState);//通过返回值判断组件是否需要更新用于react优化,true更新,false不更新
shouldComponentUpdate(nextProps,nextState){
//旧的props; this.props;
//新的props; nextProps;
//旧的state ; this.state;
//新的state; nextState;
//返回值Boolean; 默认true;
}
5、ComponentWillUPdate//组件将要更新===vue的beforeUPDATE;
6、ComponentDidUpdate//组件更新完成===vue的updated
7、ComponentWillUNmount//组件将要卸载;
8、unmountComponentAtNode()//卸载组件;
9、三个阶段:
五、==与===的区别:
==:相等:检测两个操作数是否相等
===:检测是否严格相等:类型不同就不相等
六、[endif]Node :
node搭建http服务器:
var http = require(‘http’);
Var fs = require(‘fs’);
//开启服务
Var server = http.createServer(function(req,res){
Var url = req.url;
Var file = root + url;
Fs.readFile(file,function(err,data){
If(err){
Res.writeHeader(404,{
‘content-type’:’text/html;charset=”utf-8” ’ ;
})
Res.write(‘404’);
Re.end();
}else{
Res.wtiteHeader(404,{
‘content-type’:”text/html;charset=’utf-8’ ”;
})
Res.wirte(data)//讲index.html显示在客户端;
Res.end();
}
})
}).listen(8080);
1. Nodejs npm常用指令:
Npm install -g /-s noduleNames :安装node模块
Npm view moduleName:查看
Npm list:查看当前目录已下载的包
Npm help:查看帮助命令;
Npm update moduleName:更新模块
Npm uninstall moduleName:卸载node模块
Npm init初始化
Npm root查看当前包的安装路径
Npm -v查看npm的版本;
2.
七、手动搭建webpack;
Var webpack = require(‘webpack’);
Var htmlwebpackPlugin = require(‘html-webpack-plugin’);
Var root_path = path.reaolve(__dirname);
Var src_path = path.reoslve(root_path,’src’);
Var build_path = path.reslove(root_path,’dist’);
module.exports = {
Entry:{//入口
Index:path.resolve(src_path , ’ index.jsx’);
},
Output:{//输出
Path:build_path,
Filename : ”js/[name].[has:5].js ”//输出文件命名
},
Plugins:[//默认配置项
],
Devtool: ”eval-source-map”,
devServer:{
historyApiFallback:true,
Hot:true,//热启动
Inline:true//
},
Reslove:{
Extensions:[ ‘ .js ’ , ’ .jsx ’ ]
},
Module:{
Loaders:[{
test:/\.css/,
Include:[path.resolve(__dirname,’src’)],
Use:[‘style-loader’ , ’css-loader’]
},{
Test:/\.less/,
Use:extractTextPlugin.extract({
fallback:’style-loader’,
use:[‘css-loader’,’less-loader’]
}),
},{
Test:/\.(png | jpg | gif)/,
Use:[{
Loader : ’ file-loader’,
Options : {}
}]
},{
Test:/\.(woff | eot | ttf | otf )/,
Loader:’url-loader’,
},{
Test:/\.jsx/,//babel,
Loader : ’babel-loader’,
}]
},
Plugins:[
}
阻止事件冒泡,取消默认事件:
event.stopPropagation()起到阻止捕获和冒泡阶段中当前事件的进一步传播。使用event.preventDefault()可以取消默认事件。
先捕获,后冒泡,捕获从上到下,冒泡从下到上
MVVM:
原理:深入理解mvvm的原理,实现数据劫持,数据双向绑定,数据驱动页面,数据双向绑定,计算属性computed!
1.MVVM是什么?
1.MVVM是Model-View-ViewModel的简写
2. 它本质上是MVC 的改进版
3. MVVM(Model-View-ViewModel)框架的由来是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架
2、MVVM优点
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点
1. 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
2.可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
3.独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码
4. 可测试:界面素来是比较难于测试的,而现在测试可以针对ViewModel来写
5. 获取元素
ref 获取dom(refer to缩写)
findDomNode 获取dom的实例
按需加载
封装一个loading组件
import React from 'react';
import '../../scss/index.css';
export default ()=>{
return <div className='load'>
<img src="/load.gif"/>
</div>
}
react现有版本的生命周期,以及新的生命周期:数据初始化、dom初始化、更新期、销毁期
2、手机号12345678901变成123****8901;
'12345678901'.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
3、map和forEach的区别:
map返回新数组原数组不会改变,forEach返回值是undefined你能链式调用,而且forEach没法终止循环
4、Id排序:var arr6 = [{id:10,age:2},{id:5,age:4},{id:6,age:10},{id:9,age:6},{id:2,age:8},{id:10,age:9}]; arr6.sort(function(a,b){ if(a.id === b.id){//如果id相同,按照age的降序 return b.age - a.age }else{ return a.id - b.id }})console.log(arr6);
5、发布订阅者模式:class Watch{ store = {} on(type,fn){ on 订阅 fn为监听者 if(!(this.store[type] instanceOf Array)){ this.store[type] = []; } this.store[type].push(fn); } emit(type,reset){ emit发布 if(!this.store[type]){ return } this.store[type].forEach(item => { item(reset); 在on的回调函数中将数据返给on }) }}
6、js继承:
1、原型链继承
核心: 将父类的实例作为子类的原型
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
特点:
1. 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
2.父类新增原型方法/原型属性,子类都能访问到
3. 简单,易于实现
缺点:
1.要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,不能放到构造器中
2. 无法实现多继承
3.来自原型对象的所有属性被所有实例共享
4.创建子类实例时,无法向父类构造函数传参
2、构造继承
核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特点:
1.解决了1中,子类实例共享父类引用属性的问题
2.创建子类实例时,可以向父类传递参数
3.可以实现多继承(call多个父类对象)
缺点:
1. 实例并不是父类的实例,只是子类的实例
2.只能继承父类的实例属性和方法,不能继承原型属性/方法
3. 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3、实例继承
核心:为父类实例添加新特性,作为子类实例返回
function Cat(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // false
特点:
1. 不限制调用方式,不管是new 子类()还是子类(),返回的对象具有相同的效果
缺点:
1.实例是父类的实例,不是子类的实例
2.不支持多继承
4、拷贝继承
function Cat(name){
var animal = new Animal();
for(var p in animal){
Cat.prototype[p] = animal[p];
}
Cat.prototype.name = name || 'Tom';
}
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true
特点:
1. 支持多继承
缺点:
1. 效率较低,内存占用高(因为要拷贝父类的属性)
2.无法获取父类不可枚举的方法(不可枚举方法,不能使用for in 访问到)
5、组合继承
核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
Cat.prototype = new Animal();Cat.prototype.constructor = Cat;
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true
特点:
1.弥补了方式2的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
2.既是子类的实例,也是父类的实例
3.不存在引用属性共享问题
4. 可传参
5. 函数可复用
缺点:
1.调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)
6、寄生组合继承
核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){
Animal.call(this);
this.name = name || 'Tom';
}
(function(){
// 创建一个没有实例方法的类
var Super = function(){};
Super.prototype = Animal.prototype;
//将实例作为子类的原型
Cat.prototype = new Super();
})();
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.sleep());
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true
Cat.prototype.constructor = Cat; // 需要修复下构造函数
特点:
1. 堪称完美
缺点:
1. 实现较为复杂
function Cat(name){
原因分析:
关键点:属性查找过程
执行tom.features.push,首先找tom对象的实例属性(找不到),
那么去原型对象中找,也就是Animal的实例。发现有,那么就直接在这个对象的
features属性中插入值。
在console.log(kissy.features); 的时候。同上,kissy实例上没有,那么去原型上找。
刚好原型上有,就直接返回,但是注意,这个原型对象中features属性值已经变化了。
7、setTimeout红任务先执行Promise微任务后执行,js就是红任务,然后就先执行红任务之后把微任务放在红任务队列里继续执行
8、为什么用虚拟dom更优化:
采用虚拟DOM的好处是,当数据变化的时候,无需像Backbone那样整体重新渲染,而是局部刷新变化部分
所谓虚拟DOM,其实就说用JavaScript对象来构建DOM树。
虚拟DOM以 js结构的形式存在,计算性能会比较好,而且由于减少了实际DOM操作次数,性能会有很大提示。
虚拟DOM 只是减少了一些情况下, 对真实DOM操作的 次数.
虚拟DOM只是个JavaScript object
它会在对比 后再选择更新哪些DOM, 而不会像有些时候, 全部删除再重建.
获取/修改 大量DOM元素的时候,就会先在虚拟DOM 里 取值 对比.
9、Apply、call的区别:
都是改变this指向,作用一样,接受参数不一样;
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
10、React生命周期:
实例化
当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:
1、getDefaultProps2、getInitialState3、componentWillMount4、render5、componentDidMount
当组件在服务端被实例化,首次被创建时,以下方法依次被调用:
1、getDefaultProps2、getInitialState3、componentWillMount4、render
componentDidMount 不会在服务端被渲染的过程中调用。
getDefaultProps
对于每个组件实例来讲,这个方法只会调用一次,该组件类的所有后续应用,getDefaultPops 将不会再被调用,其返回的对象可以用于设置默认的 props(properties的缩写) 值。
var Hello = React.creatClass({
getDefaultProps: function(){
return {
name: 'pomy',
git: 'dwqs'
}
},
render: function(){
return (
<div>Hello,{this.props.name},git username is {this.props.dwqs}</div>
)
}
});
ReactDOM.render(<Hello />, document.body);
也可以在挂载组件的时候设置props:
var data = [{title: 'Hello'}];
<Hello data={data} />
或者调用setProps (一般不需要调用)来设置其 props:
var data = [{title: 'Hello'}];var Hello = React.render(<Demo />, document.body);Hello.setProps({data:data});
但只能在子组件或组件树上调用setProps。别调用 this.setProps 或者 直接修改 this.props。将其当做只读数据。
React通过 propTypes 提供了一种验证props 的方式,propTypes 是一个配置对象,用于定义属性类型:
var survey = React.createClass({
propTypes: {
survey: React.PropTypes.shape({
id: React.PropTypes.number.isRequired
}).isRequired,
onClick: React.PropTypes.func,
name: React.PropTypes.string,
score: React.PropTypes.array
...
},
//...})
组件初始化时,如果传递的属性和propTypes 不匹配,则会打印一个 console.warn 日志。如果是可选配置,可以去掉.isRequired。常用的 PropTypes 如下:
getInitialState
对于组件的每个实例来说,这个方法的调用有且只有一次,用来初始化每个实例的state,在这个方法里,可以访问组件的 props。每一个React组件都有自己的 state,其与 props 的区别在于 state只存在组件的内部,props 在所有实例中共享。
getInitialState 和 getDefaultPops 的调用是有区别的,getDefaultPops 是对于组件类来说只调用一次,后续该类的应用都不会被调用,而 getInitialState 是对于每个组件实例来讲都会调用,并且只调一次。
var LikeButton = React.createClass({
getInitialState: function() {
return {liked: false};
},
handleClick: function(event) {
this.setState({liked: !this.state.liked});
},
render: function() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
});
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
每次修改state,都会重新渲染组件,实例化后通过 state 更新组件,会依次调用下列方法:
1、shouldComponentUpdate2、componentWillUpdate3、render4、componentDidUpdate
但是不要直接修改this.state,要通过 this.setState 方法来修改。
componentWillMount
该方法在首次渲染之前调用,也是再render 方法调用之前修改 state 的最后一次机会。
render
该方法会创建一个虚拟DOM,用来表示组件的输出。对于一个组件来讲,render方法是唯一一个必需的方法。render方法需要满足下面几点:
只能通过this.props 和 this.state 访问数据(不能修改)
可以返回null,false 或者任何React组件
只能出现一个顶级组件,不能返回一组元素
不能改变组件的状态
不能修改DOM的输出
render方法返回的结果并不是真正的DOM元素,而是一个虚拟的表现,类似于一个DOM tree的结构的对象。react之所以效率高,就是这个原因。
componentDidMount
该方法不会在服务端被渲染的过程中调用。该方法被调用时,已经渲染出真实的DOM,可以再该方法中通过this.getDOMNode() 访问到真实的 DOM(推荐使用 ReactDOM.findDOMNode())。
var data = [..];var comp = React.createClass({
render: function(){
return <imput .. />
},
componentDidMount: function(){
$(this.getDOMNode()).autoComplete({
src: data
})
}
})
由于组件并不是真实的DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。有时需要从组件获取真实 DOM 的节点,这时就要用到ref 属性:
var Area = React.createClass({
render: function(){
this.getDOMNode(); //render调用时,组件未挂载,这里将报错
return <canvas ref='mainCanvas'>
},
componentDidMount: function(){
var canvas = this.refs.mainCanvas.getDOMNode();
//这是有效的,可以访问到 Canvas 节点
}
})
需要注意的是,由于this.refs.[refName] 属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。
存在期
此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用
1、componentWillReceiveProps2、shouldComponentUpdate3、componentWillUpdate4、render5、componentDidUpdate
componentWillReceiveProps
组件的props 属性可以通过父组件来更改,这时,componentWillReceiveProps 将来被调用。可以在这个方法里更新 state,以触发 render 方法重新渲染组件。
componentWillReceiveProps: function(nextProps){
if(nextProps.checked !== undefined){
this.setState({
checked: nextProps.checked
})
}
}
shouldComponentUpdate
如果你确定组件的props 或者 state 的改变不需要重新渲染,可以通过在这个方法里通过返回false 来阻止组件的重新渲染,返回 `false 则不会执行 render 以及后面的 componentWillUpdate,componentDidUpdate 方法。
该方法是非必须的,并且大多数情况下没有在开发中使用。
shouldComponentUpdate: function(nextProps, nextState){
return this.state.checked === nextState.checked;
//return false 则不更新组件
}
componentWillUpdate
这个方法和componentWillMount 类似,在组件接收到了新的 props 或者 state 即将进行重新渲染前,componentWillUpdate(object nextProps, object nextState) 会被调用,注意不要在此方面里再去更新props 或者 state。
componentDidUpdate
这个方法和componentDidMount 类似,在组件重新被渲染之后,componentDidUpdate(object prevProps, object prevState) 会被调用。可以在这里访问并修改 DOM。
销毁时
componentWillUnmount
每当React使用完一个组件,这个组件必须从 DOM 中卸载后被销毁,此时 componentWillUnmout 会被执行,完成所有的清理和销毁工作,在 componentDidMount 中添加的任务都需要再该方法中撤销,如创建的定时器或事件监听器。
当再次装载组件时,以下方法会被依次调用:
1、getInitialState2、componentWillMount3、render4、componentDidMount
12、Js冒泡排序、快速排序:
冒泡排序:
随便从数组中拿一位数和后一位比较,如果是想从小到大排序,那么就把小的那一位放到前面,大的放在后面,简单来说就是交换它们的位置,如此反复的交换位置就可以得到排序的效果。
function sortA(arr){
for(var i=0;i<arr.length-1;i++){
for(var j=i+1;j<arr.length;j++){
//获取第一个值和后一个值比较
var cur = arr[i];
if(cur>arr[j]){
// 因为需要交换值,所以会把后一个值替换,我们要先保存下来
var index = arr[j];
// 交换值
arr[j] = cur;
arr[i] = index;
}
}
}
return arr;
}
快速排序:
从数组的中间拿一个值,然后通过这个值挨个和数组里面的值进行比较,如果大于的放一边,小于的放一边,然后把这些合并,再进行比较,如此反复即可。
function sortA(arr){
// 如果只有一位,就没有必要比较
if(arr.length<=1){
return arr;
}
// 获取中间值的索引
var len = Math.floor(arr.length/2);
// 截取中间值
var cur = arr.splice(len,1);
// 小于中间值放这里面
var left = [];
// 大于的放着里面
var right = [];
for(var i=0;i<arr.length;i++){
// 判断是否大于
if(cur>arr[i]){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
// 通过递归,上一轮比较好的数组合并,并且再次进行比较。
return sortA(left).concat(cur,sortA(right));
}
13、事件代理:
事件代理也叫事件委托,多个dom需要添加事件处理时,就用事件代理,
事件代理是利用事件的冒泡原理来实现的,就是事件从最深的节点开始,然后逐步向上传播事件
14、微信小程序授权流程:
第一种使用wx.getUserInfo直接获取微信头像,昵称
wx.getUserInfo({
success: function (res) {
that.setData({
nickName: res.userInfo.nickName,
avatarUrl: res.userInfo.avatarUrl,
})
},
})
能获取到:姓名、性别、手机号、头像
15、For for...in for...of的区别:
普通for循环在Array和Object中都可以使用
for in在Array和Object中都可以使用。
for of在Array、Object、Set、Map中都可以使用
json字符串----->json对象
使用JSON.parse()函数
var jsonStr = '{"name":"zhangsan","age":23,"email":"chentging@aliyun.com"}';var json = JSON.parse(jsonStr);
console.log(json);//输出:Object {name: "zhangsan", age: 23, email: "chentging@aliyun.com"}
使用eval()函数
var jsonStr = '{"name":"zhangsan","age":23,"email":"chentging@aliyun.com"}';var json = eval ("(" + jsonStr + ")");
console.log(json);//输出:Object {name: "zhangsan", age: 23, email: "chentging@aliyun.com"}
使用jQuery插件jQuery.parseJSON()
var jsonStr = '{"name":"zhangsan","age":23,"email":"chentging@aliyun.com"}';var json = jQuery.parseJSON(jsonStr);
console.log(json);//输出:Object {name: "zhangsan", age: 23, email: "chentging@aliyun.com"}
1. json对象------>json字符串
使用JSON.stringify()
var json = {name: "zhangsan", age: 23, email: "chentging@aliyun.com"};
var jsonStr = JSON.stringify(json);
console.log(jsonStr);//输出:"{"name":"zhangsan","age":23,"email":"chentging@aliyun.com"}"
把数据在前后端之间传递,需要把json对象转换为json字符串
16、加密:
base64:var bas=new Base64();bas.encode(值);//加密;bas.decode(值)//解密
Md5:<script src=’md5.js’></script> var hash = hex_md5(‘12345’);
Sha1:<script src=’sha1.js’></sxript> var sha = hex_sha1(‘1234’);
17、a=’35’ b=’1243456’返回-1;a =’34’ b=’123456’;返回2;
function collectLetterIndex(firstLetter,parentStr){
const firstLetterIndexs = []
for(let i = 0; i < parentStr.length; i++){
if(firstLetter === parentStr[i]){
firstLetterIndexs.push(i);
}
}
return firstLetterIndexs;
}
/**
* @param {*} collectIndex
* @param {*} parentStr
* @param {*} childStr
*/
function findFromCollectIndex(collectIndex,parentStr,childStr){
for(let i = 1; i < childStr.length; i++){
if(collectIndex + 1 >= parentStr.length){
return false;
}
// console.log(parentStr[collectIndex + i], childStr[i]);
if(parentStr[collectIndex + i] !== childStr[i]){
return false;
}
}
return true;
}
function findStr(childStr, parentStr){
const firstLetterIndexs = collectLetterIndex(childStr[0],parentStr);
// console.log(firstLetterIndexs);
for(let i = 0; i < firstLetterIndexs.length; i++){
const result = findFromCollectIndex(firstLetterIndexs[i],parentStr,childStr);
if(result){
return firstLetterIndexs[i];
}
}
return false;
}
findStr(‘35’,’12345678’);//-1;
findStr(‘34’,’12345678’);//-2;
17、es6新特性:set、map
Set属性:add添加、delete删除、has有没有、clear清楚所有
能去重keys()返回键名的遍历器、vlaues()返回键值的遍历器、entries()返回键值对的遍历器、forEach()返回回调函数遍历每个成员
使用Set 可以很容易地实现并集(Union)、交集(Intersect)和差集(Difference)。
let a = new Set([1, 2, 3]);let b = new Set([4, 3, 2]);
// 并集let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}
// 交集let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}
// 差集let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
Map:
Map属性:size返回map结构的成员总数;set(key,value)返回当前map对象,可采用链式let map = new Map().set(1,’a’).set(2,’b’).set(3,’c’);get(key)读取key对应的键值,找不到返回undefined;has(key)返回布尔值;delete(key)删除某个键,成功true,失败返回false;clear()清除所有成员,没有返回值;
keys():返回键名的遍历器。
values():返回键值的遍历器。
entries():返回所有成员的遍历器。
forEach():遍历 Map 的所有成员,能接受第二个参数,用来绑定this。
Map转数组:用扩展运算符... 数组转map:new Map([ [1,4],[{num:0},{abcd:0}] ])
17、部署nodejs:
买服务器,得到密钥,开始远程服务器端环境配置,先打开cmder,
ssh服务器用户名@自己的服务器ip地址,
创建个人目录
安装node,配置node到全局环境
安装git、PHPStudy
启动PHPStudy,
配置mysql为全局变量
应用代码部署,用git同步到线上
同步数据库
18、https:
HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。
HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。
HTTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
HTTPS的工作原理
我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。
客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤,如图所示。
(1)客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。
HTTPS的优点
尽管HTTPS并非绝对安全,掌握根证书的机构、掌握加密算法的组织同样可以进行中间人形式的攻击,但HTTPS仍是现行架构下最安全的解决方案,主要有以下几个好处:
(1)使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
(2)HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
(3)HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。
(4)谷歌曾在2014年8月份调整搜索引擎算法,并称“比起同等HTTP网站,采用HTTPS加密的网站在搜索结果中的排名将会更高”。
五、HTTPS的缺点
虽然说HTTPS有很大的优势,但其相对来说,还是存在不足之处的:
(1)HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;
(2)HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
(3)SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
(4)SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
(5)HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。
六、http切换到HTTPS
如果需要将网站从http切换到https到底该如何实现呢?
这里需要将页面中所有的链接,例如js,css,图片等等链接都由http改为https。例如:http://www.baidu.com改为https://www.baidu.com
BTW,这里虽然将http切换为了https,还是建议保留http。所以我们在切换的时候可以做http和https的兼容,具体实现方式是,去掉页面链接中的http头部,这样可以自动匹配http头和https头。例如:将http://www.baidu.com改为//www.baidu.com。然后当用户从http的入口进入访问页面时,页面就是http,如果用户是从https的入口进入访问页面,页面即使https的。