redux

redux

action,containers和reducer

  • action 主要是数据从应用传到store

    1
    store.dispatch(action)
  • containers是组件

  • 与component 不同 component主要是负责UI的展示
  • containers 主要是负责逻辑
  • reducer 是用来更新state
    1
    const store = createStore(reducer)

API

  • combineReducers
  • 将多个reducer 合成一个
    1
    const reducer = combineReducers({reducer1,reducer2})
  • connect (react-redux)
  • 将包装好的组件连接到Redux
    1
    connect()(Component)
1
connect(mapStateToProps,mapDispatchToProps)(Component)

FUNCTION

  • mapStateToProps
  • 建立一个从(外部的)state对象到(UI 组件的)props对象的映射关系
  • 会接受state
  • 返回一个对象
    1
    2
    3
    4
    5
    6
    const mapStateToProps = (state) => {
    return {
    // 过滤显示的内容
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
    }
    }
  • mapDispatchToProps
  • 可以是一个函数也可以是一个对象
  • 用来建立 UI 组件的参数到store.dispatch方法的映射
  • 会接受dispacth和ownProps
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // function
    const mapDispatchToProps = (
    dispatch,
    ownProps
    ) => {
    return {
    onClick: () => {
    dispatch({
    type: 'SET_VISIBILITY_FILTER',
    filter: ownProps.filter
    });
    }
    };
    }
1
2
3
const mapDispatchToProps = {
onClick: VALUE
}

===> component=>actionCreator=>reducer=>component

react组件通讯

父组件给子组件传

父组件在ReactDOM的render中当作属性传给子组件

1
2
3
4
5
6
7
{/* father */}
var arr=[1,2,3,4,5,6,7,8,9]
render(){
return <div>
<Son {...arr}></Son>
</div>
}

1
2
3
4
5
6
7
8
9
10
11
12
class Son extends React.component {
constructor(props){
super()
this.setState(props)
}
setState(props){
this.props=props
}
render(){
return <div>父组件传来的数据:{this.props}</div>
}
}

子组件给父组件传

父组件在ReactDOM的render中把一个方法当作属性传给子组件

1
2
3
4
5
6
7
8
9
10
11
{/* father */}
var arr=[1,2,3,4,5,6,7,8,9]
render(){
return <div>
<Son {...arr} sonFnName={this.fatherFn} ></Son>
</div>
}
fatherFn(arg){
//操作arg
//age===>this.props.age
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Son extends React.component {
constructor(props){
super()
this.setState(props)
//要传给父组件的数据
this.props.age=10
}
setState(props){
this.props=props
}
render(){
return <div>
父组件传来的数据:{this.props}
{/* 将当前节点挂载到this上 */}
<div ref='divTarget' onClick={()=>this.sonFn(this)}>父组件传来的方法名:{this.props.sonFnName}</div>
</div>
}
sonFn(arg){
this.props.sonFnName(arg)
}
}

ES6

class 类

一个构造函数在与关键字连用的时候就称之为类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
//定义属性
constructor(){
this.body='四肢和脑袋'
}
eat(a,b){
console.log(this.body)
this.sing()
console.log('吃东西')
}
sing(a,b){
console.log('sing:"ABC"')
}
}

class 继承

让一个构造函数拥有另一个构造函数的属性和方法

1
2
3
4
5
6
7
8
9
10
//继承 -----让Chinese拥有Person的属性的方法
class Chinese extends Person {
constructor(a,b){
super(a,b)
console.log(this)
}
speak(){
console.log('speakChinese')
}
}

react的生命钩子

recat的生命周期

react 的生命周期分为初始化(initial),更新(update)和销毁(unmount)

initial之前

  • getDefaultProps
    获取默认的props

    initial阶段会调用的生命钩子

    • getInitialState
      获取初始的state
    • componentWillMount
      组件将要安装
    • componentDidMount
      组件已经安装

      update阶段会调用的生命钩子

  • props发生改变
    • componentWillReceiveProps
      组件将要接受props
    • shouldComponentUpdate
      组件是否要更新
      //shouldCompontUpdate钩子调用后返回一个boolean     
      //  ====> false 继续运行
      //  ====> true  执行渲染操作
      
    • 渲染操作
    • 渲染操作
    • componentWillUpdate
      组件将要更新
    • componentDidUndate
      组件已经更新
    • 运行
  • state发生改变
    • shouldComponentUpdate
      组件是否要更新
      //shouldCompontUpdate钩子调用后返回一个boolean     
      //  ====> false 继续运行
      //  ====> true  执行渲染操作
      
    • 渲染操作
      react的生命周期

