前端小记及react入门

1、前端开发的演变

本文介绍前端开发的历史和趋势,帮助大家了解 React 要解决什么问题。

1.1 静态页面阶段

互联网发展的早期,网站的前后端开发是一体的,即前端代码是后端代码的一部分。

  1. 后端收到浏览器的请求
  2. 生成静态页面
  3. 发送到浏览器

那时的前端页面都是静态的,所有前端代码和前端数据都是后端生成的。前端只是纯粹的展示功能,脚本的作用只是增加一些特殊效果,比如那时很流行用脚本控制页面上飞来飞去的广告。

那时的网站开发,采用的是后端 MVC 模式

  • Model(模型层):提供/保存数据
  • Controller(控制层):数据处理,实现业务逻辑
  • View(视图层):展示数据,提供用户界面

前端只是后端 MVC 的 V。

1.2 AJAX 阶段

2004年,AJAX 技术诞生,改变了前端开发。Gmail 和 Google 地图这样革命性的产品出现,使得开发者发现,前端的作用不仅仅是展示页面,还可以管理数据并与用户互动。

AJAX 技术指的是脚本独立向服务器请求数据,拿到数据以后,进行处理并更新网页。整个过程中,后端只是负责提供数据,其他事情都由前端处理。前端不再是后端的模板,而是实现了从“获取数据 --》 处理数据 --》展示数据”的完整业务逻辑。

就是从这个阶段开始,前端脚本开始变得复杂,不再仅仅是一些玩具性的功能。

1.3 前端 MVC 阶段

前端代码有了读写数据、处理数据、生成视图等功能,因此迫切需要辅助工具,方便开发者组织代码。这导致了前端 MVC 框架的诞生。

2010年,第一个前端 MVC 框架 Backbone.js 诞生。它基本上是把 MVC 模式搬到了前端,但是只有 M (读写数据)和 V(展示数据),没有 C(处理数据)。因为,Backbone 认为前端 Controller 与后端不同,不需要、也不应该处理业务逻辑,只需要处理 UI 逻辑,响应用户的一举一动。所以,数据处理都放在后端,前端只用事件响应处理 UI 逻辑(用户操作)。

后来,更多的前端 MVC 框架出现。另一些框架提出 MVVM 模式,用 View Model 代替 Controller。MVVM 模式也将前端应用分成三个部分。

扫描二维码关注公众号,回复: 4474959 查看本文章
  • Model:读写数据
  • View:展示数据
  • View-Model:数据处理

View Model 是简化的 Controller,所有的数据逻辑都放在这个部分。它的唯一作用就是为 View 提供处理好的数据,不含其他逻辑。也就是说,Model 拿到数据以后,View Model 将数据处理成视图层(View)需要的格式,在视图层展示出来。

这个模型的特点是 View 绑定 View Model。如果 View Model 的数据变了,View(视图层)也跟着变了;反之亦然,如果用户在视图层修改了数据,也立刻反映在 View Model。整个过程完全不需要手工处理。

1.4 SPA 阶段

前端可以做到读写数据、切换视图、用户交互,这意味着,网页其实是一个应用程序,而不是信息的纯展示。这种单张网页的应用程序称为 SPA(single-page application)。

所谓 SPA,就是指在一张网页(single page)上,通过良好的体验,模拟出多页面应用程序(application)。用户的浏览器只需要将网页载入一次,然后所有操作都可以在这张页面上完成,带有迅速的响应和虚拟的页面切换。

随着 SPA 的兴起,2010年后,前端工程师从开发页面(切模板),逐渐变成了开发“前端应用”(跑在浏览器里面的应用程序)。

目前,最流行的前端框架 Vue、Angular、React 等等,都属于 SPA 开发框架。

1.5 React 的定位

React 本身的定位很单纯,它是一个网页组件的解决方案。也就是说,它只解决怎么把复杂的页面拆分成一个个组件,然后一个个独立的组件又怎么拼装成可以互相协同的网页

2、组件

我们用React编写前端其实就是在编写一个个组件

2.1 组件是什么?

按照功能划分,一张网页可以由多个互相独立的功能单位组成,这种功能单位就叫做“组件”(component)。比如,典型的网页分成页头、内容、页尾三个部分,就可以写成三个组件:Header、Content、Footer。这些组件拼装在一起,就构成了一张页面。

Header、Content、Sider3个组件拼接成了一个页面。Header、Content、Footer我们可以自己编写。当然为了提高开发效率,我们可以使用别人已经封装好了的组件库antd

2.2 组件的优势

组件的好处有很多,下面是其中几点。

  • 有利于细化 UI 逻辑,不同的组件负责不同的功能点。
  • 有利于代码复用,多个页面可以使用同样的组件。
  • 有利于人员分工,不同的工程师负责不同的组件。

React 的核心概念就是组件。

2.3 组件划分

  • 可以按UI块划分
  • 可以按功能块划分

3、React

react的基础知识看官网react中文官网

