(1) 安装node(2) 安装git(3) 安装一款前端IDE --- 本人使用HBuilder
1.2 预备知识(1) nodejs基本命令
(2) 前端html+javascript+css基础知识
(3) react16相关概念和基本使用
(4) JSX语法
(5) ES6语法
二、react介绍
2.1 Virtual DOM虚拟DOM是React的基石:2.2 React组件
(1) 引入虚拟DOM主要是解决Web页面大量操作DOM的性能问题
(2) 在React中,应用程序在虚拟DOM上操作,这让React有了优化的机会
(3) 提供开发服务端应用、Web应用和手机端应用等平台一直的开发方式(1) 所谓组件,即封装起来的具有独立功能的UI部件,React并不是MVC的前端框架
对于React而言,则完全是一个新的思路,开发者从功能的角度出发,将UI分成不同的组件,每个组件都独立封装(2) 组件化开发特性:三、redux介绍1.可组合:一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部.通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件2.3 Jsx语法
2.可重用:每个组件都是具有独立功能的,它可以被使用在多个UI场景
3.可维护:每个小的组件仅仅包含自身的逻辑,更容易被理解和维护
4.可测试:因为每个组件都是独立的,那么对于各个组件分别测试显然要比对于整个UI进行测试容易的多Jsx语法是将HTML语言直接写在JavaScript语言之中,不加任何引号。它允许 HTML 与 JavaScript的混写。2.4 单向数据流
JSX的特点: 1.类XML语法容易接受,结构清晰
2.增强JS语义
3.抽象程度高,屏蔽DOM操作,跨平台
4.代码模块化,组件化,使得每一个组件维护自己的UIReact是单向数据流,数据主要从父节点传递到子节点(通过props), 如果顶层(父级)的某个props改变了,React会重渲染所有的子节点。
3.1 传统MVC传统MVC强调分层开发,model(M)-模型层,view(V)-视图层,controller(C)-控制层,在传统MVC框架中,通常使用双向绑定的方式来将Model的数据展现到View。当Model中的数据发生变化时,一个或多个View会发生变化;当View接受了用户输入时,Model中的数据则会发生变化。如下图所示, Model 和 View 之间的关系错综复杂,导致出现问题时很难调试;实现新功能时也需要时刻注意代码是否会产生副作用
四、react+redux整合开发store(存放状态) -> container(显示状态) -> reducer (处理动作)-> store
3.2 Redux三个概念1.store:是应用的状态管理中心,保存着是应用的状态(state),当收到状态的更新时,会触发视觉组件进行更新。
2.container:是视觉组件的容器,负责把传入的状态变量渲染成视觉组件,在浏览器显示出来。
3.reducer:是动作(action)的处理中心, 负责处理各种动作并产生新的状态(state),返回给store。
//action方法名和actionType常量
export const ADD_BOOK = 'ADD_BOOK'; //添加书籍操作
export const DELETE_BOOK = 'DELETE_BOOK';//删除书籍操作
export const QUERY_BOOK = 'QUERY_BOOK';//查询书籍操作
export const CHECK_ADD = 'CHECK_ADD';//选择删除的记录操作
export const CHECK_REMOVE = 'CHECK_REMOVE';//取消删除操作
export const CHECK_CLEAR = 'CHECK_ALL';//全选
export const CHECK_CLEAR = 'CHECK_CLEAR';//取消全选
import { ADD_BOOK, DELETE_BOOK, QUERY_BOOK,CHECK_ADD,CHECK_REMOVE,CHECK_CLEAR,CHECK_ALL } from "../constants/actionTypes"
/**
* receiveData和fetchData是绑定的,fetchData是异步action去获取public目录下的data.json
* 然后发送dispatcher去执行receiveData,最好返回异步加载的data数据
*/
export const receiveData = data => ({ type: 'RECEIVE_DATA', data: data });
export const fetchData = () => {
return dispatch => {
fetch('/data.json')
.then(res => res.json())
.then(json => dispatch(receiveData(json)));
};
};
/**
* addBook新增数据action
*/
export function addBook(book) {
return {
type: ADD_BOOK,
book
}
}
/**
* deleteBook根据ids删除数据
*/
export function deleteBook(ids) {
return {
type: DELETE_BOOK,
ids
}
}
/**
* queryBook根据书籍名称查询列表
*/
export function queryBook(bookName) {
return {
type: QUERY_BOOK,
bookName
}
}
/**
* checkAdd选择删除的记录id,添加到待删除数组列表
*/
export function checkAdd(id) {
return {
type: CHECK_ADD,
id
}
}
/**
* checkRemove从待删除数组列表中取消删除的记录id
*/
export function checkRemove(id) {
return {
type: CHECK_REMOVE,
id
}
}
/**
* checkClear将待删除数组列表清空
*/
export function checkClear() {
return {
type: CHECK_REMOVE
}
}
/**
* 将记录id全部添加到待删除列表
*/
export function checkAll(ids) {
return {
type: CHECK_ALL,
ids
}
}
import { CHECK_ADD ,CHECK_REMOVE,CHECK_CLEAR,CHECK_ALL} from "../constants/actionTypes"
/**
* 待删除列表state
* CHECK_ADD:执行添加待删除记录
* CHECK_REMOVE:执行移除待删除记录
* CHECK_ALL:全选进入待删除记录
* CHECK_CLEAR:清空待删除记录
*/
export default function bookDeleteState(state = [], action) {
switch(action.type) {
case CHECK_ADD:
return [...state,action.id];
case CHECK_REMOVE:{
let state_= [];
let j=0;
for(var i=0;i<state.length;i++){
if(state != action.id){
state_[j++]=state
}
}
return state_; }
case CHECK_ALL:
return [...state,action.ids];
case CHECK_CLEAR:
return [];
default:
return state;
}
}
import { QUERY_BOOK } from "../constants/actionTypes"
/**
* 维护查询条件的state
* QUERY_BOOK:设置查询条件
*/
export default function bookQueryState(state = "", action) {
switch(action.type) {
case QUERY_BOOK:
return action.bookName;
default:
return state;
}
}
import { ADD_BOOK, DELETE_BOOK } from "../constants/actionTypes"
/**
* 维护数据列表的State
* ADD_BOOK:执行新增书籍操作
* DELETE_BOOK:执行删除书籍的操作
* RECEIVE_DATA:异步请求,返回查询到的列表
*/
export default function bookListState(state = [], action) {
switch(action.type) {
case ADD_BOOK:
return [...state, action.book];
case DELETE_BOOK:{
let state_= [];
let j=0;
for(var i=0;i<state.length;i++){
if(action.ids.indexOf(state.id) == -1){
state_[j++]=state
}
}
return state_;
}
case "RECEIVE_DATA":
return action.data;
default:
return state;
}
}
import { combineReducers } from 'redux';
import bookListState from './bookListState';
import bookQueryState from './bookQueryState';
import bookDeleteState from './bookDeleteState';
const rootReducer = combineReducers({
bookListState,
bookQueryState,
bookDeleteState
});
export default rootReducer;
import React, { Component } from 'react';
import { addBook, queryBook,deleteBook,checkAdd,checkRemove,checkClear,checkAll,fetchData } from "./actions/action"
import { connect } from 'react-redux';
import BookItem from "./components/BookItem";
import logo from './logo.svg';
//App作为容器组件
class App extends Component {
constructor(props) {
super(props);
this.saveBook = this.saveBook.bind(this);
this.queryBook_ = this.queryBook_.bind(this);
}
componentDidMount() {
this.props.searchData();
}
saveBook(){
const book = {
id:this.id.value,
name:this.name.value,
author:this.author.value,
price:this.price.value
};
this.props.saveBook(book)
}
queryBook_(name){
if(name == "ALL"){
this.props.queryBook("");
}else{
this.props.queryBook(this.search.value);
}
}
render() {
let { dispatch,bookList,checkIds,checkAdd,checkRemove,deleteBook } = this.props;
return (
....
<form className="navbar-form navbar-left">
<div className="form-group">
<input type="text" ref={(search)=>{this.search = search}} className="form-control" placeholder="Search" />
</div>
<button type="button" className="btn btn-default" onClick={this.queryBook_}>Submit</button>
</form>
....
<button type="button" onClick={()=>{ this.id.value="";this.name.value="";this.author.value="";this.price.value="" }} className="btn btn-default" data-toggle="modal" data-target="#myModal">新增</button>
<button type="button" className="btn btn-default" onClick={this.queryBook_.bind(this,"ALL")}>刷新</button>
<button type="button" className="btn btn-default" onClick={()=>{ deleteBook(checkIds) }}>删除</button>
....
<table className="table table-striped">
<thead>
<th></th>
<th>#</th>
<th>书名</th>
<th>作者</th>
<th>价格</th>
</thead>
<tbody>
{ bookList.map(item => <BookItem item={item} checkAdd={checkAdd} checkRemove={checkRemove}/>) }
</tbody>
</table>
....
<form className="form-horizontal" role="form">
<input type="text" ref={(id) => {this.id = id}} className="form-control" id="id" placeholder="请输入id" />
<input type="text" ref={(name) => {this.name = name}} className="form-control" id="lastname" placeholder="请输入书名" />
<input type="text" ref={(author) => {this.author = author}} className="form-control" id="lastname" placeholder="请输入作者" />
<input type="number" ref={(price) => {this.price = price}} className="form-control" id="lastname" placeholder="请输入价格" />
<button type="button" className="btn btn-primary" data-dismiss="modal" onClick={this.saveBook}>提交保存</button>
</form>
....
);
}
}
//条件过滤
const bookFilter = (bookList ,filter)=>{
console.log(filter);
return bookList.filter(item => item.name.indexOf(filter)!=-1);
}
//绑定state数据到容器组件的prop属性
const mapStateToProps = (state) => {
return {
//state.bookListState 数据列表
//state.bookQueryState 过滤条件
bookList: bookFilter(state.bookListState,state.bookQueryState),
checkIds: state.bookDeleteState
}
};
//绑定dispatcher到容器组件的prop属性
const mapDispatchToProps = (dispatch,ownProps) => {
return {
searchData:()=>{
dispatch(fetchData());
},
saveBook:(book)=>{
dispatch(addBook(book));
},
queryBook:(value)=>{
dispatch(queryBook(value));
},
deleteBook:(ids)=>{
dispatch(deleteBook(ids));
},
checkAdd: (id) => {
dispatch(checkAdd(id));
},
checkRemove: (id) => {
dispatch(checkRemove(id+""));
},
checkClear: () => {
dispatch(checkClear());
},
checkAll: () => {
dispatch(checkAll());
}
};
}
//将绑定后的prop属性连接到容器组件
export default connect(mapStateToProps,mapDispatchToProps)(App);
import React, {
Component
} from 'react';
class BookItem extends Component {
constructor(props) {
super(props);
this.checkID=this.checkID.bind(this);
}
checkID(event){
var flag = event.target.checked;
if(flag){
this.props.checkAdd(event.target.value);
}else{
this.props.checkRemove(event.target.value);
}
}
render() {
let {item} = this.props;
return(
<tr>
<td><input type="checkbox" value={item.id} onClick={this.checkID}/></td>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.author}</td>
<td>{item.price}</td>
</tr>
)
};
}
export default BookItem;
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) | 黑马程序员IT技术论坛 X3.2 |