本文将对react基础进行由浅到深的讲解.
html模板
每个react中需要引用的文件
<script src="../build/react.development.js"></script>
<script src="../build/react-dom.development.js"></script>
<script src="../build/babel.min.js"></script>
// react.js 是 React 的核心库
// react-dom.js 是提供与 DOM 相关的功能
// Browser.js 的作用是将 JSX 语法转为 JavaScript 语法
<div id="example"></div>
<script type="text/babel">
//ReactDOM.render 是 React 的最基本方法
//用于将模板转为 HTML 语言,并插入指定的 DOM 节点。
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
JSX 的基本语法规则
var names = ["Alice", "Emily", "Kate"];
// JSX 的基本语法规则:
//遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;
//遇到代码块(以 { 开头),就用 JavaScript 规则解析。
ReactDOM.render(
<div>
{names.map(function (name, index) {
return <div key={index}>Hello, {name}!</div>;
})}
</div>,
document.getElementById("example")
);
style样式写法
<div style={{ opacity: this.state.opacity }}>
因为 React 组件样式是一个对象,
所以第一重大括号表示这是 JavaScript 语法,
第二重大括号表示样式对象。
运算符
//true && expression 总是会返回 expression,
//而 false && expression 总是会返回 false。
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 && (
<h2>You have {unreadMessages.length} unread messages.</h2>
)}
</div>
);
}
const messages = ["React", "Re: React", "Re:Re: React"];
ReactDOM.render(
<Mailbox unreadMessages={messages} />,
document.getElementById("root")
);
组件
<div id="example"></div>
<script type="text/babel">
//将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。
//所有组件类都必须有自己的 render 方法,用于输出组件。
class HelloMessage extends React.Component {
render() {
return <h1>Hello {this.props.name}</h1>;
}
}
// <HelloMessage name="John"> ,
// 就是 HelloMessage 组件加入一个 name 属性,值为 John。组件的属性可以在组件类的 this.props 对象上获取,
// 比如 name 属性就可以通过 this.props.name 读取。
ReactDOM.render(
<HelloMessage name="John" />,
document.getElementById('example')
);
//注意:class 属性需要写成 className ,for 属性需要写成 htmlFor
</script>
组件类型
//函数组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
//自定义组件
//组件名称必须以大写字母开头。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(element, document.getElementById("app"));
//当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)
//以及子组件(children)转换为单个对象传递给组件,这个对象被称之为 “props”。
//组合组件
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
function App() {
return (
<div>
<Welcome name="Sara" />
<Welcome name="Cahal" />
<Welcome name="Edite" />
</div> //运行三行
);
}
ReactDOM.render(<App />, document.getElementById("app"));
组件传值传参
//组件可以选择把它的 state 作为 props 向下传递到它的子组件中
//自定义组件也可以
<FormattedDate date={this.state.date} />
function FormattedDate(props) {
return <h2>It is {props.date.toLocaleTimeString()}.</h2>,document.getElementById('root');
}
传递参数 id 是你要删除那一行的 ID
//分别通过箭头函数和 Function.prototype.bind 来实现
<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
//React 的事件对象 e 会被作为第二个参数传递。
//如果通过箭头函数的方式,事件对象必须显式的进行传递,
//而通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递。
this.state
//this.props 表示那些一旦定义,就不再改变的特性
//this.state 是会随着用户互动而产生变化的特性。
class LikeButton extends React.Component {
constructor(props) {
super(props)
this.state = {
liked: true
}
this.handleClick = this.handleClick.bind(this)
// 为了在回调中使用 `this`,这个绑定是必不可少的
//下面会讲详细事件处理的this
}
handleClick(event) {
this.setState({ liked: !this.state.liked });
//通过 this.state 属性读取。当用户点击组件,导致状态变化
//this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法
//再次渲染组件。
}
render() {
var text = this.state.liked ? 'like' : 'haven\'t liked';
return (
<p onClick={this.handleClick}>
You {text} this. Click to toggle.
</p>
);
}
}
ReactDOM.render(
<LikeButton />,
document.getElementById('example')
);
事件处理this
<div id="root"></div>
<script type="text/babel">
//添加按钮事件
<button onClick={activateLasers}>Activate Lasers</button>;
//在 React 中另一个不同点是你不能通过返回 false 的方式阻止默认行为。
//你必须显式的使用 preventDefault
//阻止链接默认打开一个新页面
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log("The link was clicked.");
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// 为了在回调中使用 `this`,这个绑定是必不可少的
this.handleClick = this.handleClick.bind(this);
}
// 谨慎对待JSX回调函数中的this,在 JavaScript 中,class 的方法默认不会绑定this。
// 如果忘记绑定this.handleClick,并把它传入了 onClick,当你调用这个函数的时候this的值为undefined。
//还有另外两种解决方案
//1.使用 class fields 正确的绑定回调函数
class LoggingButton extends React.Component {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
// 注意: 这是 *实验性* 语法。
handleClick = () => {
console.log("this is:", this);
};
//2.没有使用 class fields 语法,你可以在回调中使用箭头函数 不建议使用
class LoggingButton extends React.Component {
handleClick() {
console.log('this is:', this);
}
render() {
// 此语法确保 `handleClick` 内的 `this` 已被绑定。
return (
<button onClick={() => this.handleClick()}>
Click me
</button>
);
}
}
handleClick() {
this.setState((state) => ({
isToggleOn: !state.isToggleOn,
}));
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? "ON" : "OFF"}
</button>
);
}
}
ReactDOM.render(<Toggle />, document.getElementById("root"));
PropTypes验证/defaultProps默认值
var data ;
//组件类的PropTypes属性,就是用来验证组件实例的属性是否符合要求
//Mytitle组件有一个title属性。
//PropTypes 告诉 React,这个 title 属性是必须的,而且它的值必须是字符串。
class MyTitle extends React.Component {
static propTypes = {
title: PropTypes.string.isRequired,
}
//设置组件默认值 组件内部写法 defaultProps
// static defaultProps = {
// title:"a"
// }
render() {
return <h1> {this.props.title} </h1>;
}
}
//设置组件默认值 组件外部写法 defaultProps,验证同理
MyTitle.defaultProps={
title:"aaaa"
}
ReactDOM.render(
<MyTitle title={data} />,
document.getElementById('example')
);
表单
//用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props
class Input extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 'Hello!'}
this.handleChange = this.handleChange.bind(this) }
handleChange(event) {
this.setState({ value: event.target.value }); }
render(){
var value = this.state.value;
return (
<div>
<input type="text" value={value} onChange={this.handleChange} />
<p>{value}</p>
</div> );}}
// 定义一个 onChange 事件的回调函数,
// 通过 event.target.value 读取用户输入的值。
// textarea 元素、select元素、radio元素都属于这种情况
ReactDOM.render(<Input/>, document.getElementById('example'));
列表
<div id="root"></div>
<script type="text/babel">
//通过使用 {} 在 JSX 内构建一个元素集合。
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) => <li>{number}</li>);
ReactDOM.render(<ul>{listItems}</ul>, document.getElementById("root"));
//列表组件
key 帮助 React 识别哪些元素改变了,比如被添加或删除。
一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => (
<li key={number.toString()}>{number}</li>
));
return <ul>{listItems}</ul>;
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById("root")
);
//用 key 提取组件
//一个好的经验法则是:在 map() 方法中的元素需要设置 key 属性。
// 元素的 key 只有放在就近的数组上下文中才有意义。
// 比方说,如果你提取出一个 ListItem 组件,
// 你应该把 key 保留在数组中的这个 <ListItem /> 元素上,
// 而不是放在 ListItem 组件中的 <li> 元素上。
function ListItem(props) {
// 正确!这里不需要指定 key:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) => (
// 正确!key 应该在数组的上下文中被指定
<ListItem key={number.toString()} value={number} />
));
return <ul>{listItems}</ul>;
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById("root")
);
列表小练习
class List extends React.Component{
render(){
const numbers=[1,2,3,4,5];
const listItems = numbers.map((numbers) =>
<li key='index'>{numbers}</li>
);
return(
<div>
<h1>框架</h1>
<ul>{listItems}</ul>,
</div>
)
}
}
ReactDOM.render(
<List/>,
document.getElementById("root")
);
生命周期
// Mounting:已插入真实 DOM
// Updating:正在被重新渲染
// Unmounting:已移出真实 DOM
//will 函数在进入状态之前调用,did 函数在进入状态之后调用
class Hello extends React.Component {
constructor(props) {
super(props);
this.state = {
opacity: 1.0,
};
}
componentDidMount() {
this.timer = setInterval(
function () {
var opacity = this.state.opacity;
opacity -= 0.05;
if (opacity < 0.1) {
opacity = 1.0;
}
this.setState({
opacity: opacity,
});
}.bind(this),
100 );
}
render() {
return (
//因为 React 组件样式是一个对象,
// 所以第一重大括号表示这是 JavaScript 语法,
// 第二重大括号表示样式对象。
<div style={{ opacity: this.state.opacity }}>
Hello {this.props.name}
</div> );
}
}
ReactDOM.render(
<Hello name="world" />,
document.getElementById("example")
);
生命周期时间小例子
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { date: new Date() };
} //初始化
// 当 Clock 组件第一次被渲染到 DOM 中的时候,就为其设置一个计时器。“挂载(mount)”。
// 当 DOM 中 Clock 组件被删除的时候,应该清除计时器。“卸载(unmount)”。
//componentDidMount() 方法会在组件已经被渲染到 DOM 中后运行
componentDidMount() {
this.timerID = setInterval(() => this.tick(), 1000);
} //3
// componentWillUnmount() 生命周期方法中清除计时器
componentWillUnmount() {
clearInterval(this.timerID);
} //5
// 使用tick() 的方法,Clock 组件每秒都会调用它。
// 使用 this.setState() 来时刻更新组件 state
tick() {
this.setState({
date: new Date(),
});
} //4
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
} //2
ReactDOM.render(<Clock />, document.getElementById("root")); //1
获取真实DOM节点
1.字符串
通过 this.refs.a 来引用真实dom的节点---dom 节点上使用
<input type ="text" ref="a"/>
2.回调函数
回调函数就是在dom节点或组件上挂载函数,函数的入参是dom节点或组件实例,达到的效果与字符串形式是一样的,都是获取其引用。
<input type="text" ref={(input)=>{this.textInput=input}}
//可以通过 this.textinput 获取到这个 DOM 元素
var name = this.textInput.value
3.React.createRef()
在React 16.3版本后,使用此方法来创建ref。将其赋值给一个变量,通过ref挂载在dom节点或组件上,该ref的current属性将能拿到dom节点或组件的实例
)1.通过render放入一个元素
<input type="text" ref={this.myRef} />
)2.通过React.createRef()创建Refs并通过ref属性联系到React组件
this.myRef = React.createRef();
)3.通过ref的current属性得到
this.myRef.current.value;
<input type="text" ref={(input)=>{this.textInput=input}} />
this.textInput.value
this.props.children
// this.props.children 属性。它表示组件的所有子节点
//this.props.children 的值有三种可能:
//如果当前组件没有子节点,它就是 undefined ;
//如果有一个子节点,数据类型是 object ;
//如果有多个子节点,数据类型就是 array
class NotesList extends React.Component {
render() {
return (
<ol>
{React.Children.map(this.props.children, function (child) {
return <li>{child}</li>;
})}
</ol>
);
}
}
//React 提供一个工具方法 React.Children 来处理 this.props.children 。
//我们可以用 React.Children.map 来遍历子节点,
//而不用担心 this.props.children 的数据类型是 undefined 还是 object
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.getElementById("example")
);
Ajax
<div id="example"></div>
<script type="text/babel">
//使用 componentDidMount 方法设置 Ajax 请求
//等到请求成功,再用 this.setState 方法重新渲染 UI
class UserGist extends React.Component {
constructor(props) {
super(props)
this.state = {
username: '',
lastGistUrl: ''
}
}
//$.get() 方法使用 HTTP GET 请求从服务器加载数据。
//$.get(URL,data,function(data,status,xhr),dataType)
//function(data,status,xhr) 可选。规定当请求成功时运行的函数。
//dataType 可选。规定预期的服务器响应的数据类型。
componentDidMount() {
$.get(this.props.source, function(result) {
var lastGist = result[0];
this.setState({
username: lastGist.owner.login,
lastGistUrl: lastGist.html_url
});
}.bind(this));
}
render() {
return (
<div>
{this.state.username}'s last gist is <a href={this.state.lastGistUrl}>here</a>.
</div>
);
}
}
ReactDOM.render(
<UserGist source="https://api.github.com/users/octocat/gists" />,
document.getElementById('example')
);
promise
class RepoList extends React.Component {
constructor(props) {
super(props)
this.state = {
loading: true,
error: null,
data: null
};
}
componentDidMount() {
this.props.promise.then(
value => this.setState({loading: false, data: value}),
error => this.setState({loading: false, error: error}));
}
render() {
if (this.state.loading) {
return <span>Loading...</span>;
}
else if (this.state.error !== null) {
return <span>Error: {this.state.error.message}</span>;
}
else {
var repos = this.state.data.items;
var repoList = repos.map(function (repo, index) {
return (
<li key={index}><a href={repo.html_url}>{repo.name}</a> ({repo.stargazers_count} stars) <br/> {repo.description}</li>
);
});
return (
<main>
<h1>Most Popular JavaScript Projects in Github</h1>
<ol>{repoList}</ol>
</main>
);
}
}
}
ReactDOM.render(
<RepoList promise={$.getJSON('https://api.github.com/search/repositories?q=javascript&sort=stars')} />,
document.getElementById('example')
);