3.1 React组件

React做的其实就是编写React组件,将React组件拼成页面,页面本质也是一个大的组件。

React组件分为两种:

  • 函数组件
  • 类组件
//函数组件
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;            //props是外界传给组件的属性
}

//类组件
class MyComponent extends React.Component{       
    render(){
        return (
        	<div>hello {this.props.name}</div>
        )
    }
}

当编写简单的组件时可以用函数组件。当编写复杂的组件,如要用到生命周期、需要注入store、route时就用类组件。

编写组件的步骤:

  1. 引入组件需要的依赖
  2. 编写组件
  3. 导出组件
import { Component } from 'react';       
import { Layout } from 'antd';                                  //引入依赖

// Header, Footer, Sider, Content组件在Layout组件模块下
const { Header, Footer, Sider, Content } = Layout;

class BasicLayout extends Component {                         //编写组件,
    //处理用户点击事件
    clickHandle = () => {
        console.log('hello')
    }
    
    render() {
        return (
            <Layout>
                <Sider>Sider</Sider>
                <Layout>
                    <button onClick={this.clickHandle}>click</button>
                    <Header>Header</Header>
                    <Content>Content</Content>
                    <Footer>Footer</Footer>
                </Layout>
            </Layout>
        )
    }
}

export default BasicLayout;

类组件必须提供render函数用来返回一个视图。

3.2 props

props是外界传递给组件的只读属性(不可修改),当我们要使用route、store时,使用注解实际上就是将route、store信息绑定到了props对象上。通过props的属性就可以拿到我们想要的。

import React from 'react'
import {observer,inject} from 'mobx-react'
import {withRouter} from 'react-router-dom'

@withRouter @inject('masterDatabaseStore') @form @observer     //ES7的修饰器语法注解到组件上,
class MasterDatabase extends React.Component{
    render(){
        console.log('this.props',this.props)
        return (
       		<div>
            	...
            </div> 
        )
    }
}

export default MasterDatabase

可以看到store和路由信息都已经绑定到props对象中去了。我们通过this.props.masterDatabaseStore可以拿到store状态。

3.3 state

props是不可改变的,react的状态定义到state中,通过调用this.setState()方法来改变状态,setState会自动调用组件的render方法来刷新视图。

当我们将页面拆分为不同的组件后,组件之间是相互隔离的,A组件中的状态不能直接在B组件中使用,反之亦然。React提供了状态提升来解决不同组件之间的通信问题,但是过于麻烦。我们使用mobx来管理状态。

4、mobx

mobx官网

为了方便代码维护,我们将页面细分成了更小的功能、UI组件,这样不仅代码易维护还能复用组件。拆分后的组件之间如何通信?

当页面需要拆分成不同的组件后,组件之前的状态传递就需要用到store来传递和共享

React 和 MobX 是一对强力组合。React 通过提供机制把应用状态转换为可渲染组件树并对其进行渲染。而MobX提供机制来存储和更新应用状态供 React 使用

state状态只能在定义的组件中使用,而mobx的定义的store能在所有页面中使用,不仅解决了组件之间的通信问题,还将数据与视图完成分离:store中编写状态,react中定义视图。符合后端人员的思想

4.1 MobX 要点

  1. 定义可观察的状
  2. 创建视图
  3. 改变状态
  4. 页面更新
class TestStore {
    @observable name                //定义可观察的状态

    constructor (){
        this.name = 'lazyliang'
    }


    @computed get age(){
        return this.name + '24'
    }
    
    @action                               //在action中改变状态,
    changeName = ()=>{
        this.name = 'hhhh'
    }
}

...
@observer                                //监测状态
class Test extends React.Component{
    render(){
        return (
            <div>
                <div>name:{testStore.name}</div>
                <button onClick={testStore.changeName}>改变name</button>
            </div>
        )
    }
}

action 包装/装饰器只会对当前运行的函数作出反应,而不会对当前运行函数所调用的函数(不包含在当前函数之内)作出反应! 这意味着如果 action 中存在 setTimeout、promise 的 thenasync 语句,并且在回调函数中某些状态改变了,那么这些回调函数也应该包装在 action 中。创建异步 action 有几种方式。

当store状态在回调函数中改变或在异步函数后改变,则需要runInAction来改变状态

@action
changeName = ()=>{      
    setTimeout(()=>{                       //在回调函数中改变状态要用runInAction
        // this.name = "hhhh"
        runInAction(() => {
            this.name = "hhhh"
        })
    },1000)
}

@action
changeName = async ()=>{             
    await handle()                    //在异步函数后改变状态要用runInAction
    // this.name = 'hhh'
    runInAction(() => {
        this.name = "hhhh"
    })

}

5、路由

react-router4简约教程

一个路由匹配一个组件

6、项目

我目前所在公司的项目所需的技术栈为:

  • React
  • antd
  • mobx
  • React-router
  • ES6

6.1 项目简介

