react 基础 学习
react 基础 学习
1、环境配置
初始化项目。npm init 生成package.json
npm install xx 可以生存package-lock.json 和 node_modules 文件
// 渲染react元素
ReactDOM.render(
title,
document.getElementById('root')
)
// 第一个参数:要渲染的React元素
//第二个参数:Dom对象,用于指定渲染到页面中到位置
初始化脚手架
npx create-react-app my-app
扩充小知识:
ReactDom用于渲染Web页面,ios和安卓用的react-native里面的东西
2、JSX
2.1、Jsx介绍
因为React.createElement 十分繁琐,便引出了JSX。
JSX JavaScript XML:表示在Js代码中写HTML格式的代码。
JSX是react的核心内容。
JSX表示在JS代码中写HTML结构,是React申明式的体现
const title = <h1>i use jsx </h1>;
ReactDOM.render(title, document.getElementById("root"));
为什么脚手架可以使用JSX语法。==> 使用babel/present-react编译过后,才能在浏览器中使用。
2.2、JSX的基本使用
1、React元素的属性名使用驼峰命名法
2、特殊属性名 class - >ClassName 、 for ->HtmlFor 、 tabindex -> tabInDex
const title = <h1 className = "hello">i use jsx </h1>;
3、没有React子节点的元素可以单闭合标签
const title = <h1 className = "hello">i use jsx <span/></h1>;
4、推荐使用小括号包裹JSX,从而避免Js中的自动插入分号陷阱
const dv = (
<div>hello jsx </div>
)
3、 JSX中使用JavaScript表达式
Jsx中嵌入js表达式
- 数据存储在js中
- 语法:
const name = 'hujesse'
const dv = (
<h1> hello,{name}</h1>
)
4、条件渲染
1 、 逻辑与运算符
const showLoading = (isLoading) => {
return isLoading && (<div>Loading</div>);
};
2、if-else
const showLoading = (isLoading)=>{
if (isLoading){
return <div> loading</div>
}
return <div>success</div>
}
3、三元表达式
const showLoading = (isLoading) => {
return isLoading?(<div>Loading</div>):(<div>Success</div>)
};
5、Arrow function
普通的function(){}和箭头函数的区别在于this的指向不同,其他一样
6、 JSX的列表渲染
const songs = [
{ id: 1, name: "gang" },
{ id: 2, name: "no-flex-zone" },
{ id: 3, name: "flecRoom" },
];
const list = (
<ul>
{songs.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
ReactDOM.render(list, document.getElementById("root"));
注意点:避免使用索引号作为key,而应该使用唯一的属性比如id
7、JSX的样式处理
1、行内样式
const list = <h1 style={{ color: "red" }}>Jsx的样式处理</h1>;
2、使用类名className( 推荐)
import "./index.css";
const list = <h1 className="title">Jsx的样式处理</h1>;
8、组件
8.1、组件介绍
使用React就是在使用组件。
组合多个组件实现完整的页面功能。(可复用、独立、可组合)
8.2、组件二种创建方式
1、函数式组件
约定:1)大写字母开头 2)必须有返回值
function Hello() {
return <div>这是函数式组件普通方法形式</div>;
}
const Hello2 = () => <div>这是函数式组件ArrowFun形式</div>;
ReactDOM.render(<Hello2 />, document.getElementById("root"));
2、类式组件
约定:1)大写字母开头、 2)继承React.Component、 3)提供render()方法 、4)render方法必须有返回值
class Hello3 extends React.Component {
render() {
return <div>这是我的第一个类组件</div>;
}
}
ReactDOM.render(<Hello3 />, document.getElementById("root"));
8.2.1、组件定义抽离为Js文件
.. 没啥好说的
8.3、React事件处理
1、事件绑定
语法:on+事件名称 = 「事件处理程序」 onClick
注意:React事件采用驼峰命名法 比如:onFocus.
export default class Hello extends Component {
handleClick() {
return () => {
console.log("单击");
};
}
render() {
return (
<div>
<button onClick={this.handleClick()}>clike me</button>
</div>
);
}
}
上面和下面需要注意⚠️!!! 因为{} 前套的js表达式会立马执行
export default class Hello extends Component {
handleClick() {
console.log("单击");
}
render() {
return (
<div>
<button onClick={this.handleClick}>clike me</button>
</div>
);
}
}
2、事件对象
export default class Hello extends Component {
handleClick(e) {
//这里我们拿到了事件对象叫 ‘e’
// 阻止浏览器的默认行为
e.preventDefault();
console.log("点击我不跳转");
}
render() {
return (
<div>
<a href="www.google.com" onClick={this.handleClick}>
clike me
</a>
</div>
);
}
}
8.4、有状态组件和无状态组件
- 函数组件又叫做无状态组件,类组件又叫有状态组件
- 状态(state)即数据
- 函数组件没有自己的状态,只负责数据展示(静)
- 类组件有自己的状态,负责更新UI, 让页面动起来
8.5、组件中的state和setState()
状态(state)即数据,是组件内部的私有数据,只能在组件内部使用。
写法一:
export default class Hello extends Component {
constructor(){
this.state = {
count:0,
}
}
写法二:
export default class Hello extends Component {
state = {
count: 0,
};
小案列:计数器
export default class Hello extends Component {
state = {
count: 0,
};
render() {
return (
<div>
<h1
onClick={() => {
this.setState({ count: this.state.count + 1 });
}}
>
{this.state.count}
</h1>
</div>
);
}
}
8.6、事件绑定this指向
同上计数器,需要修改this的指向.
希望:this指向组件实例(render方法中的this即为组件实例)
使用箭头函数修改this
export default class Hello extends Component {
state = {
count: 0,
};
fun = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<h1 onClick={this.fun}>{this.state.count}</h1>
</div>
);
}
}
8.7、表单处理
1、受控组件(受react控制)
定义:HTML中的表单元素是可输入的,也就是有自己的可变状态(input)
而React中可变状态一般保存在state中,并且只能通过setState()修改
React将state与表单元素值value绑定在一起,由state的值来控制表单元素的值
文本框 富文本 下拉 复选框
export default class Hello extends Component {
state = {
txt: "",
fullTxt: "",
city: "",
isChecked: false,
};
handleChange = (e) => {
const target = e.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
// [name] 等同于把name字符串变成变量名了
this.setState({ [name]: value });
};
render() {
return (
<div>
<input
name="txt"
type="text"
value={this.state.txt}
onChange={this.handleChange}
/>
{/* 富文本框 */}
<textarea
name="fullTxt"
value={this.state.fullTxt}
onChange={this.handleChange}
></textarea>
{/* 下拉框 */}
<select
value={this.state.city}
onChange={this.handleChange}
name="city"
>
<option value="bj">北京</option>
<option value="sz">深圳</option>
<option value="gz">广州</option>
</select>
{/* 复选框 */}
<input
name="isChecked"
type="checkbox"
checked={this.state.isChecked}
onChange={this.handleChange}
/>
</div>
);
}
}
2、非受控组件
说明:借助于ref获取值,但是直接操作了dom,不推荐使用。
8.8、总结
react完全利用js语言的能力创建组件,这就是react的思想
8.9、小案列:展示 嘿嘿嘿🤤,我的小案例🤤
export default class Hello extends Component {
state = {
comments: [
{ id: 1, name: "jack", content: "hi" },
{ id: 2, name: "dick", content: "hol" },
{ id: 3, name: "hoe", content: "hoe" },
],
userName: "",
content: "",
};
renderList = () => {
const { comments } = this.state;
if (comments.length === 0) {
return <div className="no-comment">暂无评论</div>;
}
return (
<ul>
{comments.map((item) => (
<li key={item.id}>
<h3>评论人:{item.name}</h3>
<p>{item.content}</p>
</li>
))}
</ul>
);
};
handleChange = (e) => {
const { name, value } = e.target;
this.setState({ [name]: value });
};
addComment = () => {
const { comments, userName, content } = this.state;
// 非空判断
if (userName.trim() === "" || content.trim() === "") {
alert("请输入");
return;
}
const lastComment = comments[comments.length - 1]; //取出最后一个元素
const newComnets = [
...comments,
{ id: lastComment.id + 1, name: userName, content: content },
];
this.setState({ comments: newComnets });
// 清空文本框
this.setState({
userName: "",
content: "",
});
};
render() {
return (
<div className="app">
<div>
<input
type="text"
className="user"
placeholder="plz input ur name"
name="userName"
value={this.state.userName}
onChange={this.handleChange}
/>
<br />
<textarea
className="content"
id=""
cols="30"
rows="10"
value={this.state.content}
name="content"
onChange={this.handleChange}
></textarea>
<br />
<button onClick={this.addComment}>发表评论</button>
</div>
{this.renderList()}
</div>
);
}
}
9、组件通信
介绍:多个组件之间不可避免的要共享某些数据
9.1、组件的props
组件是封闭的,要接受外部数据应该通过props来实现
props是只读的
接受数据:类组件通过this.props接受数据,函数组件通过参数props接受数据
可以传递字符串,对象,数组,函数,jsx表达式 etc
9.2、组件通讯的三种方式
1、父向子:props
2、子向父:利用回调函数,夫提供回调,子组件调用,将要传递的数据作为回调的参数
class Parent extends React.Component {
getMsg = (msg) => {
console.log("getMsg" + msg);
};
render() {
return (
<div className="parent">
父组件
<Child getMsg={this.getMsg} />
</div>
);
}
}
class Child extends React.Component {
handleClick = () => {
this.props.getMsg("ahah");
};
render() {
return (
<div className="child">
子组件
<button onClick={this.handleClick}>clickMe</button>
</div>
);
}
}
ReactDOM.render(<Parent />, document.getElementById("root"));
3、兄弟之间组件通信
把二个兄弟之间的状态提升到父组件中,由后者进行管理。
class Counter extends React.Component {
// 提供共享状态
state = {
count: 0,
};
handleChange = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<Child1 count={this.state.count} />
<Child2 handleChange={this.handleChange} />
</div>
);
}
}
const Child1 = (props) => {
return <h1>计数器 {props.count}</h1>;
};
const Child2 = (props) => {
return <button onClick={() => props.handleChange()}>+1</button>;
};
ReactDOM.render(<Counter />, document.getElementById("root"));
9.3、Context
调用步骤:
1、调用React.createContext()创建Provider(提供数据)和Consumer(消费数据)二个组件。
const {Provider,Consumer} = React.createContext()
2、使用Provider组件作为父组件
<Provider>
<div className="App">
<Child1/>
</div>
</Provider>
3、设置value属性,表示要传递的数据
<Provider value="pink">
<div>
<Node />
</div>
</Provider>
4、调用Consumer组件接受数据
const Child = (props) => {
return (
<Consumer>
{(data) => {
return <span>我是子节点接受的数据 -- {data}</span>;
}}
</Consumer>
);
};
整体:
const { Provider, Consumer } = React.createContext();
export default class App extends Component {
render() {
return (
<Provider value="pink">
<div>
<Node />
</div>
</Provider>
);
}
}
const Node = (props) => {
return (
<div>
<SubNode />
</div>
);
};
const SubNode = (props) => {
return (
<div>
<Child />
</div>
);
};
const Child = (props) => {
return (
<Consumer>
{(data) => {
return <span>我是子节点接受的数据 -- {data}</span>;
}}
</Consumer>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
10、props深入
10.1、props.children属性
props可以传递任意值!!
props.children 是双标签组件中插槽中的值
const App = (props) => {
return (
<div>
<h1>组件标签的子节点:</h1>
{props.children}
</div>
);
};
const Test = () => {
return (
<div>
<button>我是button</button>
</div>
);
};
ReactDOM.render(
<App>
<p>我是插槽中的子节点</p>
<Test />
</App>,
document.getElementById("root")
);
10.2 props 校验
不想说 没必要
10.3 props默认值
App.defaultProps = {
pageSize:10
}
11、组件的生命周期
定义:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。
钩子函数:生命周期的每一个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数。
只有类组件才有生命周期
11.1、生命周期的三个阶段
1、创建时候
2、更新时候
3、卸载时候
组件从页面消失。
12、react路由
Router组件:包裹整个应用,一个React应用只需要使用一次
二个常用Router:HashRouter 和 BrowserRouter
前者格式为:localhost:3000/#/first
有个‘ # ’
后者格式为:localhost:3000/first
编程式导航:this.props.history.push('/home')