基础部分
创建一个react的项目
-
创建一个react的项目
全局安装 react 指令
// 全局安装react (根据需要安装,不是必须的) npm i -g react // 或者 yarn -global react // 全局安装 react的脚手架 (创建react的应用,必须安装脚手架) npm i -g create-react-app // 或者 yarn -global create-react-app
使用脚手架创建应用
create-react-app 应用名称 // 例如创建一个TodoList应用 create-react-app todo-list
注意点:
1.全局安装create-react-app才能使用脚手架创建应用 2.应用名称全部为小写字母,不能出现“TodoList”这样的名称
组件的使用
-
组件的组成
// React 是react组件必不可少的,用于支持jsx语法的模块,虽然看不到引用,但是不能少 // Component 所有的react的组件都继承于Component,它是react组件的基类 import React, { Component } from 'react'; // TodoItem 自定义的组件 import TodoItem from "./TodoItem" // 定义TodoList组件 ,该组件继承于基类Component class TodoList extends Component { /*** * constructor 当前类的构造函数 * props 简单的理解:是父类传递的参数,例如 传递的值 或 方法,它是一个对象 * super(props) 简单的理解是:继承父类中的传递的参数 **/ constructor(props){ super(props) // state 是 所有react变量的仓储,简单理解就是:当前组件的变量都放在这个对象中 this.state = { inputValue: "", List: [] } // 使用 bind绑定this,让方法中的this永远指向当前的组件(可根据需求改变this的指向) this.getList = this.getList.bind(this) this.inputChang = this.inputChang.bind(this) this.addItem = this.addItem.bind(this) this.delItem = this.delItem.bind(this) } // react组件必不可少的方法,return 返回的是jsx的模板,可以理解为类似html+js的模板 render() { return ( {/*在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点 */} <> <div> <input value={this.state.inputValue} onChange={this.inputChang} /> <button onClick={this.addItem}>添加</button> </div> <ul> {this.getList()} </ul> </> ); }; // 遍历输出item getList() { ... } // 动态改变输入框的值 inputChang( e ) { ... } // 添加item addItem() { ... } // 删除item delItem(index) { ... } } // 导出TodoList export default TodoList;
-
认识jsx
简单的jsx的语法
... render() { return ( {/*在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点 */} <> <div> <input value={this.state.inputValue} onChange={this.inputChang} /> <button onClick={this.addItem}>添加</button> </div> <ul> {this.getList()} </ul> </> ); }; ...
-
在jsx中只能有一个根标签,使用<></>(幽灵标签)包裹,既能满足jsx的语法格式,在浏览器解析时不会解析幽灵标签,减少了dom树结构节点,也可以使用代码片段(Fragments ),效果和<></>相同,只是Fragments 还有更广泛的使用,后面会有详细说明
-
在jsx中使用注释,多行使用{/* 注释内容 */},单行使用
// 多行 {/* 多行注释内容 */} {/* 多行注释内容 */} // 单行 { // 单行注释内容 }
-
在jsx中使用组件的变量或者方法,使用{}包裹
-
在jsx中绑定的方法默认this指向undefined,所以需要使用bind绑定this的指向
// 方式1: 在constructor指定this constructor(props){ super(props) this.state = { inputValue: "", List: [] } this.getList = this.getList.bind(this) this.inputChang = this.inputChang.bind(this) this.addItem = this.addItem.bind(this) this.delItem = this.delItem.bind(this) } // 方式2:绑定事件的时候指定this ... <li onClick={this.delItem.bind(this,index)}></li> ...
-
-
组件的基本通讯
-
最简单的 父 ---> 子 传值
// 父组件通过在子组件标签上设置属性传递数据 <Boy teacherName={ this.state.teacherName } /> <Girl teacherName={ this.state.teacherName } /> // 子组件通过this.props获取父组件传递的数据 // this.props.teacherName 获取老师的名称 render(){ return ( <> <p> 我是{this.state.boyName},我的老师是{this.props.teacherName}, 我对老师很 <button onClick={()=> this.props.say(this.state.boyName,"满意") } > 满意 </button> </p> </> ) }
-
最简单的 子 ---> 父 通讯
// 父组件通过在子组件标签上设置属性传递数据 <Boy say = { this.stuSay } /> <Girl say = { this.stuSay } /> // 子组件通过this.props获取父组件传递的数据 // this.props.say 获取父组件提供的方法,通过调用父组件的方法,将传递的数据作为参数传入,当父组件的方法被调用,就通过获取当前方法参数的方式,得到了子组件传递的数据 render(){ return ( <> <p> 我是{this.state.boyName}, 我对老师很 <button onClick={()=> this.props.say(this.state.boyName,"满意") } > 满意 </button> </p> </> ) }
-
最简单的非父子通讯
核心思路:找到共同的父组件,同时使用父组件传递的值和方法
过程有些复杂,这里省略了
teacher.js
import React,{ Component } from "react"
// 导入 Boy(男孩) 和 Girl(女孩) 组件
import Boy from "./boy"
import Girl from "./girl"
export default class Teacher extends Component {
constructor(props){
super(props)
this.state = {
teacherName: "Tom",
stuName: "",
stuSayContent: "",
boyName: "",
girlName: "",
boySayContent: "",
girlSayContent: ""
}
this.stuSay = this.stuSay.bind(this);
this.boySaySecret = this.boySaySecret.bind(this);
this.grilSaySecret = this.grilSaySecret.bind(this);
}
render(){
let evaluation = false
if (this.state.stuName!=="" && this.state.stuSayContent) {
evaluation = true
}
return (
<>
<p>我是{ this.state.teacherName }老师</p>
<div>
{
evaluation ? (<p>学生评价:{this.state.stuName}对我很{this.state.stuSayContent}</p>) : " "
}
</div>
<Boy
say = { this.stuSay }
teacherName={ this.state.teacherName }
boySaySecret = {this.boySaySecret}
girlSayContent = {this.state.girlSayContent}
/>
<Girl
say = { this.stuSay }
teacherName={ this.state.teacherName }
grilSaySecret = {this.grilSaySecret}
boySayContent = {this.state.boySayContent}
/>
</>
)
}
stuSay(stuName,stuSayContent){
this.setState(()=>{
return {
stuSayContent,
stuName
}
})
}
boySaySecret(constent){
this.setState(()=>{
return {
boySayContent : constent
}
})
}
grilSaySecret(constent){
this.setState(()=>{
return {
girlSayContent : constent
}
})
}
}
boy.js
import React,{ Component } from "react"
export default class Boy extends Component {
constructor(props){
super(props)
this.state = {
boyName: "龙震天"
}
}
render(){
return (
<>
<p>
我是{this.state.boyName},我的老师是{this.props.teacherName},
我对老师很
<button onClick={()=> this.props.say(this.state.boyName,"满意") } >
满意
</button>,
我想对女孩说:<button onClick={()=> this.props.boySaySecret("我喜欢你")}>悄悄话</button>,
她对我说:{this.props.girlSayContent}
</p>
</>
)
}
}
gril.js
import React,{ Component } from "react"
export default class Boy extends Component {
constructor(props){
super(props)
this.state = {
girlName: "怜香玉"
}
}
render(){
return (
<>
<p>
我是{this.state.girlName},我的老师是{this.props.teacherName},
我对老师很
<button onClick={()=> this.props.say(this.state.girlName,"不满意") } >
不满意
</button>,
我想对男孩说:<button onClick={() => this.props.grilSaySecret("我也是")}>悄悄话</button>,
他对我说:{this.props.boySayContent}
</p>
</>
)
}
}
高级部分
- PropTypes与defaultProps
官方学习地址:https://reactjs.org/docs/typechecking-with-proptypes.html
import React, { Component } from "react";
class Test extends Component {
render() {
return (
<>
{this.props.content}
</>
)
}
MyComponent.propTypes = {
// 你可以将属性声明为 JS 原生类型,默认情况下
// 这些属性都是可选的。
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括数字、字符串、元素或数组)
// (或 Fragment) 也包含这些类型。
optionalNode: PropTypes.node,
// 一个 React 元素。
optionalElement: PropTypes.element,
// 一个 React 元素类型(即,MyComponent)。
optionalElementType: PropTypes.elementType,
// 你也可以声明 prop 为类的实例,这里使用
// JS 的 instanceof 操作符。
optionalMessage: PropTypes.instanceOf(Message),
// 你可以让你的 prop 只能是特定的值,指定它为
// 枚举类型。
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 一个对象可以是几种类型中的任意一个类型
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 可以指定一个数组由某一类型的元素组成
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 可以指定一个对象由某一类型的值组成
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 可以指定一个对象由特定的类型值组成
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// An object with warnings on extra properties
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
// 这个 prop 没有被提供时,会打印警告信息。
requiredFunc: PropTypes.func.isRequired,
// 任意类型的数据
requiredAny: PropTypes.any.isRequired,
// 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
// 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
// 它应该在验证失败时返回一个 Error 对象。
// 验证器将验证数组或对象中的每个值。验证器的前两个参数
// 第一个是数组或对象本身
// 第二个是他们当前的键。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})
}
export default Test;
- state 、props 、render() 之间的关系
父组件(主组件):当组件的state 或者 props发生改变的时候。render函数就会重新执行
子组件:当父组件的render函数运行时,它的所有子组件render函数都将重新执行。
网友评论