用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/[email protected]/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);
}

 

有很多改寫和參考的地方,新手可以參考學習。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章