React是Facebook推出的一个前端JavaScript框架,React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用。
React框架主要用于前端页面的编写,非常的高效,而且安全。框架自动处理了前端页面相关的常见安全漏洞:如跨域攻击、SQL注入等等。React框架采用组件化思想,进行构建页面。例如我们可以把一个前端页面分成几个组件来组合:导航组件、内容组件(内容列表组件、推荐栏组件等)、底部版权等信息组件等等。这样大大提高了编写的清晰度、以及后期的可维护性、组件的复用,达到高内聚、低耦合的设计原则。
React的特点:(引用)
-
1.声明式设计 −React采用声明范式,可以轻松描述应用。
-
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
-
3.灵活 −React可以与已知的库或框架很好地配合。
-
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
-
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
-
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
-
7.安全 − React实现的单页面应用,安全性能高、常见的漏洞都已经自行处理。
那么接下来我就带领大家把最近用到的React分享一下,实现从开始搭建环境到编写出一个简单的组件化前端页面。
这里选择的开发工具是:Visual Studio Code。
一、首先我们进行React的安装。
1、最简单的引用。
我们直接在单页面应用的html里引入React库:
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
然后我们写一个最简单的页面内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="body"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('body')
);
</script>
</body>
</html>
这样我们就把我们的动态Html代码渲染添加到了指定id的DOM结点中了。是不是很简单?
其实React的核心特点就是,只需要写一个最简单的Html页面框架,内部只需要一个根<div>标签即可,后续的所有针对页面的绘制、绑定数据等都是编写React组件类来实现,然后渲染到这个根<div>标签上即可。最后编写完所有逻辑后,就直接用node命令来实现实时运行查看效果和编译成最后的页面:npm run start(实时运行查看);npm run build(编译成最终的静态页面)。
2、通过npm安装。
我们需要安装和配置Nodejs环境,Nodejs的安装非常简单,我们去Nodejs的官网下载对应的安装包安装即可。官网:https://nodejs.org/en/
下载安装后,我们就可以使用npm命令了。
如果觉得国内使用npm下载相关库慢的话,可以切换使用淘宝的npm库。
$ npm config set registry https://registry.npm.taobao.org
接下来我们就通过create-react-app命令创建react应用框架。
create-react-app 自动创建的项目是基于 Webpack + ES6 。
$ npm install -g create-react-app
$ create-react-app my-app
$ cd my-app/
$ npm start
运行后,我们在浏览器里访问http://localhost:3000/,即可看到默认的页面框架。
如果运行npm run build后,在build目录生成的页面遇到找不到相关js和css资源文件的话,可能是路径用了绝对路径,我们需要修改为相对路径引用。最新版的话是直接在项目的package.json里添加一个homepage属性字段即可。
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"homepage": "./",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-scripts": "3.4.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
二、编写综合实例单页面。
这个实例既简单有复杂,虽然页面可能不是太美观,但是涵盖了很多React和前端的东西。这里也用到了阿里巴巴的Antd:https://ant.design/。
主要把页面分成了Header组件、Body组件和Footer组件。Body组件里后续也可以再继续细分。
编写Html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>index</title>
<link rel="stylesheet" type="text/css" href="../src/index.css">
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div id="example"></div>
<div id="header"></div>
<div id="tip"></div>
<div id="web"></div>
<div id="antd" style="padding: 24px"></div>
<div id="cal"></div>
<div id="body"></div>
<div id="footer"></div>
<script type="text/babel">
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('example')
);
</script>
<!-- <script type="text/babel" src="../src/index.js"></script> -->
</body>
</html>
header.js组件
import React from 'react';
import './header.css'
import ReactDOM from 'react-dom';
class Header extends React.Component {
constructor() {
super();
this.state = { index: 0 };
}
subMenuClick(e) {
e.preventDefault();
alert('subMenu点击');
}
menuClick(index, e) {
var body = null;
switch (index) {
case 0:
body = <div>页面一,切换页面+{index}</div>;
break
case 1:
body = <div>页面二,切换页面+{index}</div>;
break
default:
break;
}
ReactDOM.render(
body,
document.getElementById('body')
);
}
render() {
return (<div className='headerContent'>
{/* <div className='header'> */}
<ul className='menu clearfix'>
<li className='menuItem' onClick={this.menuClick.bind(this, 0)}>标题1</li>
<li className='menuItem'>标题2<img className='more' src='https://raw.githubusercontent.com/google/material-design-icons/master/hardware/2x_web/ic_keyboard_arrow_down_black_48dp.png' alt='更多' />
<div id='subMenu' className='subMenu'>
<ul>
<li><a href='#' onClick={this.subMenuClick}>菜单1</a></li>
<li><a href='#'>菜单2</a></li>
</ul>
</div>
</li>
<li className='menuItem' onClick={this.menuClick.bind(this, 1)}>标题3</li>
<li className='menuItemRight'>标题4</li>
<li className='menuItemRight'>标题5</li>
</ul>
{/* </div> */}
</div>);
};
}
export {
Header
}
header.css
html,
body {
width: 100%;
height: 3000px;
/* text-align: center; */
}
.headerContent {
position: fixed;
top: 0px;
width: 100%;
height: 70px;
background: rgb(67, 163, 244);
}
.header {
max-width: 980px;
height: 70px;
position: fixed;
margin: 0 auto;
left: 0;
right: 0;
background: rgb(27, 146, 243);
/*flex 布局*/
display: flex;
/*实现垂直居中*/
align-items: center;
}
.menu {
list-style: none;
background: rgb(27, 146, 243);
max-width: 980px;
margin: 0 auto;
left: 0;
padding-left: 0;
right: 0;
width: 100%;
height: 70px;
}
.menuItem {
list-style: none;
padding: 0 10px;
height: 70px;
line-height: 70px;
float: left;
align-items: center;
cursor: pointer;
}
.menuItem:hover {
color: white;
}
.subMenu {
display: none;
}
.subMenu ul {
list-style: none;
margin: 0 auto;
left: 0;
padding-left: 0;
right: 0;
}
.subMenu li {
list-style: none;
text-align: center;
}
.subMenu li a {
color: white;
}
.menuItem:hover .subMenu {
background-color: rgb(27, 146, 243);
padding: 5px;
color: white;
list-style: none;
display: block;
}
.menuItemRight {
padding: 0 10px;
float: right;
list-style: none;
height: 70px;
line-height: 70px;
cursor: pointer;
}
.menuItemRight:hover {
color: white;
}
.clearfix::after {
content: '';
display: block;
clear: both;
}
.more {
height: 30px;
margin: 0 auto;
}
footter.js
import React from 'react';
import './footer.css'
class Footer extends React.Component {
render() {
return (<div className='footer'>
<div className='info'>Information</div>
<div className='copyRight'>copyRight</div>
</div>);
};
}
export {
Footer
}
footer.css
.footer {
margin: 0 auto;
text-align: center;
}
.info{
color: black;
}
body.js
import React from 'react';
import { Slider, Tabs } from 'antd';
import './body.css'
class Body extends React.Component {
state = {
disabled: false,
};
onAfterChange(value) {
alert(value);
}
componentDidMount() {
// alert('渲染组件');
console.log('渲染组件');
}
componentWillUnmount() {
// alert('关闭界面');
console.log('关闭界面');
}
render() {
const { disabled } = this.state;
return (<div className='bodyComponent'>
<p>Body Component</p>
<div className='slider'>
<Slider defaultValue={30} disabled={disabled} max={100} min={0} onAfterChange={this.onAfterChange} />
</div>
<div className='textArea'>
<textarea className='textArea' rows='10' wrap='soft' placeholder='输入文本...'></textarea>
</div>
<progress value='60' max='100'></progress>
<div className='photo'>
<img className='avatar'></img>
<a>名称</a>
</div>
<div className='left'></div>
<div className='right'></div>
<div className='main'></div>
<div className='layout'>
<div className='layout_left'></div>
<div className='layout_main'></div>
<div className='layout_right'></div>
</div>
<div className='animation'></div>
</div>);
}
}
export {
Body
}
body.css
.bodyComponent {
text-align: center;
}
.textArea {
width: 960px;
height: 500px;
}
.slider {
width: 20%;
padding: 20px;
background-color: peru;
}
.photo {
width: 100px;
height: 100px;
text-align: center;
}
.avatar {
width: 100px;
height: 100px;
background-color: royalblue;
border-radius: 50%;
}
.photo a {
margin-top: -20px;
padding-top: -20px;
clip-path: circle(50%);
}
.left {
width: 200px;
height: 100px;
background: #a0b3d6;
float: left;
}
.right {
width: 200px;
height: 100px;
background: #a0b3d6;
float: right;
}
.main {
height: 100px;
margin: 0 210px;
background: #ffe6b8;
}
.layout {
display: -webkit-flex;
/* Safari */
display: flex;
justify-content: space-between;
align-items: center;
}
.layout_left {
background-color: royalblue;
height: 100px;
width: 30%;
}
.layout_right {
background-color: royalblue;
height: 100px;
width: 30%;
}
.layout_main {
background-color: sandybrown;
height: 100px;
width: 30%;
}
.animation {
width: 100px;
height: 100px;
background-color: silver;
transition: .3s;
}
.animation:hover {
width: 100px;
height: 100px;
background-color: slateblue;
transform: rotate(45deg);
}
有很多改写和参考的地方,新手可以参考学习。