前面有篇就是
[email protected] +babel-loader 的配置我就不说,关键是 配置要制定版本,否则会出现不匹配的情况,
这也是大家看爱前端react 课程苦恼的地方,我给解决了!
链接地址:
我理清下思路,因为
jsx 语法需要通过babel编译, 既然需要通过babel 编译, 干嘛不顺便 让babel 编译es6呢 ,
既然用babel 干嘛不用webpack 来管理babel 呢
下面这章图,我随手画的!
我们不着急,我们先把两个最重要的文件拿过来!
package.json
{
"name": "hh",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"react-redux": "^5.1.1",
"redux": "^4.0.1",
"webpack": "^3.6.0"
},
"dependencies": {}
}
webpack.config.js
const path = require('path');
module.exports = {
entry: "./app/main.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "all.js"
},
watch:true,
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/ ,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015','react'],
plugins:["transform-object-rest-spread"]
}
}
}
]
}
}
通过上面的两个文件我们就可以很轻松的配置好了
webpack 版本的运行环境!当然我这个配置也装好了redux + react-redux
先看张结构图:
webpack 会编译 main.js 到all.js 中,然后index.html 会引用 all.js 这是基本逻辑,所以下面我们就重点关注
main.js 和App.js 这是我们的重点逻辑,也是本篇博客的重点!
main.js
import React from "react";
import {render} from "react-dom";
import {createStore} from 'redux';
//引入组件
import App from "./App.js";
// import News from './News.js';
//使用、挂载组件,两个参数
//第一个参数是jsx语法
//第二个参数表示组件挂在哪里
import reducer from './reducer.js';
import {Provider} from 'react-redux';
let store = createStore(reducer);
render(
<Provider store = {store}>
<App></App>
</Provider>
,
document.getElementById("app-container")
);
官方的解释:
Provider自定义组件:
Makes the Redux store available to the connect() calls in the component hierarchy below。
这个Provider组件使得它内部的自定义组件可以使用connect()函数。
Normally, you can’t use connect() without wrapping a parent or ancestor component in <Provider>
通常的,你不能在没有Provider父亲或者组件的情况下,使用connect()函数。
属性store (Redux Store): APP中唯一的那个store
解释:也就是说,只要你用 <Provider> 包裹的组件,都可以使用全局的store 里的一些逻辑
(1, 得到 全局的数据state 2, 可以 向 store 发送指令),先解释这么多,会头画个图,你就明白了!
let store = createStore(reducer);
这句话就是创建个全局的store 对象!
<Provider store = {store}>
<App></App>
</Provider>
注意这里,要将store 作为属性传递给 Provider 这是人家要求的!
reducer 是啥,它是一个纯函数,根据指令对全局数据进行处理!
reducer.js
export default (state , action) => {
if(state == undefined){
return {"v" : 0 , "a" : 1 , "b" : 2};
}
switch(action.type){
case "ZENGJIA":
return {...state , "v" : state.v + 1};
break;
case "JIANSHAO":
return {...state , "v" : state.v - 1};
break;
case "ZENGJIANUMBER" :
return {...state , "v" : state.v + action.number};
break;
}
return state;
}
在这个纯函数中, 有两个参数! state ,action
state 是全局的数据 action 就是指令对象 里面包含一个type 属性!
所以说 redux 是一个可预期的数据流动!
2, 我们来看App 组件
import React , {Component} from "react";
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
import * as actions from "./actions.js";
class App extends Component{
render(){
return (
<div>
<button onClick = {this.props.actions.jianshao}>+</button>
{this.props.v}
<button onClick = {this.props.actions.zengjia}>-</button>
</div>
);
}
}
export default connect(
(state) => {
return {
v : state.v
}
},
(dispatch) => {
return {
actions : bindActionCreators(actions,dispatch)
}
}
)(App);
connect 方法的意义
Connects a React component to a Redux store.
将React组件和Redux的store进行连接。
connect providing a convenient API for the most common use cases.
connect提供了一个方便的API能够适应绝大多数工作。
It does not modify the component class passed to it; instead, it returns a new, connected component class for you to use
它没有更改你传进来的类,返回会返回一个已经连接好的新类。
解释:1, 在provider 中我们将store 传递进来了,那么这里就可以通过connect 连接!
连接后,我们能得到两大好处, 1 得到全局的数据 state
2, 得到一个带发送指令的 对象!
v 会自动和属性绑定
actions 里可以发送各种指令
当 数据state 变化时, 视图会自动更新!
我们来看下 actions.js 是啥!
actions.js
1,纯指令标准方式
2, 得到并且修改成带 发送器的指令方式
import {bindActionCreators} from "redux";
import * as actions from "./actions.js";
那么指令发出后 ,谁来处理呢? 答案就是reducer 那个纯函数!
到此redux 基本结构就这样了!
我画个图吧:
总之, store 将数据,和发送 变化的指令对象,都交给了组件
组件 根据数据显示界面,可以通过 指令对象发送更改命令
reducer 接受命令处理后返回新的数据对象
而新的数据对象会重新 注入给组件,组件视图会跟着发生变化