网页总是一个链接着另一个的,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
路由。作为一个小白,我怎么会对这个技术的深层理论进行研究,我只知道他有一个我觉得很好用的功能:局部更新页面,并且不用刷新加载新页面,快速、用户体验好。
React Router
的效果
看他的样子平平无奇,别别别,这多好呀!不用刷新重新加载就能更新局部页面,看上去又很流畅、代码量不多、兼容性React
也帮助你完成了,皆大欢喜~
React Router
的引入
React Router
的官方文档教你使用npm
安装,但是像我这样不喜欢往电脑里装杂七杂八东西的人,还可以使用不同的cdn
引入,或者进入你选择的cdn
的网址,把你要的复制到本地文件里再引用
-
unpkg
这是一个cdn
它的官网:https://unpkg.com/
中文介绍可以看这篇:https://yq.aliyun.com/article...
使用unpkg
引入React Router
请看下面:<script src="https://unpkg.com/react-router/umd/react-router.min.js"></script> <script src="https://unpkg.com/react-router-dom/umd/react-router-dom.min.js"></script>
-
cdnjs
这是一个cdn
它的官网:https://cdnjs.com/
中文介绍:进入官网,搜索你想要的<script>
使用cdnjs
引入React Router
请看下面(截止至2019-2-18):<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.3.1/react-router.min.js"><script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-router-dom/4.3.1/react-router-dom.min.js"></script>
React Router
的使用
通过上述的内容,我们能够正确的使用React
框架搭建一个网页,使用React Router
需要在组件中修改一点内容,并在随后的ReactDOM.render()
中添加像下面这样的渲染内容:
<script type="text/babel">
var {HashRouter,Switch,Link,Route} = window.ReactRouterDOM;
class Header extends React.Component {
render() {
return (
<header>
<img id="logoCo" src="./img/logo-1.png"/>
<div className="verticalLine"></div>
<img src="./img/logo-2-2.png" width="100px"/>
<nav>
<ul className="clearfix">
<li><Link to="/home">首页</Link></li>
<li><Link to="/case">案例成效</Link></li>
</ul>
</nav>
</header>
);
}
}
class Case extends React.Component{
// your codes
render(){
return(
// anything, mostly JSX, you want to return
);
}
}
ReactDOM.render(
<HashRouter>
<div>
<Header/>
<Route exact path="/" component={Home}/>
<Route path="/home" component={Home}/>
<Route path="/case" component={Case}/>
<Footer/>
</div>
</HashRouter>,
container
)
</script>
所有,只需要上面这些代码就OK了?我书读的真的少。。。。。。
如果只是要实现白菜功能,像是不管内容怎么变化,总有一条导航栏不变的需求,那这么点代码就ok啦,当然,再加上上面使用React
写的组件。
实例中到底写了什么?
- 首先,搭建
React
框架,引入React
、构建组件Component
、渲染页面ReactDOM.render
- 撰写
<script type="text/babel">
,注意!!!type="text/babel"
必须要加 -
引入
window.ReactRouterDOM
,var {HashRouter,Link,Route} = window.ReactRouterDOM;
上面
ES6
写法,等于:var HashRouter = window.ReactRouterDOM.HashRouter; var Link = window.ReactRouterDOM.Link; var Route = window.ReactRouterDOM.Router;
-
ReactDOM.render
中必须、只能渲染一个元素,所以使用React Router
提供的<HashRouter>
,然后,<HashRouter>
中也必须只能有一个子元素,所以,加上一个<div>
十分安全 - 下面,渲染了一个
<Header/>
组件,直接渲染,没有杂七杂八的东西,这个就是永恒不变的导航栏。所以,如果你需要页面上的某些元素不变,那就直接在React Router
中直接渲染 - 接下来,渲染需要改变的部分。方法就是使用
React Router
提供的<Router>
来渲染组件。其基本的属性要求一个path
来说明在哪个地址下渲染某个组件、一个component
来说明在某个地址下渲染哪个组件。exact
的意思是必须一丝不差的匹配地址,组件才能被渲染。 - 一般,我们是单击导航栏中的链接再更新页面内容,所以我们必须将链接和对应的组件联系在一起。方法就是将通常我们会使用的链接标签
<a>
修改为<Link to="地址">我是一个链接</Link>
总结:将组件中的链接元素用<Link>
代替,在ReactDOM.render
中将路径和组件关联上
上述内容都是极易写错导致报错的点,多加小心
通过上面的实例,页面会在不同的地址下,更新局部页面。使用<Router>
渲染的组件就是会被更新的内容,虽然可能写了很多个<Router>
,但是他们都会在相同的地方被渲染,且一个地址只会渲染一个组件。
更多React Router
- 我们在例子中,总路由使用的是
<HashRouter>
,应对不同的情况,总路由还可能是<BrowserRouter>
、<MemoryRouter>
、<NativeRouter>
、<StaticRouter>
等,具体可以参见相关官方文档、这篇简书。 -
<Router>
的更多属性可以参见相关官方文档、这篇简书 - 初学者教程可以参考这个,本文也有很多内容出自:https://www.w3cplus.com/react...
- 这篇简书很好:https://www.jianshu.com/p/6a4...
- 这两个网站也可以随便看看:
https://segmentfault.com/a/11...
https://www.cnblogs.com/qiang... - 这个问题关于引入
window.ReactRouterDOM
错误,参考第二个答案:
https://stackoverflow.com/que...
本文还可能更新的内容
-
React Router
嵌套,额并不是像其它的嵌套一样:<Router><Router></Router></Router>
。这里嵌套的意思是在变化的局部页面里,又有一部分内容是不变的,仅针对这个局部页面。e。。。。。。
-
React
表单
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。