webpack

webpack

webpack的安装

  • 注意文件名最好是全英文的

    1. npm i webpack -g
      全局安装
    2. npm i webpack -D
      安装到项目中

      webpack.config.js 配置文件

      配置文件里面需要使用模块化
    • 必须有 entry 入口
    • 必须有 output 出口

      1
      2
      3
      4
      5
      6
      7
      8
      9
      module.exports={
      entry:{
      app:'./src/main.js'
      },
      output:{
      path:'./dist',
      filename:'bundle.js'
      }
      }

      关于webpack中的loader

      1
      2
      3
      4
      5
      6
      7
      //所有的loader都要写在 module节点中
      module:{
      rules:[
      //匹配对应的文件后缀 使用对应的loader
      {test:/\.css$/,use:['name-loader','name-loader']}
      ]
      }
    • 处理样式

      • css
      • npm i style-loader css-loader -D
        1
        {test:/\.css$/,use:['style-loader','css-loader']}
      • sass
      • npm i sass-loader node-sass -D
        1
        {test:/\.scss$/,use:['style-loader','css-loader','sass-loader']}
      • 处理css中的路径
      • npm i url-loader file-loader -D
        1
        2
        // limit:小于1024的图片才会编码 name:文件名字 = 随机生成的哈希值的前七位 - 原文件名字 . 后缀
        {test:/\.(jpg|gif|png|bmp)$/,use:'url-loader?limit=1024&name=[hash:7]-[name].[ext]'}
  • 处理html文件

    1. npm i -D html-webpack-plugin
    2. 引入 const htmlWebpackPlugin=require('html-webpack-plugin')
    3. 在plugins节点中

      1
      2
      3
      4
      new htmlWebpackPlugin({
      template:path.join(__dirname,"./src/main.html"),//模版
      filename:"index.html" //文件名
      })
    4. 压缩 html

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      plugins:[
      new htmlWebpackPlugin({
      template:path.join(__dirname,"./src/main.html"),
      filename:"index.html",
      minify:{
      collapseWhitespace:true, // 合并空白字符
      removeComments:true, // 移除注释
      removeAttributeQuotes:true // 移除属性上的引号
      }
      })
      ]
  • 处理高级的JS语法

    1. 安装依赖包
      1. npm i babel-core babel-loader babel-plugin-transform-runtime -D
      2. npm i babel-preset-env babel-preset-stage-0 -D
        如果要编译react,就要在还要安装加入 "babel-preset-react"
    2. 配置loader

      1
      2
      //忽略的文件
      {test:/\.js$/,use:'babel-loader',exclude:/node_modules/}
    3. 配置 .babellrc 文件
      1.项目根目录创建.babelrc文件
      2.在文件中写入
      如果要编译react,就要在presets中加入 "react"

      1
      2
      3
      4
      {
      "presets":["env","stage-0"],
      "plugins":["transform-runtime"]
      }
  • 每次重构就删除dist目录

    1. npm i clean-webpack-plugin -D
    2. 引入const CleanWebpackPlugin =require('clean-webpack-plugin')
    3. plugins 节点中添加 new CleanWebpackPlugin(['dist'])
  • 分离第三方包
  • js

    1. entry节点

      • 先引入 webpack 包
        1
        2
        3
        4
        entry:{
        app:path.join(__dirname,"./src/js/main.js"),
        vendors:['jquery'] //和plugins节点中那么相同
        }
    2. plugins节点

      1
      2
      3
      4
      new webpack.optimeze.CommonsChunkPlugin({
      name:'vendors',
      filename:'vendors.js'
      })
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      //分离多个第三方包
      entry:{
      app:path.join(__dirname.'./src/js/main.js')
      React:['react'],
      ReactDOM:['react-dom']
      },
      output:{
      path:path.join(__dirname,'./dist'),
      filename:'[name].js'
      },
      plugins:[
      new webpack.optimeze.CommonsChunkPlugin({
      name:['react','react-dom'],
      filename:'[name]/[name].js'
      })
      ]
    3. 压缩JS

        1. 在plugins节点中添加
          1
          2
          3
          4
          5
          6
          7
          8
          new webpack.optimize.UglifyJsPlugin({
          commpress:{
          warnings:false //移除警告
          }
          }),
          new webpack.DefinePlugin({
          'process.env.NODE_ENV':'"production"' //进一步压缩JS 但效果不明显
          })
  • css

    1. npm i -D extract-text-webpack-plugin
    2. 导入插件 const extractTextWebpackPlugin=require('extract-text-webpack-plugin')
    3. module节点下的rules中修改 css 和 sass loader

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      {test:/\.css$/,use:extractTextWebpackPlugin.extract({
      fallback:'style-loader',
      use:'css-loader',
      publicPath:'../' //设置公共路径
      }),}
      {test:/\.scss$/,use:extractTextWebpackPlugin.extract({
      fallback:'style-loader',
      use:['css-loader','scss-loader'],
      publicPath:'../' // 设置公共路径
      }),}
    4. 在plugins节点中

      1
      new extractTextWebpackPlugin('css/styles.css') //抽取css
    5. 压缩抽取的css

      1. 安装依赖包 npm i optimize-css-assets-webpack-plugin -D
      2. 导入插件

        1
        const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
      3. 在plugins节点中 new optimizeCssAssetsWebpackPlugin()

