用React搭建渲染一个前端页面

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);
}

 

有很多改写和参考的地方,新手可以参考学习。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

持续学习的工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值