原课程链接->React16.4开发简书项目从零基础入门到实战
PWA:progressive web application
大致意思就是通过写网页的方式来写一下手机APP的应用
// 4. 引入react -> 编译jsx语法
import React from 'react';
import ReactDOM from 'react-dom';
// 1. 引入App组件
// 注意:如果我们要使用自己创建的组件,组件和标签开头一定以大写字母开头,否则不支持识别,小写的标签一般都是h5标签
import App from './App';
// 2. ReactDOM.render:将某个组件挂载到某个节点上
ReactDOM.render(
<React.StrictMode>
{/* 3. 是一种JSX语法:通过标签,
而不是直接写App引用。 但是这种语法需要react去编译,
所以第一行引入react */}
<App />
</React.StrictMode>,
document.getElementById('root')
);
import React from 'react';
function App() {
return (
// 5. 这个div也是一种JSX语法,所以需要引入React
<div className="App">
hello
</div>
);
}
export default App;
<body>
<!-- 容错代码,如果未开启javascript,那么提醒用户 -->
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
import React from 'react';
function App() {
return (
// 正确
<div>
<div>b</div>
</div>
// 错误
<div>a</div>
<div>b</div>
);
}
export default App;
Fragment
import React, { Fragment } from 'react';
function App() {
return (
// 正确
<Fragment>
<div>b</div>
</Fragment>
);
}
export default App;
import React, { Component, Fragment } from 'react';
class TodoList extends Component {
// 当我们去使用组件的时候,constructor是优于其他任何函数,会自动的,最先被执行的函数
constructor(props){
// 调用一次父类(Component)的构造函数
super(props);
// react中定义数据,定义在状态里面也就是state
// 第1步:设置inputValue初始值
this.state = {
inputValue: '',
list: [],
}
}
render() {
return (
// 正确
<Fragment>
<div>
{/* 当state中数据改变,input输入框中的内容同步改变,这就是响应式,也是react名字的起源 */}
<input
// 第2步:onChange监听
onChange={this.handleInputChange.bind(this)}
// 第4步:inputValue实时更新
value={this.state.inputValue}/>
<button>提交</button>
</div>
<ul>
<li>learn hard</li>
<li>study up</li>
</ul>
</Fragment>
);
}
handleInputChange(e){
// e.target指的是dom结点
console.log(e.target.value);
// 如果input上 不利用bind改变this指向,那么这个this应为undefined
console.log(this);
// 第3步:state中数据改变
this.setState({
inputValue: e.target.value,
})
}
}
export default TodoList;
第1步:
this.state = {
inputValue: '',
list: [],
}
第2步:渲染list数组
<ul>
{
this.state.list.map((item, index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
第3步:提交按钮绑定事件-改变this.state.list
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
第4步:
handleBtnClick(e){
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: '',
})
}
第1步:给li绑定事件,点击li传递index给函数
<ul>
{
this.state.list.map((item, index)=>{
return (
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
>
{item}
</li>
)
})
}
</ul>
第2步:删除方法
handleItemDelete(index){
let list = [...this.state.list];
list.splice(index, 1);
this.setState({
list,
})
}
this.state.a = 'a';
{/* 这是多行注释 */}
{// 这是单行注释 }
.input{
border: 1px solid red;
}
第1步:
import './style.css';
第2步:注意是className不是class,因为js文件中class是有其他意义的
<input className='input'/>
hello
后,点击提交,出现样式为大大的hello,而不是hello
<ul>
{
this.state.list.map((item, index)=>{
return (
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
// 可以将输入值作为html输出,其中第一个括号,表示{}中是JS表达式,{}中的{}代表JS表达式是一个对象,对象值是{__html: item},item表示遍历list的值
dangerouslySetInnerHTML={{__html: item}}
>
</li>
)
})
}
</ul>
第1步:
{/* label作用就是可以扩大点击区域,注意:不使用for属性而是使用htmlFor for在js中有单独含义*/}
<label htmlFor="insertArea">输入内容</label>
第2步:input添加id
<input id="insertArea"/>
父组件传值:
<TodoItem content={item}/>
子组件接收:
<div>
{this.props.content}
</div>
将父组件的方法传递给子组件:
注意:必须利用bind强制改变this指向父组件,否组子组件的this找不到这个方法
<TodoItem
deleteItem={this.handleItemDelete.bind(this)}
/>
子组件接收:
handleClick(){
this.props.deleteItem(this.props.index);
}
原:
this.props.deleteItem(this.props.index);
优化:
const { deleteItem, index } = this.props;
deleteItem( index);
原:
import './style.css';
import TodoItem from './TodoItem';
优化:
import TodoItem from './TodoItem';
import './style.css';
原来的方法:
<div onClick={this.handleClick.bind(this)}>
{this.props.content}
</div>
优化的方法:在constructor中改变
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
}
<input
className='input'
onChange={this.handleInputChange}
value={this.state.inputValue}
id="insertArea"
/>
<ul>
{ this.getTodoItem() }
</ul>
getTodoItem(){
return (
this.state.list.map((item, index)=>{
return (
<div>
<TodoItem
content={item}
index={index}
deleteItem={this.handleItemDelete}
/>
</div>
)
})
)
}
之前的写法:
this.setState({
inputValue: e.target.value,
})
现在的写法:
const value = e.target.value
this.setState(() => {
return {
inputValue: value,
}
})
用ES6语法优化:
const value = e.target.value
//箭头后面的括号其实是简化了return的写法,括号中的内容就是return返回的内容
this.setState(() => ({
inputValue: value,
}
));
this.setState((prevState) => ({
// list: [...this.state.list, this.state.inputValue],
list: [...prevState.list, prevState.inputValue],
inputValue: '',
}));
<TodoItem
key={index}
/>
this.state.list.map((item, index)=>{
return (
//放在独立子组件最外层div上:正确
<div key={index}>
//放在TodoItem上:错误
<TodoItem key={index}/>
</div>
)
})