webpack-dev-server 可以设置

1
"dev": "webpack-dev-server --port 1007 --hot --open --contentBase .\/src/ "
1
2
3
4
5
6
/*
--port: 设置的端口
--hot : 开启热根性
--open: 自动打开浏览器
--contentBase: 设置默认打开的文件
*/

react配置

react的配置

安装webpack npm i webpack -S

安装处理样式的loader

安装处理高级Js的loader

安装处理html的plugin

1. 一个插件可以压缩html代码

安装react

事件兼容问题

attachEvent 和 addEventListener

1
2
3
4
5
6
7
8
9
10
//attachEvent 是IE678支持的 而 addEventListener是其他大部分浏览器支持的
function addEvent(el,e,fn){
if(el.addEventListener){
el.addEventListener(e,fn)
}else if(el.attachEvent){
el.attachEvent("on"+e,fn)
}else{
el["on"+e]=fn
}
}

addEventListener(e,fn[,boolean])

可以两个必传的参数和一个可传参数

e:事件类型

fn:事件函数

boolean: 是否支持捕获 true就是捕获 false就是冒泡

冒泡和捕获

冒泡是从当前元素到父元素依次触发事件

1
2
3
4
5
6
7
8
9
var father=document.getElementById('#box')
var son = father.chlidren[0]
father.addEventListener('click',function(e){
console.log('father')
},false)
son.addEventListener('click',function(e){
console.log('son')
},false)
//点击son 会先打印 son 在打印 father

捕获是从父元素到当前元素依次触发事件

1
2
3
4
5
6
7
8
9
var father=document.getElementById('#box')
var son = father.chlidren[0]
father.addEventListener('click',function(e){
console.log('father')
},true)
son.addEventListener('click',function(e){
console.log('son')
},true)
//点击son 会先打印 father 在打印 son

捕获不常用 而冒泡最常见的就是在事件委托

事件委托只要是因为当页面重新渲染后,渲染的内容所有注册的事件都失效了,所有用到了事件委托

1
2
3
4
5
6
7
8
9
10
var father=document.getElementById('#box')
//点击father里面的div弹出 '你好'
father.addEventListener('click',function(e){
if(e.target.tagName==="DIV"){
window.alert('你好')
}
},false)
var son=document.creatElement('div')
son.innerHTML="点我"
father.appendChild(son);

browser-sync跨域

browser-sync跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//在客户端创建 `browser-sync.config.js` 文件
/**
* Module dependencies.
*/
var browserSync = require('browser-sync').create()
var proxy = require('http-proxy-middleware') // require('http-proxy-middleware');
/**
* Configure proxy middleware
*/
var jsonPlaceholderProxy = proxy('/api', {
target: 'http://127.0.0.1:3000',
changeOrigin: true, // for vhosted sites, changes host header to match to target's host
pathRewrite: {
'^/api': ''
},
logLevel: 'debug'
})
/**
* Add the proxy to browser-sync
*/
browserSync.init({
server: {
baseDir: './',
port: 5000,
middleware: [jsonPlaceholderProxy]
},
startPath: '/'
})
console.log('[DEMO] Server: listening on port 5000')