在node下使用webpack构建react开发环境,node是运行引擎,通过他可以直接在后端运行js语法,webpack是打包工具。
本项目使用 create-react-app 快速构建 React 开发环境,create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境。

1、node的安装

我们使用的webpack是基于nodejs的环境下开发的,可以看看自己的电脑中有没有安装node。打开命令窗口。输入node -v 就可以查看自己的node版本。
如果没有安装,请到nodejs中文网安装node。

2、命令行工具

一般而言,安装了node之后,npm自动集成在node环境中,你的电脑也会自动安装了npm。可以直接使用命令 npm -v 查看npm版本。
国内使用 npm 速度很慢,使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm 或者是直接 yarn

$ npm install -g cnpm --registry=https://registry.npm.taobao.org
3、webpack
cnpm install -g webpack  //全局安装了webpack

//对这个命令的解读。 
npm install 是下载命令。 
-g是以全局方式下载 
webpack是下载的内容。

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler),作用:

① 模块化开发(import,require)

import与require的区别

② 预处理(Less,Sass,ES6,TypeScript……)

③ 对主流框架脚手架支持(Vue,React,Angular)

4、react前端框架

react 是一个基于 mvvm (Model-View-ViewModel)模式的组件化开发的 web 框架。
通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。

5、React-router 路由管理

react-router:新的基本特性,看完获益颇丰。

区分React-routerReact-router-dom

6、antd 是前端UI框架

这里是 Ant Design 的 React 实现,开发和服务于企业级后台产品。

$ cnpm install antd --save  
$ yarn add antd  

6.2 新项目结构

├── components                            # 所有项目可复用的组件
│   ├── system                            # 系统基础模块
│   │   ├── Role
│   │   └── User     
│   ├── LinkButton.js                    
│   └── SideMenu.js    
├── framework                             # 所有项目可共用的工具类
│   ├── utils                             # 工具函数
│   │   ├── ajax.js                      
│   │   └── Section.js     
│   ├── LoadableComponent.js              # 组件懒加载,代码拆分函数
│   └── PrivateRoute.js                   # 路由验证函数
├── xxx                                 # 项目
│   ├── components                        # 项目可复用的组件
│   ├── locales                           # 国际化
│   ├── routers                           
│   │   ├── backend                       # 后台模块
│   │   ├── frontend                      # 前台模块
│   │   ├── home                          # 首页模块
│   │   ├── backend.js                    # 后台路由
│   │   ├── frontend.js                   # 前台路由
│   │   └── home.js                       # 首页路由
│   ├── stores                            # 项目store
│   └── config.js                         # 项目配置                       
├── stores                                # 项目路由(根据env配置选择) 
├── App.js                                # React根组件
└── index.js                              # 项目入口文件

6.3 项目路由

在老项目中,路由没有分公司,所有项目都在一个文件中,比如后台路由都写在main.js中

导致的问题就是路由不清晰,维护困难

新项目中,项目的路由统一放在项目目录文件中。路由从main.js中抽到单个项目的backend.js文件里

新项目封装了一个组件来进行路由验证,所以现在路由和以前有点区别,比如后台路由写法:

//backend.js
import React from 'react'
import PrivateRoute from '../../framework/PrivateRoute'
import LoadableComponent from '../../framework/LoadableComponent'

export default [
  <PrivateRoute 
    key="backend_user" 
    path="/backend/user" 
    component={LoadableComponent(import('./backend/system/User'))}/>,
  <PrivateRoute 
	key="backend_role" 
	path="/backend/role" 
	component={LoadableComponent(import('./backend/system/Role'))}/>,
]

PrivateRoute是新封装的一个路由验证组件和Route类似,不过当未登录时会重定向到登录页面;path是页面路由;component是组件,LoadableComponent用于组件懒加载和代码拆分

6.4 项目store

和路由类似,在老项目中所有项目都放在src下的store文件中,在index.js中就会将所有store注入到react中。在新项目中可以看到目录结构发生了变化

├── xxx                                   # 项目
│   ├── components                        # 项目可复用的组件
│   ├── locales                           # 国际化
│   ├── routers                           
│   │   ├── backend                       # 后台模块
│   │   ├── frontend                      # 前台模块
│   │   ├── home                          # 首页模块
│   │   ├── backend.js                    # 后台路由
│   │   ├── frontend.js                   # 前台路由
│   │   └── home.js                       # 首页路由
│   ├── stores                            # 项目store
│   └── config.js                         # 项目配置

路由和store都放在了项目目录中,

src下的store文件变成了:

import localeStore from './LocaleStore'
//根据env文件的配置动态引入项目store,老项目是将所有项目的store放在了下面
const stores = require(`../${process.env.REACT_APP_PROJECT_NAME}/stores`)

export default {
  ...stores.default
}

6.5 命名

组件一律以大驼峰命名法(首字母大写)

文件名以小写命名

猜你喜欢

转载自blog.csdn.net/qq_38224158/article/details/84391713
今日推荐