今日总结
课上提到的内容
1. 讲了react要学习的内容提纲
- react 基础,JSX语法,插件
- react-router 路由
- redux 状态管理
- ant-ui 组件库(自己学习)
2.基础知识
-
react是什么?
帮助构建页面的js库
-
组件开发方式
类组件:有状态(state)和完整的生命周期
和函数式:只做展示(hook自有状态)
作业
1.大家根据我们今天讲到的内容,结合自己的学习,写一篇关于jsx的使用,组件相关的总结
- JSX是JavaScript的语法扩展,具有JavaScript的全部功能
const element = <h1>Hello, world!</h1>;
- 为什么使用JSX?
- React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合
- React 并没有采用将标记与逻辑进行分离到不同文件这种人为地分离方式,而是通过将二者共同存放在称之为“组件”的松散耦合单元之中,来实现关注点分离
- 在JSX中嵌入表达式
const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;
ReactDOM.render(
element,
document.getElementById('root')
);
//在JSX语法中,你可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2,user.firstName或 formatName(user)都是有效的JavaScript表达式
- 为了便于阅读,我们会将 JSX 拆分为多行
- JSX 也是一个表达式
- 你可以在 if 语句和 for 循环的代码块中使用 JSX,将 JSX 赋值给变量,把 JSX 当作参数传入,以及从函数中返回 JSX
- JSX 特定属性
- 你可以通过使用引号,来将属性值指定为字符串字面量,也可以使用大括号,来在属性值中插入一个 JavaScript 表达式
const element = <div tabIndex="0"></div>;
const element = <img src={user.avatarUrl}></img>;
- 使用 JSX 指定子元素
- 假如一个标签里面没有内容,你可以使用 /> 来闭合标签,就像 XML 语法一样:
const element = <img src={user.avatarUrl} />;
- 假如一个标签里面没有内容,你可以使用 /> 来闭合标签,就像 XML 语法一样:
- JSX 标签里能够包含很多子元素:
- JSX 防止注入攻击
- JSX 表示对象
- Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用,以下两种示例代码完全等效:
const element = (
<h1 className="greeting">
Hello, world!
</h1>
);
const element = React.createElement(
'h1',
{className: 'greeting'},
'Hello, world!'
);
- react生命周期
组件传给ReactDom.render()->调用组件的构造函数->this.state初始化->React调用组件的render()方法->组件插入DOM中后调用ComponentDidMount()->当组件被移除的时候,React 就会调用 componentWillUnmount() - 正确使用State
-
不要直接修改State,而是应该使用setState,构造函数是唯一可以给this.state赋值的地方
-
State的更新可能是异步的,出于性能考虑,React 可能会把多个 setState() 调用合并成一个调用。
- 因为 this.props 和 this.state 可能会异步更新,所以你不要依赖他们的值来更新下一个状态。
- 例如,此代码可能会无法更新计数器:
// Wrong this.setState({ counter: this.state.counter + this.props.increment, });
- 要解决这个问题,可以让 setState() 接收一个函数而不是一个对象。这个函数用上一个 state 作为第一个参数,将此次更新被应用时的 props 做为第二个参数:
// Correct this.setState((state, props) => ({ counter: state.counter + props.increment }));
- State 的更新会被合并
2.在201907-B-Train项目,自己的目录下,用create-react-app创建一个项目,项目名称叫做react-demo
3.可以使用这个 codesandbox.io去做一些在线开发验证
4.React.Children(demo5)
- React.Children 提供了用于处理 this.props.children 不透明数据结构的实用方法
- this.props.children有三种可能性。如果组件没有子节点,则值为undefined; 如果单个子节点,一个对象; 如果有多个子节点,则为数组
5.PropTypes属性(demo6)
- 定义title应该是个字符串
class MyTitle extends React.Component {
static propTypes = {
title: PropTypes.string.isRequired,
}
render() {
return <h1> {this.props.title} </h1>;
}
static defaultProps = {//给title设置默认值
title: 'Hello World',
}
}
6.React.createRef,ref(demo7)
- 有时您需要引用组件中的DOM节点。React为您提供了ref将DOM节点附加到由其创建的实例的属性React.createRef()
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.myTextInput = React.createRef();
this.handleClick = this.handleClick.bind(this)
}
handleClick() {
this.myTextInput.current.focus();
}
render() {
return (
<div>
<input type="text" ref={this.myTextInput} />
<input type="button" value="Focus the text input" onClick={this.handleClick} />
</div>
);
}
}
ReactDOM.render(
<MyComponent />,
document.getElementById('example')
);
}
7.this.state(demo8)
- React将组件视为状态机,并用于this.state保存组件的状态,this.setState()以更新this.state和重新呈现组件
8.react生命周期
- componentWillMount():在初始渲染发生之前触发一次。连接消息监听器的好地方。this.setState在这里不起作用。
- componentDidMount():在初始渲染发生后触发一次。可以用this.getDOMNode()。
- componentWillUpdate(object nextProps,object nextState):在组件对DOM进行更新后触发。可以this.getDOMNode()用于更新。
- componentDidUpdate(object prevProps,object prevState):在将组件的更新刷新到DOM之后立即调用。初始渲染不会调用此方法。将此作为在更新组件时对DOM进行操作的机会。
- componentWillUnmount():在从DOM卸载组件之前立即触发。删除消息监听器或一般清理的好地方。
- componentWillReceiveProps(object nextProps):在组件接收新props时触发。你可能想要this.setState依赖props。
- shouldComponentUpdate(object nextProps,object nextState):在收到新的props或state时呈现之前触发。return false如果你知道不需要更新。
今天做了什么
1.写了日志
2.按照官网写了井字棋的小游戏
3.学习理解了阮一峰react的11个demo
4.官网看到了核心概念的第7条条件渲染
今日心得
今天通过老师讲解大致react学习的大纲,通过react官网逐步去适应了react的JSX编写规则,通过实践井字棋游戏,也理解了react父子组件的传参,只能通过props传参,state 和 props 之间最重要的区别是:props 由父组件传入,而 state 由组件本身管理。组件不能修改 props,但它可以修改state,state只能通过setState来修改等基础知识。
做了什么
- 主要课上学习了react的条件渲染、列表渲染、表单、ref、状态提升等。
- 做了todo-list demo,实现了react的组件嵌套,父子组件的传值,顶层组件数据控制,状态管理等
有什么收获
- 写demo的时候遇到了很多问题,比如我想通过子组件去处理父组件传过来的props但是,在子组件中处理父组件的数据,逻辑非常混论,并且状态更新难以管理,后来,直接在父组件上面进行数据的绑定,函数的分装,然后通过事件传递给子组件,然后执行,完成状态管理
- 在处理事件的时候,遇到了事件this绑定的问题,有三种方法可以实现,constuctor中事件.bind(this)、箭头函数和传递的时候.bind(this)
- 还遇到了元事件e的隐式和显示传递问题,()=>{this.handle(item)}不传递e,(e)=>{this.handle(e)}
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// 类组件
// class Square extends React.Component{
// render(){
// return (
// <button
// className="square"
// onClick={()=>{this.props.onClick()}}
// >
// {this.props.value}
// </button>
// );
// }
// }
// 等价于函数组件
function Square(props){
console.log(props)
return (
<button
className="square"
onClick={props.onClick}
// onClick={props.onCd}
>
{props.value}
</button>
);
}
function calculateWinner(squares) {
const lines = [
[0, 1, 2],//[x,o,x,o,x,o,null,x,null,null]
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}
class Board extends React.Component{
// constructor(props){
// super(props);
// this.state = {
// squares:Array(9).fill(null),
// xIsNext:true,
// }
// }
// handleClick=(i)=>{
// const squares = this.state.squares.slice();
// if (calculateWinner(squares) || squares[i]) {
// return;
// }
// squares[i]= this.state.xIsNext ? 'X' : 'O';
// this.setState({
// squares:squares,
// xIsNext:!this.state.xIsNext,
// });
// }
renderSquire(i){
console.log(this.props);
return (
<Square
// value={this.state.squares[i]}
// onClick={()=>this.handleClick(i)}
value={this.props.squares[i]}
onClick={()=>this.props.onClick(i)}
// onClick={()=>this.props.onCd()}
/>);
}
render(){
// const winner = calculateWinner(this.state.squares);
// let status;
// if(winner){
// status="Winner:"+winner;
// }else{
// status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
// }
// const status = 'Next player:'+ (this.state.xIsNext ? 'X' : 'O');
return (
<div>
{/* <div className="status">{status}</div> */}
<div className="board-row">
{this.renderSquire(0)}
{this.renderSquire(1)}
{this.renderSquire(2)}
</div>
<div className="board-row">
{this.renderSquire(3)}
{this.renderSquire(4)}
{this.renderSquire(5)}
</div>
<div className="board-row">
{this.renderSquire(6)}
{this.renderSquire(7)}
{this.renderSquire(8)}
</div>
</div>
);
}
}
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
history: [{
squares: Array(9).fill(null),
}],
stepNumber:0,
xIsNext: true,
};
console.log(props)
}
handleClick(i){
// const history = this.state.history;
const history = this.state.history.slice(0, this.state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice();
// const squares = this.state.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i]= this.state.xIsNext ? 'X' : 'O';
this.setState({
history: history.concat([{
squares: squares,
}]),
stepNumber:history.length,
xIsNext:!this.state.xIsNext,
});
}
jumpTo(step){
this.setState({
stepNumber:step,
xIsNext:(step % 2)===0,
})
}
render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);
const moves = history.map((step, move) => {
const desc = move ?
'Go to move #' + move :
'Go to game start';
return (
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
);
});
let status;
if(winner){
status="Winner: "+winner;
}else{
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={i =>this.handleClick(i)}
// onCd={()=>this.l(1)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
学习内容
1. react-router学习
2. router配置
3. 路由匹配原理
4. 默认路由
练习内容
完成路由切换的demo
遇到的问题?
未完成用a标签实现路由跳转
代码:
import React from 'react';
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import Introduction from './Introduction'
import Introduction1 from './Introduction1'
import Basis from './Basis'
import './App.css'
function App(){
return (
<Router>
<div className="app">
<ul className="menu">
<li>
<Link activeClassName="active" to="/">Introduction</Link>
</li>
<li>
<Link activeClassName="active" to="/Introduction1">1.简介</Link>
</li>
<li>
<Link to="/basis">2.基础</Link>
<ul>
<li>
<Link>2.1路由配置</Link>
</li>
<li>
<Link>2.2路由匹配原理</Link>
</li>
<li>
<Link>2.3History</Link>
</li>
<li>
<Link>2.4默认路由</Link>
</li>
</ul>
</li>
<li>
<Link to="/">3.高级用法</Link>
<ul>
<li>
<Link>2.1路由配置</Link>
</li>
<li>
<Link>2.2路由匹配原理</Link>
</li>
<li>
<Link>2.3History</Link>
</li>
<li>
<Link>2.4默认路由</Link>
</li>
</ul>
</li>
<li>
<Link to="/">4.升级指南</Link>
</li>
<li>
<Link to="/">5.排错</Link>
</li>
<li>
<Link to="/">6.Api文档</Link>
</li>
<li>
<Link to="/">7.词汇表</Link>
</li>
</ul>
<div className="content">
<Route exact path="/" component={Introduction} />
<Route exact path="/Introduction1" component={Introduction1} />
<Route exact path="/Basis" component={Basis} />
</div>
</div>
</Router>
)
}
export default App
学习内容
redux基础学习
Action,Reducer,Store,数据流的学习
- action 只是一个带有type属性的普通对象
- store 是一个用于改变state状态的对象
storeChange(){
this.setState(store.getState())
}
store.subscribe(this.storeChange) //订阅Redux的状态
store.dispatch(action)//触发一次订阅
- reducer是一个纯函数,接受上一个state和action作为参数,并返回下一个要更新的state给store,reducer里面的内容主要是通过action的type去对下一个state进行限定和修改,但是不更新
今日总结
1. 今天做了什么
- 今天主要做了表单的页面部分内容
- 是通过使用antd插件进行构建的
2. 学习
- 学习了antd的一些基本使用方法
安装,引入,按模块导入,导入css文件
3. 收获
- 最后引入的样式很完美,但是因为对这个库根本不熟悉所以,中间的数据不知道怎么传递,最后以失败告终,从而自己的进度就拉下了,
- 感悟和收获:以后做项目,一定先写逻辑再写页面样式,这样做有很多好处,交互的逻辑先写完,样式可以慢慢加,但写样式,如果逻辑加不进去可能导致重写。
明日计划
继续redux学习
image.png
image.png
今日总结
1.做了什么?
- 重写了项目的交互逻辑
- 重写了项目的页面
- 明白了redux的数据状态管理:component创建action,通过store.dispatch(action)传递给store,store接受到action后先不处理,而是将action当参数传递给reducer,reducer根据传来的action,将state做相应的更新以后,将新的state返还给store,store接受到新的state后更新全局的state,store可以通过store.subscribe订阅store的改变
2.学了什么
- 上面描述的redux的工作机制
- 对selet和form等使用和学习
3.明日计划
继续完善项目的校验功能
今日总结
1.做了什么?
- 用mockjs模拟了后台数据,并且通过axios能获取到,通过里面的参数也可以向后台传递参数
import Mock from 'mockjs'//导入mockjs模块
Mock.mock('/data','get',(options)=>{//options 为axios传递给mock的数据,return的对象为mock给axios的body内数据内容
console.log(options);
return{
'list|1':[{
'id|+1': 1,
'selectValue':null,
'educationValue':null,
'startTime':null,
'endTime':null,
'firstMajor':null,
'firstMajorGPA':null,
'secondMajor':null,
'secondMajorGPA':null
}]
}
})
- 通过for...of加switch做提交前的校验
for(let i of list) {
for(let item of Object.entries(i)){
let [key,value] = item;
console.log(key);
switch (key){
case "id":
value===null?alert("id未填写"):console.log(value);
break
case "selectValue":
value === null ? alert("学校未填写") : console.log(value);
break
case "educationValue":
value === null ? alert("学历未填写") : console.log(value);
break
case "startTime":
value === null ? alert("起始时间未填写") : console.log(value);
break
case "endTime" :
value === null ? alert("终止时间未填写") : console.log(value);
break
case "firstMajor":
value === null ? alert("第一学位未填写") : console.log(value);
break
case "firstMajorGPA":
value === null ? alert("第一学位GPA未填写") : console.log(value);
break
case "secondMajor":
value === null ? alert("第二学位未填写") : console.log(value);
break
case "secondMajorGPA":
value === null ? alert("第二学位GPA未填写") : console.log(value);
break
default:
console.log("success");
}
}
}
2.学了什么
- mockjs和axios的简单使用
- switch的使用
- for...of的使用
3.明日计划
继续完善表单的前台,后端校验和提交前的校验等功能,将代码分块
今日总结
1.做了什么?
- 继续完善表单
- 将代码分块,将所有的action操作全部提取出来,放在actionTypes.js里面,将action提取出来放在actionCreators.js
- 对表单的数据和UI做了双向绑定
- 复习了Generator函数,看来一部分redux-saga内容
2.遇到问题
- 几个需要注意的地方
- 刚开始的input监控事件是用onBlur事件,但是这个不能用于数据的双向绑定,因为它不能实时更新input框里面的内容,所以会造成input框数据第一次可以输入,但是第二次输入不了的情况,因为第一次的值绑定了以后,输入框再要改变必须要onBlur才行,而输入内容的时候是onFocus
- 初始化数据,包括后面新增数据项的初始化数据尽量不要设置成null,而是缓存空字符串,要不然会有警告
3.明日计划
- 继续学习redux-saga内容
今日总结
做了什么
- 对redux-saga基础进行学习
- 对angular1.x进行学习,学习了指令,表达式,模型,$scope,控制器和过滤器等
遇到什么问题
- redux-saga文档给的例子,只有分支上的可以跑起来,master分支上的会报错
- angular1.x没有官方文档,只能通过菜鸟教程去学习,上面给的例子很简单,导致复杂应用的开发的话没什么借鉴意义
有哪些收获
- redux-saga还很迷,后面还需要好好重新学习,感受了老框架angular初代版本的魅力,觉得学习和使用的成本很低,还挺实用的
明日计划
- 开始hzero前端开发的学习
网友评论