React 学习笔记
第一部分,腾讯课堂react入门课程
课程地址
React第一篇 npm、yarn介绍
React第二篇 React语法
React第三篇 单页应用开发
React第四篇 路由&Hooks
React第五篇 综合应用(登录+列表)
第二部分,Redux课程
课程地址
React第六篇 Redux
React第七篇 React Redux
主流前端框架:
- vue(mvvm)
- react (mvvm)
- angular(mvc)
1.React介绍
特性
- 声明式:如声明变量,在react中可以声明组件、变量等
- 组件化
- 独立的模块开发成小组件,在不同的页面进行嵌套,类似堆积木的方式
- 任何大的项目都可以拆分成无数小的项目,小的项目可以拆分成一个个小零件
- 将积木拼在一起堆成一个大的项目
- 模块化和组件化的区别:==模块化相对于功能(如支付,订单做成独立的功能), 组件化侧重于UI==
- 灵活
- 支持单页面和多页面,通过路由分发出不同的页面
- 支持服务端渲染,把react丢到node.js中去,渲染出多个页面
- React Native,App开发
引入方式
cdn
基本语法
- ReactDOM.render() 渲染元素 如 div 等
- React.createElement() 创建元素(虚拟dom模拟真实dom进行对比差异,然后渲染), react核心库提供各种api操作dom
- React.Component ES6语法,开发中经常使用extents继承React.Component
2.编写Hello World
- 首先vi命令 touch index.html创建程序入口
- cdn或者npm方式引入react
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React demo 4</title>
<!-- cdn方式引入-->
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 引入babel -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<!-- 或者npm 方式引入 -->
<!-- <script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script> -->
</head>
<body>
<div id = "app"></div>
<script>
var hello = React.createElement('h1',{},"Hello world!");
ReactDOM.render(hello,document.getElementById('app'));
</script>
</body>
</html>
- ES6语法糖
- 引入babel 并且在div下script下添加type="text/babel"属性,即可在script下直接写html标签
<head> ... <!-- 引入babel --> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> ... </head> ... <body> <div id = "app"></div> <script type = "text/babel"> // var hello = React.createElement('h1',{},"Hello world!"); // ReactDOM.render(hello,document.getElementById('app')); ReactDOM.render( <h1>Hello,World</h1>, document.getElementById('app')); </script> </body>
3.jsx介绍
- 1 即在js中编写html代码
// 1 js中插入html代码
//原生方式
// var hello = React.createElement('h1',
// {
// className:'red',
// name:'jack'
// },
// "Hello world!");
// ReactDOM.render(hello,document.getElementById('app'));
//语法糖
ReactDOM.render(
<h1 className="red" name="jack">Hello,React</h1>,
document.getElementById('app'));
- 2 同时html中也可以嵌套js代码
// 2 html中插入js代码
var name = 'jack';
var ele = <h1 className="red" name="jack">Hello,{name}</h1>;
ReactDOM.render(
ele,
document.getElementById('app'));
4. 元素渲染
- React 只会更新必要的部分
- 值得注意的是 React DOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。
- 修改代码,每隔1s重新渲染一次,查看chrome控制台
// 元素渲染
function tick(params) {
var time = new Date().toLocaleTimeString();
var ele = <div>
<h1 className="red" name="jack">Hello,jack</h1>
<h2> 现在是,{time} </h2>
</div>
ReactDOM.render(
ele,
document.getElementById('app'));
}
setInterval(() => {
tick();
}, 1000);
- 可以看到,只会重新渲染改变的节点,而不会重新渲染整个标签
- vue是双向绑定,react是单向绑定
5. 组件和Props
公共UI,比如页面头部组件、底部组件、面包屑等,属于多个页面都需要用到的,这个时候需要将它做成(抽离成)组件, 一次修改,其他地方都跟着改变,提高开发效率
创建方式
- 函数式组件(无状态组件,没有生命周期)
- 属性通过 props.name方式取得
- 继承自React.Component (有状态组件,有生命周期)
- 有状态组件,属性通过this.props.name 方式取得
//5 组件和props
//5.1 函数式组件,无状态
// function Hello(props) {
// return <div>
// <h1>Hello,{props.name}</h1>
// <p>年龄:{props.age}</p>
// <p>擅长:Everything</p>
// </div>
// }
// ReactDOM.render(
// <Hello name ="jack" age = "29"/>,
// document.getElementById('app'));
//5.2 标准组件(带状态)
class HelloJack extends React.Component{
render(){
return <div>
<h1>Hello,{this.props.name}</h1>
<p>年龄:{this.props.age}</p>
<p>擅长:Everything</p>
</div>
}
}
ReactDOM.render(
<HelloJack name ="jack" age = "29"/>,
document.getElementById('app'));
6. React生命周期
四个阶段
- 1)组件初始化阶段
- 属性初始化
- 状态初始化
- 2)组件加载阶段
- 获取属性值
- 3)数据更新阶段
- 组件属性值发生变化
- 4)组件销毁阶段
// 6. React生命周期
class HelloJack extends React.Component{
// 构造函数 可以省略
constructor(props){
console.log('初始化阶段')
// 初始化props
super(props);
//初始化状态
this.state = {
name:'jack',
age:25
}
}
componentWillMount(){
console.log('组件加载前')
//可以进行ajax请求,请求数据操作
}
componentDidMount(){
console.log('组件加载后')
}
updateUser =()=>{
//错误的语法
//this.state.name = 'Time';
this.setState({
name:'Tim',
age:32
})
}
shouldComponentUpdate(){
//一般默认true
//根据具体业务场景,可以增加判断条件,比如登录了就更新,未登录就不更新
console.log('数据是否需要更新')
return true;
}
componentWillUpdate(){
console.log('数据将要更新')
}
componentDidUpdate(){
console.log('数据已经更新')
}
render(){
// 组件发生变化,就会执行render
console.log('组件加载 或 数据更新')
return <div>
<h1>Hello,{this.state.name}</h1>
<p>年龄:{this.state.age}</p>
<p>擅长:Everything</p>
{/*绑定updateUser函数 不能加括号,即不能写成updateUser()*/}
<button onClick={this.updateUser}>更新数据</button>
</div>
}
}
ReactDOM.render(
<HelloJack />,
document.getElementById('app'));
7.事件处理
事件名称为驼峰式命名,如onClick等
四种方式:
- 方式1 箭头函数动态绑定 如果写成updateUser(){...},就会undefined
- 方式2 初始化阶段绑定updateUser2对象,(设定指针)
- 方式3 onClick中 箭头函数直接绑定函数
- 方式4 onClick中 this.updateUser3.bind(this)
//7. 事件处理
class HelloJack extends React.Component{
// 构造函数 可以省略
constructor(props){
// 初始化props
super(props);
//初始化状态
this.state = {
name:'jack',
age:25
}
this.updateUser2 = this.updateUser2.bind(this);
}
// 方式1 箭头函数动态绑定 如果写成updateUser(){...},就会undefined
updateUser =()=>{
console.log(this);
this.setState({
name:'Tim',
age:32
})
}
//方式2 初始化阶段绑定updateUser2对象,(设定指针)
updateUser2(){
console.log(this);
this.setState({
name:'Joy',
age:33
})
}
// 方式3 onClick中 箭头函数直接绑定函数
// 方式4 onClick中 this.updateUser3.bind(this)
updateUser3(){
console.log(this);
this.setState({
name:'Stephen',
age:30
})
}
render(){
return <div>
<h1>Hello,{this.state.name}</h1>
<p>年龄:{this.state.age}</p>
<p>擅长:Everything</p>
<button onClick={this.updateUser}>更新数据</button><br/>
<button onClick={this.updateUser2}>更新数据2</button><br/>
<button onClick={()=>this.updateUser3()}>更新数据3</button><br/>
<button onClick={this.updateUser3.bind(this)}>更新数据4</button>
</div>
}
}
ReactDOM.render(
<HelloJack />,
document.getElementById('app'));
8. 条件处理
8.1 if else 和三元表达式
//8.条件处理
function Login(){
return <button >登录</button>
}
function LogOut(){
return <button>登出</button>
}
class App extends React.Component{
state = {
isLogin:false
}
updateUser =()=>{
console.log(this);
this.setState({
isLogin:true
})
}
render(){
// 获取状态
const isLogin = this.state.isLogin;
//或者
// const{isLogin} = this.state;
//1.if else
// let ele;//声明为let 如果是const 则其值不能改变
// if (isLogin) {
// ele = <Login/>
// }else{
// ele = <LogOut/>
// }
return <div>
<h1>Hello,{this.state.name}</h1>
{/*{ele}*/}
{/* 2. 三元表达式*/}
{isLogin?<Login/>:<LogOut/>}
<br/>
<button onClick={this.updateUser}>更新数据</button><br/>
</div>
}
}
ReactDOM.render(
<App />,
document.getElementById('app'));
8.2 子组件触发父组件的方法
function Login(props){
//子组件通过props属性接收updateUser方法
return <button onClick={props.updateUser}>登录</button>
}
function LogOut(props){
return <button onClick={props.updateUser}>登出</button>
}
class App extends React.Component{
state = {
isLogin:false
}
updateUser =()=>{
console.log(this);
this.setState({
isLogin:!this.state.isLogin
})
}
render(){
const isLogin = this.state.isLogin;
return <div>
<h1>Hello,{this.state.name}</h1>
{/*将updateUser方法传递给子组件*/}
{isLogin
?<Login updateUser={this.updateUser}/>
:<LogOut updateUser={this.updateUser}/>}
<br/>
</div>
}
}
ReactDOM.render(
<App />,
document.getElementById('app'));
9.列表渲染
//9. 列表渲染
class List extends React.Component{
state = {
list:[1,2,3,4,5],
list2:[
{id:1,text:'java'},
{id:2,text:'js'},
{id:3,text:'php'},
{id:4,text:'python'},
{id:5,text:'node'}
]
}
render(){
const arr = this.state.list;
const arr2 = this.state.list2;
const listItem = []
const listItem2 = []
//map方式遍历
arr.map((item)=>{
let li = <li>{item}</li>;
listItem.push(li);
})
//或for循环
// for (let i = 0; i < arr.length; i++) {
// let li = <li>{arr[i]}</li>;
// listItem.push(li);
// }
for (let i = 0; i < arr2.length; i++) {
let li = <li key={arr2[i].id}>{arr2[i].text}</li>;
listItem2.push(li);
}
return <div>
<ul>
{listItem}
{listItem2}
</ul>
</div>
}
}
ReactDOM.render(
<List />,
document.getElementById('app'));
10.表单应用
//10.表单应用
class ToDoList extends React.Component{
state = {
value:'',
list:[]
}
handleAdd = ()=>{
const val = this.state.value;
const list = this.state.list;
//或 es6结构语法
// const{val,list} = this.state;
list.push(val);
this.setState({
list:list
//es6中 当list和value相等时,可以省略key
//由list:list 简写为 list
})
}
handleInput = (event)=>{
this.setState({
value:event.target.value
})
}
render(){
const val = this.state.value;
const arr = this.state.list;
const listItem = []
arr.map((item,index)=>{
let li = <li key = {index}>{item}</li>;
listItem.push(li);
})
return <div>
<div>
<input type = "text" value={val} onChange={this.handleInput}/>
<button onClick={this.handleAdd}>添加条目</button>
</div>
<ul>
{listItem}
</ul>
</div>
}
}
ReactDOM.render(
<ToDoList />,
document.getElementById('app'));