使用Webpack的话,项目的整体结果是这样的:
</>复制代码
-webapp
|--public // webpack 编译打包后的js文件所在目录
|--css // css文件所在的目录
|--src // 使用React编写的代码所在目录
|--index.html // HTML页面
如果你使用网页内部加载React的话,那么就直接在public目录下创建一个bundle.js文件,并在index.html引用即可。
我们就以一个用户登录的界面喂例子。登录,用户需呀输入用户名、密码,然后点击登录按钮。
React代码我们来看看要实现这个功能React代码应该什么样的。
</>复制代码
import React from "react";
import {render} from "react-dom";
import LabeledInputText from "./LabeledInputText";
import SubmitButton from "./SubmitButton";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {un: "", pwd: ""};
this.handleLogin = this.handleLogin.bind(this);
this.handleUserNameChanged = this.handleUserNameChanged.bind(this);
this.handlePasswordChanged = this.handlePasswordChanged.bind(this);
}
handleUserNameChanged(un) {
this.setState({un: un});
}
handlePasswordChanged(pwd) {
this.setState({pwd: pwd});
}
handleLogin() {
// $.ajax({
// url: this.props.url,
// dataType: "json",
// method: "POST",
// data: this.state,
// cache: false,
// success: function(data) {
// this.setState({data: data});
// }.bind(this),
// error: function(xhr, status, err) {
// console.error(this.props.url, status, err.toString());
// }.bind(this)
// });
alert(`${this.state.un}, ${this.state.pwd}`);
}
render() {
var divStyle = {
color: "blue",
wdith: "150px",
paddingTop: "10px",
display: "inline-block"
};
return (
Yo, React
);
}
}
render(, document.getElementById("content"));
// LabeledInputText
import React from "react";
export default class LabeledInputText extends React.Component {
constructor(props) {
super(props);
this.handleTextChange = this.handleTextChange.bind(this);
}
handleTextChange(e) {
if (this.props.labelText.toLowerCase() == "username") {
this.props.onUserNameChanged(e.target.value);
} else {
this.props.onPasswordChanged(e.target.value);
}
}
render() {
return (
{`${this.props.labelText} :`}
);
}
}
// SubmitButton
import React from "react";
export default class SubmitButton extends React.Component {
constructor(props) {
super(props);
// this.state = {value: ""};
// bind event handler
this.handleLogin = this.handleLogin.bind(this);
}
handleLogin(e) {
// this.setState({value: e.target.value});
// alert("hello react");
this.props.onLogin()
}
render() {
return (
);
}
}
App类是这个登录界面的整体。里面的HTML元素可以分为两类,一个是label和label后面的输入框,另一类是提交按钮。
LabeledInputText是label和输入框的组合。SubmitButton是提交按钮。
生成出来的HTML页面是这样的:
</>复制代码
<span class="hljs-attr">Add</span> <span class="hljs-string">style to React</span>
Yo, React
Username :
Password :
在添加样式之后,效果是这样的:
在React组件上使用CSS样式比你想的还要简单。因为最终React还是把组件都转化成了HTML元素,而你会的各种CSS技巧一样都可以作用在这些元素上。但是还是有一些小小的地方需要注意:
理解生成的HTML在使用CSS之前,你需要知道React生成的HTML元素是什么样子的。看起来很容易理解,因为JSX语法和HTML元素非常接近。
</>复制代码
import React from "react";
import {render} from "react-dom";
import LabeledInputText from "./LabeledInputText";
import SubmitButton from "./SubmitButton";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {un: "", pwd: ""};
}
render() {
var divStyle = {
color: "blue",
wdith: "150px",
paddingTop: "10px",
display: "inline-block"
};
return (
//
{/* Yo, React
*/}
);
}
}
render(, document.getElementById("content"));
在render方法里的就是整体的React组件的结构。所有的东西都在一个div里面。LabeledInputText就是一个文字Label和一个input的文本输入框的组合。SubmitButton是一个可以点击的按钮,这里其实是一个含有click事件的div。
全部组件生成HTML之后:
</>复制代码
Username :
Password :
Click
里面一些div包含的各种元素,就如前文所说的一样。另外还有的就是很多的css的class。
React中使用CSS首先添加css样式文件:
</>复制代码
input:focus{
outline: none !important;
border:1px solid red;
/*box-shadow: 0 0 10px #719ECE;*/
}
.box-group {
width:230px;
border: 1px solid blue;
padding:5px;
margin: 10px;
}
.form-control {
padding:5px;
}
.form-under {
margin-top:10px;
}
.form-button {
display:block;
background-color:red;
text-align: center;
}
上面就是main.css文件包含的全部的样式。这些样式主要是给登录的整个界面元素的边框设置为蓝色,然后在用户名、密码和登录按钮之间增加间距,最后给按钮指定背景色为红色。
接下来需要在React的组件中使用这些样式。但是直接使用class是不行的。毕竟JSX和HTML元素是有区别的。就以登录按钮为例:
</>复制代码
{this.props.title}
在React中指定class名称使用className。React的className最后就会转化成HTML的class。
这个登录按钮的样式有一点复杂:className="form-control form-under form-button"使用了三个不同的css的selector。这些selector的样式都会应用到这个登录按钮上。
用React的方式来添加样式React推崇的是内联的方式定义样式。这样做的目的就在于让你的组件更加的容易复用。和组件相关的全部内容聚合到一起,包括你的组件看起来是什么样的,是如何工作的。
下面就把之前添加的全部的样式className都去掉,回到最开始的状态。
</>复制代码
/* index.js */
{/* Yo, React
*/}
/*LabeledInputText*/
{`${this.props.labelText} :`}
/*SubmitButton*/
{this.props.title}
登录使用的三个组件的render方法返回的内容的className已经全部都去掉了。
要往React组件内添加一个自定义的样式对象,这个对象包含的就是css样式的名称和样式的值。只不过样式的名称不是css的background-color而是JSX的backgroundColor。例如:
</>复制代码
let divStyle = {
width:"230px",
border: "1px solid blue",
padding:"5px",
margin: "10px"
};
return (
{/* Yo, React
*/}
);
小贴士
</>复制代码
在React里注释不能用HTML的方式,那是木有用的。也不能直接用js的
注释,那也是不行的。而是用大括号括起来,之后用/**/来注释。
看起来是这样的`{/* 这是一个注释 */}`。
divStyle就是我们定义的样式对象。要使用这个样式,只要在React组件中给style赋值。如:style={divStyle}。
让样式可以自定义要让组件的子组件的某些样式可以自定义很简单。只需要使用React组件的props。比如,我现在想要定制不同的用户名、密码输入框的边框颜色。
</>复制代码
{/* Yo, React
*/}
之后在LabeledInputText文件中:
</>复制代码
styleObj = Object.assign({}, this.pwdStyle, {border: "1px solid " + this.props.bordercolor});
每次需要用到边框值的时候都从props里面取:this.props.bordercolor。
根据不同的状态显示不同颜色HTML的文本输入框有两种状态,focused和blured。用户要输入内容的时候,文本框就在focus的状态下。用户的焦点移开,比如开始输入密码的时候,用户名的文本框就在blur状态下了。
在focus的状态下的时候,显示指定颜色的边框,否则不显示边框。这个时候就要用到React的另一个重要概念:State。
首先,给input注册focus和blur的事件处理方法。
</>复制代码
// hanleFocus & handleBlur
handleFocus() {
this.setState({focused: true});
}
handleBlur() {
this.setState({focused: false});
}
状态都存在state里了。然后在input里指定style:style={this.getInputStyles()}。getInputStyles方法就会根据不同的状态返回不同的样式。
</>复制代码
getInputStyles() {
let styleObj;
if (this.state.focused == true) {
styleObj = {outlineStyle: "none"};
}
return styleObj;
}
这个方法在focus的时候去除了input默认的效果,blur的时候保持原样。
最后随着React学习的深入,你会发现React添加样式的方式和之前的方式大有不同。如果你透过上面的例子收入思考的话你会发现,之所以React使用了和以往不同的添加样式方法是有原因的。HTML、CSS和Javascript这样的传统方法在处理网页的时候是非常有用的,但是在处理React组件组成的复杂的界面的web app的时候却显得力不从心。