共计 21709 个字符,预计需要花费 55 分钟才能阅读完成。
网页总是一个链接着另一个的,React 一大优势在于每次链接到另一个页面上去的时候,不需要向传统页面一样,得销毁所有代码,重新渲染新页面的代码,而只在一个页面上展现新的内容——单页页面。
React 另一个优势是,以往的单页页面你需要考虑哪个元素要被删除、哪个元素的行为要被修改,而我们只需要告诉 React 我们想要的最终页面的效果,React 会自动帮我们处理页面上的元素,做删除、修改等操作。
而我只知道 React 有自己的虚拟 DOM,它会对比虚拟 DOM 和真实 DOM 的差别,然后在适当的时机更新页面。至于它怎么对比的?怎么知道差别的?怎么进行修改的?我不知道,不过,对于我们,谁在乎呢?
必须首先知道的关于 React 的术语
JSX 语法:React 特有语法,用来搭建虚拟 DOM
组件(Component):一个个代码块,用来封装各种功能,可以类比于函数(function)
props&status:组件的所有静态属性 & 所有动态属性
引入 React
想要使用 React,你需要先引入:
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin</script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
上面两个 <script> 引入了 React 的核心库,最后一句 <script> 引入 jsx 语法编译器,因为浏览器不懂 jsx 只知道 javascript,所以,引入编译器转换为浏览器能懂的 javascript 语言
请参考 React 官方文档以获取最新版本 React 的引入:https://reactjs.org/docs/add-…
初步使用 React
并没有什么特别的技巧,先看代码,再做解释:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>React First Try</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
ReactDOM.render(
<div>
<p>Batman</p>
<p>catwoman</p>
</div>,
container
);
</script>
</body>
</html>
解释:
首先引入了三个 <script>
新建一个元素 <div id=”container”></div>
我们必须在一个 <scripr type=”text/babel”> 中使用 React,请注意 <script> 的 type
像一般的 javascript 语法一样,我们先获取页面元素
var container = document.querySelector(“#container”);
修改虚拟 DOM,并渲染真实 DOM 其中,ReactDOM.render(); 就是在渲染,其含义是将第一个参数渲染到第二个参数下。而第一个参数 <div>…</div> 就是新的虚拟 DOM 的内容,可更改为我们想要的真实 DOM 结构。
ReactDOM.render(
<div>
<p>Batman</p>
<p>catwoman</p>
</div>,
container
);
效果、页面结构
我们看到,页面中已经添加了包含两个 <p> 元素的 <div>。React.render()函数的第一个参数只能是一个标签,不能是并列的两个标签。不过一个标签里的子标签可以随便的添加,所以最好的方法就是,在外面添加一个 <div></div>
使用组件(Component)
上面的方法是直接将你想要的写在 React.render()里,通常的做法是引用组件
定义一个组件
class 组件名 extends React.Component(
//your code
);
组件里可以添加很多功能,比如想要添加一个按钮,你只需直接写你想要的 DOM 结构,而不需要使用 javascript 语法:createElement()、appendChild()等
class 组件名 extends React.Component(
render(){
return (<button>Batman</button>);
}
);
在组件里写好你想要的东西,使用 React.render()进行渲染
React.render(
< 组件名 />,
想要渲染的位置
)
完整代码可以如下
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>React First Try</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Myname extends React.Component{
render(){
return (<button>Batman</button>);
}
};
ReactDOM.render(
<Myname/>,
container
);
</script>
</body>
</html>
效果、页面结构
我们看到,页面上出现了我们想要的按钮,页面结构里也成功添加了 <button> 标签。注意!!!组件名首字母必须大写!!!引用组件注意代码 < 组件名 />,一个符号都不能错的!!!
使用 props
props 用来获取组件的静态属性,可以先看下面的一个小例子:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>React First Try</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Myname extends React.Component{
render(){
return (<button type={this.props.buttontype}>{this.props.children}</button>);
}
};
ReactDOM.render(
<Myname buttontype=”submit”>Batman</Myname>
,
container
);
</script>
</body>
</html>
不必惊慌,修改的地方只有组件的 render()和实际渲染的 render()两个函数。
第一个 render()添加了 <button> 的 type 属性,该属性值指向 {this.props.buttontype},意思是该组件名为 buttontype 的静态属性。这个 render() 还将 <button> 的显示文字指向{this.props.children},意思是该组件的子元素这个静态属性
第二个 render()函数添加了 <Myname> 的静态属性 buttontype,和一个 text 类型的子元素 Batman
结论就是:在渲染真实 DOM 的时候,会创建一个 <button></button> 标签,它的 type 属性值为 submit,文字显示为 Batman
效果、页面结构,哈哈哈,没啥区别,没区别就对了:
props 的传递性
props 只能从父元素向下传递给子元素:
当有多个属性你想传递的时候,你的代码可能就会是这样的,会重复很多遍{this.props.propsName}:
<script>
class Me extends React.Component{
render(){
return (
<div>
<p>{this.props.props1}</p>
<p>{this.props.props2}</p>
<p>{this.props.props3}</p>
</div>
);
}
};
class Father extends React.Component{
render(){
return (
<Me props1={this.props.props1} props2={this.props.props2} props3={this.props.props3}/>
);
}
};
ReactDOM.render(
<Father props1=”a” props2=”b” props3=”c”/>,container
);
</script>
如果你不想重复很多遍繁琐的{this.props.propsName},那你可以使用扩展运算符 … 表示取到所有的静态属性并且都使等于{this.props.propsName},所以我们的代码可以稍作简化:
<script>
class Me extends React.Component{
render(){
return (
<div>
<p>{this.props.props1}</p>
<p>{this.props.props2}</p>
<p>{this.props.props3}</p>
</div>
);
}
};
class Father extends React.Component{
render(){
return (
<Me {…props}/> //???????? 使用扩展运算符进行简化{…props}
);
}
};
ReactDOM.render(
<Father props1=”a” props2=”b” props3=”c”/>,container
);
</script>
React 操作 CSS
此方法可以使你在 <script> 里更改、渲染 CSS。不过使用 React 的 JSX 语法会和 CSS 语法有一点点不同,就一点点┑(~Д ~)┍
因为刚开始接触,代码不难,所以直接先看示例代码吧;
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>React First Try</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Mycss extends React.Component{
render(){
var letterColor = {
padding: 10,
margin: 10,
backgroundColor: this.props.thiscolor,
color: “#333”,
display: “inline-block”,
fontFamily: “monospace”,
fontSize: 32,
textAlign: “center”,
};
return (<div style={letterColor}>{this.props.children}</div>);
}
};
ReactDOM.render(
<div>
<Mycss thiscolor=”#58B3FF”>B</Mycss>
<Mycss thiscolor=”#FF605F”>a</Mycss>
<Mycss thiscolor=”#FFD52E”>t</Mycss>
<Mycss thiscolor=”#49DD8E”>m</Mycss>
<Mycss thiscolor=”#AE99FF”>a</Mycss>
<Mycss thiscolor=”#FF6633″>n</Mycss>
</div>
,
container
);
</script>
</body>
</html>
哇!!代码怎么看上去又有这么多的改动啊!!别慌张别慌张!其实和上一小节一样,只改动了一些内容在组件的 render()和真实渲染的 render()两个函数里
组件 render()里首先定义了一个虚拟 CSS 类,看上去符合 CSS 语法,但其实呢,他是一个 JSX 语法,仔细看,它就是一个用 JSX 语法写的神似 CSS 的对象。其中的一些区别如下:
它不应该有 px,px 这种东西 JSX 会自动补充
它不应该有分号; 来表示这个属性结束了,请使用逗号,
它应该把除了纯数字外的所有属性值都加上引号 ””
它应该使用驼峰命名法来表示 CSS 中使用连接号 - 的属性名:backgroundColor
所以,在遵循了所有使用 JSX 语法描述 CSS 状态的规则之后,你就可以成功的定义一个虚拟 CSS。接着,在组件的 render()里调用它,像这样 <div style={letterColor}>,style={虚拟 CSS 名}。
在这里另一个知识点是,在定义虚拟 CSS 的 backgroundColor 时,它的参数值是一个变量 this.props.thiscolor,同上一小节一样,在真实渲染 render()的第一个参数里定义这个静态变量 <Mycss thiscolor=”#58B3FF”>。这样,就成功在 CSS(虚拟的)里调用了其它地方的变量来确定属性值。
效果、页面结构:值得注意的是,React 处理的 CSS 是通过内联方式(标签中插入 style 属性)实现的
小结
这个时候,我们需要做一个小例子,来巩固下关于组件、CSS 引入、props 的概念
我们想要实现的效果
我们想要实现的效果就是,当你输入颜色代码,上面就能正确的展示颜色:
分离组件
在 React 的世界,一切都是组件,页面上所有的内容都是由一个个组件搭建起来的。你可以将结构划分为很小的组件,这样实现的功能就很详细。你也可以将结构划分为稍大的组件,功能就更集中。
所以,像我们这样的小应用,下面的组件划分方法就足以满足要求:
编写程序
在分析完结构需要分成多少组件之后,可以开始构造代码~
首先,我们编写组件框架。其中每一个 class 就代表了我们分成的组件。在这里 class ColorName 表示文字部分,class Color 表示颜色显示区,class Board 表示用来承载这个应用的底板。每个组件都有一个 render()函数用来之后渲染组件到 DOM 上。
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Color</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class ColorName extends React.Component{
render(){
}
};
class Color extends React.Component{
render(){
}
};
class Board extends React.Component{
render(){
}
};
ReactDOM.render(
<Board/>,container
);
</script>
</body>
</html>
上述步骤等于搭完了骨架,我们需要填充肌肉。写下,最终需要每个组件分别返回什么标签:ColorName 组件返回一个 <p> 标签,用以展现颜色的色号 Color 组件返回一个 <div> 标签,用来显示颜色 Board 组件返回一个 <div> 标签,并且把上两个组件包在一起
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Color</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class ColorName extends React.Component{
render(){
return (<p>{this.props.colorName}</p>);
}
};
class Color extends React.Component{
render(){
return (<div id=”color”></div>);
}
};
class Board extends React.Component{
render(){
return (
<div>
<Color colorName = {this.props.colorName}/>
<ColorName colorName = {this.props.colorName}/>
</div>
);
}
};
ReactDOM.render(
<Board colorName=”#f7a87d”/>,container
);
</script>
</body>
</html>
接下来我们只需要添加你想要的 CSS 就 OK 了,不过在添加 CSS 之前,我想对上一步骤简单解释:我们在渲染真实 DOM 时定义了一个静态属性 colorName=”#f7a87d”,经由组件 Board 传入组件 ColorName、Color。最后通过每个组件各自的 render()函数的 return 渲染在页面上。
最后我们需要添加一些 CSS 帮页面穿点衣服,其中对 CSS 的引入使用了两种方法,使用 React 引入和引入外部 CSS 文件:
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Color</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
<style>
#board{
width: 300px;
height: 400px;
/* border: 1px solid red; */
border-radius: 3%;
box-shadow: 3px 5px 7px 1px rgba(128,128,128,1);
}
#color{
height: 80%;
border-radius: 3%;
box-shadow: 1px 1px 6px 1px rgba(128,128,128,1);
}
</style>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class ColorName extends React.Component{
render(){
var ColorNameStyle = {
fontSize: “2.5em”,
fontFamily: “sans-serif”,
fontWeight: “bold”,
textAlign: “center”,
margin: 17,
};
return (<p style={ColorNameStyle}>{this.props.colorName}</p>);
}
};
class Color extends React.Component{
render(){
var colorStyle = {
backgroundColor: this.props.colorName,
};
return (<div style={colorStyle} id=”color”></div>);
}
};
class Board extends React.Component{
render(){
return (
<div id=”board”>
<Color colorName = {this.props.colorName}/>
<ColorName colorName = {this.props.colorName}/>
</div>
);
}
};
ReactDOM.render(
<Board colorName=”#f7a87d”/>,container
);
</script>
</body>
</html>
使用 state
以上的各个步骤可以创建一个基本的静态页面,如果想要创建一个有点动态,看上不是死气沉沉的页面,那就一定需要 state。正如之前提到的,props 包含了所有的静态属性,state 则包含了所有用于动态展示的属性。
这时,我们需要一个例子
我们的目标
分离组件
外面一个黑的长方形边框;内部一个黑色的底板;#5dffff 的动态数字;三行文字
编写代码
编写代码框架:Times 类表示变化的数字;Words 表示三行灰色的文字;BlackBoard 表示黑色的底板;Board 表示最外面一圈黑边框
<!DOCTYPE html>
<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>Lightning</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Times extends React.Component{
render(){
return ();
}
};
class Words extends React.Component{
render(){
return ();
}
};
class BlackBoard extends React.Component{
render(){
return ();
}
};
class Board extends React.Component{
render(){
return ();
}
};
ReactDOM.render(
<Board/>
,container
);
</script>
</body>
</html>
然后我们需要添上返回的内容,我们就只看 React 的内容
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Times extends React.Component{
render(){
return (<h1>Strike Times</h1>);
}
};
class Words extends React.Component{
render(){
return (
<div>
<p>lightning strike</p>
<p>worldwide</p>
<p>(since you loaded this outstanding)</p>
</div>
);
}
};
class BlackBoard extends React.Component{
render(){
return (
<div>
<Times/>
<Words/>
</div>
);
}
};
class Board extends React.Component{
render(){
return (
<div>
<BlackBoard/>
</div>
);
}
};
ReactDOM.render(
<Board/>
,container
);
</script>
将 Strike Times 变成动态,我们只需改变 Times 类:
首先需要定义 state:必须在 constructor 内定义 this.state={}
constructor(props){
super(props);
this.state = {
strike: 0,
};
}
使用生命周期钩子,componentDidMount 钩子里的内容会在页面渲染完成后被调用. 在本例中,页面渲染完成后会调用一个计时器 setInterval(),计时器中调用的函数请使用箭头函数,这样被调用的函数里的 this 才会被正确的指向当前类,其它调用方法会指向 window
componentDidMount() {
setInterval(() => this.addNumber(),1000);
}
定义你想调用的函数注意!!!如果你想修改 state 中的值,请必须使用 this.setState()来修改!!
addNumber(){
this.setState({
strike: this.state.strike + 100,
});
}
最后,设定返回值,显示的内容为 state 中的 strike 值
render(){
return (<h1>{this.state.strike}</h1>);
}
加上点样式
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Times extends React.Component{
constructor(props){
super(props);
this.state = {
strike: 0,
};
}
componentDidMount() {
setInterval(() => this.addNumber(),1000);
}
addNumber(){
this.setState({
strike: this.state.strike + 100,
});
}
render(){
var strikeStyle = {
margin: 0,
padding: “55px”,
color: “#5dffff”,
fontSize: “60px”,
}
return (<h1 style={strikeStyle}>{this.state.strike}</h1>);
}
};
class Words extends React.Component{
render(){
var words = {
fontFamily: “sans-serif”,
margin: 0,
padding: 0,
};
var wordStyle = {
wordNormal: {
…words,
color: “#999999”,
fontSize: 33,
},
wordBig: {
…words,
color: “#999999”,
fontSize: 50,
},
wordSmall: {
…words,
color: “#4d4d4d”,
},
}
return (
<div>
<p style = {wordStyle.wordNormal}>lightning strike</p>
<p style = {wordStyle.wordBig}>worldwide</p>
<p style = {wordStyle.wordSmall}>(since you loaded this outstanding)</p>
</div>
);
}
};
class BlackBoard extends React.Component{
render(){
return (
<div style = {this.props.style}>
<Times/>
<Words/>
</div>
);
}
};
class Board extends React.Component{
render(){
var boardStyle = {
board: {
width: 300,
height: 400,
padding: 13,
backgroundColor: “white”,
border: “2px solid black”,
},
blackboard: {
height: “100%”,
backgroundColor: “black”,
borderRadius: “7%”,
textAlign: “center”,
lineHeight: “50px”,
}
};
return (
<div style={boardStyle.board}>
<BlackBoard style = {boardStyle.blackboard}/>
</div>
);
}
};
ReactDOM.render(
<Board/>
,container
);
</script>
使用 JSX
即使我们在之前的文章中已经开始使用了 JSX 这种 React 特别的语法,但是,我们还是应该为它专门开辟一个新的章节,因为,JSX、组件、组件生命周期是 React 的三大奠基核心(哈哈哈,当然是我的个人见解)。
说到 JSX,令人印象深刻的就是各种在 js 里添加 html 标签和出现在各个地方的{}
在 js 里添加 html 标签
在提倡 css 样式、js 行为、html 标签 分离的时代,这样的设计别出心裁。主要是因为 React 的基础设施不是传统的 html 标签,而是各个组件。一个组件里包含了构成页面某一部分所需要的所有的 css 样式、js 行为、html 标签。所以,遵循这样的思路,在 js 里添加 html 标签没什么稀奇的。
像这样:
var myname = <h1>Batman</h1>;
function functionName(){
// your codes
return <h1>Batman</h1>;
}
const me = (
<div>
<h1>Batman</h1>
<h2>hello gotham</h2>
</div>
);
注意!!!JSX 不能够将 多个 html 标签 直接赋给一个变量或者直接返回,需要将 多个 html 标签 包括在一个父元素中,就像上例第三个例子一样。
{}
在 js 里添加 html 标签对我们来说已经见怪不怪了,大括号 {} 的使用才是精髓。哈哈哈~~
{}用于在 React 中的各个地方引用各种合理的 JS 表达式(valid JavaScript expression)。大括号里可以是变量 user.username、表达式 2 +2、函数调用 functionName(user)等。
像这样:
const name = ‘Josh Perez’;
const element = <h1>Hello, {name}</h1>;
const element = <img src={user.avatarUrl}></img>;
const element = <h1>2+2={2+2}</h1>;
function formatName(user) {
return user.firstName + ‘ ‘ + user.lastName;
}
const user = {
firstName: ‘Harper’,
lastName: ‘Perez’
};
const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);
ReactDOM.render(
element,
document.getElementById(‘root’)
);
另外,还有双括号 {{}} 的写法,这种表达方式用于在 JSX 里内联样式。
{{}}内的内容:
对象的写法,将 css 里的; 变成,
属性名使用驼峰写法,css 里 - 后面的第一个字母大写
只会生效最后一个 style,下例中只会生效 style={gothamStyle}
var myName = <h1 style={{color:”black”}} style={{fontSize:”25px”}} style={gothamStyle}>Batman</h1>;
像这样:
const myName = <h1 style={{color:”black”,fontSize:”25px”}}>Batman</h1>;
关于更多 React 中操作 CSS,你还可以浏览这篇文章:https://www.jianshu.com/p/850…
JSX 的优势
防止 XSS (cross-site-scripting)攻击。因为所有内容在被 React 渲染到页面上前都会先转成字符串
小巧灵活。JSX 本质就是 Javascript,所以,JSX 可以被放在任何一个地方。再加上 JSX 里的内容非常丰富。结合 React 的设计思想,JSX 非常好用。
当然 JSX 还可以撰写 css 内容,详细可以参见之前章节:React 操作 CSS
使用 JSX 的一个例子
只要使用 React 搭建网站必然需要用到 JSX,额,虽然官方是这样表示的:Well~ 我们还是快速的过一遍这个例子
我们要实现的目标
几个圆圈过 1 秒就变颜色,颜色随机从颜色库里选取
完整代码
其实很简单,Circle 组件负责改变颜色的行为,CreateCircle 组件负责定义样式并渲染这些圆圈。
然后因为一直是动态的,所以,使用 Circle 组件的 state,每个一段时间 setInterval 都会调用 changeColor 函数,来改变 state 里的内容,改变之后 React 会重新渲染页面被改动的部分。
值得注意的是,在这个例子中,JSX 被运用在任何一个位置,
可以被压到数组中去
colorarray.push(<CreateCircle bgColor={colors[random]} key={i}/>)
被渲染
render(){
return (<div>{this.state.colorArray}</div>);
};
撰写、引用 css
class CreateCircle extends React.Component{
render(){
var circleStyle = {
padding: 10,
margin: 20,
display: “inline-block”,
backgroundColor: this.props.bgColor,
borderRadius: “50%”,
width: 100,
height: 100,
};
return (<div style={circleStyle}></div>);
}
};
注意!!!在 React 中使用 key={}属性来唯一标识一个组件 <CreateCircle key={i}/>
完整代码:
<!DOCTYPE html>
<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>Lightning</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.getElementById(“container”);
var colors = [“#393E41″,”#E94F37″,”#1C89BF”,”#A1D363″,”#85FFC7″,”#297373″,”#FF8552″,”#A40E4C”];
class Circle extends React.Component{
constructor(props){
super(props);
this.state = {
colorArray: [],
};
};
changeColor(){
var colorarray = [];
this.setState({
colorArray: [],
});
for(var i=0;i < colors.length;i++){
var random = Math.floor(Math.random()*colors.length);
colorarray.push(<CreateCircle bgColor={colors[random]} key={i}/>)
this.setState({
colorArray: colorarray,
});
}
};
componentDidMount(){
setInterval(() => this.changeColor(),1000);
};
render(){
return (<div>{this.state.colorArray}</div>);
};
};
class CreateCircle extends React.Component{
render(){
var circleStyle = {
padding: 10,
margin: 20,
display: “inline-block”,
backgroundColor: this.props.bgColor,
borderRadius: “50%”,
width: 100,
height: 100,
};
return (<div style={circleStyle}></div>);
}
};
ReactDOM.render(
<Circle/>
,container
)
</script>
</body>
</html>
React 中的事件
事件的意义不用多说,事件是页面与用户交互的唯一途径,人机交互大部分还是通过鼠标和键盘吧,当然还有像手写板、麦克风、摄像头等设备,但截至今日前端貌似没有什么权限,不然安全性就太差了。
在 React 中,事件的绑定大致和原生网页相似,大概也就是命名方式不同和 this 的指向不同这两点区别。
可以参考:https://reactjs.org/docs/hand…
在 React 中绑定事件
直接绑定
class Button extends React.Component{
render(){
return (<button onClick=”console.log(‘Hello gotham’)”>Click me!</button>)
}
}
WHAT??这不是和原生的一模一样吗?是呀,只是在命名上采用的是 React 喜爱的驼峰 Camel-Case 命名法,原生的都是小写。但这种方法多老式。
间接绑定
class Button extends React.Component{
consoleLog(){
console.log(“Hello gotham”);
}
render(){
return (<button onClick={this.consoleLog}>Click me!</button>)
}
}
将函数拿到外面去,然后在元素的事件上绑定这个函数,绑定的时候使用 JSX 的 {} 并且一定加上 this,表示绑定的是这个组件里的函数。
超级间接绑定
class Inner extends React.Component{
render(){
return (<button onClick={this.props.clickHandler}>Click me!</button>)
}
}
class Outer extends React.Component{
consoleLog(){
console.log(“Hello gotham”);
}
render(){
return (<Inner clickHandler={this.consoleLog}/>)
}
}
哈哈哈,这是什么鬼?就是利用了 React 的 props,把函数绑定在一个 props 上,本例中是 clickHandler,然后渲染了新组件,在新组件中,可以使用 this.props 来调用这个函数。简单来说就是,将函数从父组件通过 props 传递到了子组件。
this 的指向
在 React 中,绝大部分的 this 都指向组件本身。但是,在自定义的函数中,this 是没有指向的,所以会有 this is undefined 的报错,尤其是自定义的函数需要引用函数外组件内的其它资源的时候。
像下面这样写是会报错的:我们想要点击 Hello gotham 按钮调用 greeting 函数,greeting 函数会调用 gotham 函数打印 Hello gotham 字样。但是,greeting 函数里的 this 没有指向,所以会出现上面的报错。
class Welcome extends React.Component{
gotham(){
console.log(“Hello gotham”);
}
greeting(){
this.gotham();
}
render(){
return (<button onClick={this.greeting}>Hello gotham<button/>)
}
}
所以,如果想要在自定义函数中调用同组件其它资源,你有下面 3 中方法来绑定 this:
constructor 中绑定
class Welcome extends React.Component{
constructor(props){
super(props);
this.greeting = this.greeting.bind(this); ???? 这句是绑定
}
gotham(){
console.log(“Hello gotham”);
}
greeting(){
this.gotham();
}
render(){
return (<button onClick={this.greeting}>Hello gotham<button/>)
}
}
内联式绑定
class Welcome extends React.Component{
gotham(){
console.log(“Hello gotham”);
}
greeting(){
this.gotham();
}
render(){
???????????????????????? 这里是绑定
return (<button onClick={this.greeting.bind(this)}>Hello gotham<button/>)
}
}
内联式箭头函数绑定
class Welcome extends React.Component{
gotham(){
console.log(“Hello gotham”);
}
greeting(){
this.gotham();
}
render(){
???????????????????????????????????????????????? 这里是绑定
return (<button onClick={(e) => this.greeting(e)}>Hello gotham<button/>)
}
}
关于绑定 this 还可以参考:https://www.jianshu.com/p/95a…
合成事件 SyntheticEvent
React 中的合成事件可以对应为通常函数中的事件对象 event
function gotham(event){
// your codes
}
e… 这个功能有点多,你可以自己打印出来看看呀,或者看看官方文档:https://reactjs.org/docs/even…
这里只贴出来关于鼠标和键盘事件:
鼠标事件
boolean altKey
boolean ctrlKey
boolean shiftKey
boolean metaKey
number button
number buttons
number clientX
number clientY
boolean getModifierState(key)
number pageX
number pageY
DOMEventTarget relatedTarget
number screenX
number screenY
适用于如下事件:
onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp
键盘事件
boolean altKey
number charCode
boolean ctrlKey
boolean getModifierState(key)
string key
number keyCode
string locale
number location
boolean metaKey
boolean repeat
boolean shiftKey
number which
适用于如下事件:
onKeyDown onKeyPress onKeyUp
关于事件的小例子
我们的目标
点击加号按钮数字加 1,按住 shift 点击加号,数字加 10
实现思路
分割组件。底板、数字、按钮
点击按钮数字变化,所以,将资料存放于数字组件,并且通过数字组件调用按钮
键盘事件的合成事件中,能够监听 shift 键是否被按下
抛开样式的完整代码
其它的无关紧要,注意 Show 组件内的 increase 函数,我们可以看到合成事件 e.shiftKey 和 {this.increase.bind(this)} 的使用
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>react-event</title>
<script src=”https://unpkg.com/react@16/umd/react.development.js” crossorigin></script>
<script src=”https://unpkg.com/react-dom@16/umd/react-dom.development.js” crossorigin></script>
<script src=”https://unpkg.com/babel-standalone@6/babel.min.js”></script>
</head>
<body>
<div id=”container”></div>
<script type=”text/babel”>
var container = document.querySelector(“#container”);
class Button extends React.Component{
render(){
return (<button onClick={this.props.clickHandler}>+</button>)
}
}
class Show extends React.Component{
constructor(props){
super(props);
this.state = {
number: 0,
};
}
increase(e){
var num = this.state.number;
if(e.shiftKey){
num += 10;
}else{
num += 1;
}
this.setState({
number: num,
});
}
render(){
return (
<div>
<p>{this.state.number}</p>
<Button clickHandler={this.increase.bind(this)}/>
</div>
)
}
}
class Board extends React.Component{
render(){
return (
<div>
<Show/>
</div>
);
}
};
ReactDOM.render(
<Board/>,
container
)
</script>
</body>
</html>
组件的生命周期 Lifecycle
React 创造出来组件,同时也给组件配上了生命周期,用来更好的控制组件,这也是 React 的一大优势。
组建的生命周期可以参考这个:https://reactjs.org/docs/reac…。往下多翻翻~~ 这个参考资料也非常棒:https://www.w3cplus.com/react…
常用生命周期
componentDidMount()
componentDidUpdate()
componentWillUnmount()
不常用且慎用的生命周期
shouldComponentUpdate()
static getDerivedStateFromProps()
getSnapshotBeforeUpdate()
static getDerivedStateFromError()
componentDidCatch()
消失的生命周期
消失的生命周期不理他。
React Router
官方文档:https://reacttraining.com/rea…github:https://github.com/ReactTrain…
React Router 就把他看作是一个插件吧,中文名:React 路由。