React-mobile项目初始化配置/项目知识点

项目目录搭建

src

components 公共组件

pages 一些页面

assets 资源

utils 工具函数

utils.js

api 异步请求相关

redux

config 配置文件(路由配置)

routes.js

App.js

index.js

config-overrides.js

项目环境搭建

rem适配环境搭建

下载依赖包

yarn add react-app-rewired customize-cra babel-plugin-import postcss-px2rem -D
  • react-app-rewired 用于重写脚手架配置 会覆盖react教授架中的配置
  • customize-cra 是react-app-rewired依赖的包
  • babel-plugin-import 用于ant-mobile按需加载
  • postcss-px2rem 将px转成rem

React 手机组件库

yarn add antd-mobile

修改默认配置

  • 找到package.json将script修改成下面的样子
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },

创建config-overrides

  • 在项目根目录创建文件config-overrides.js(用于覆盖脚手架默认配置)
  • 和package.json package-lock.json同级
const {
  override, // 专门用来覆盖webpack配置项的
  fixBabelImports, // antd使用的一个包, 实现antd按需加载
  addPostcssPlugins, // 将我们的px-> rem的包
  addDecoratorsLegacy
} = require('customize-cra')

module.exports = override(
  // antd按需加载
  fixBabelImports('import', {
    libraryName: 'antd-mobile',
    style: 'css'
  }),
  // rem适配. 将px改为rem
  // remUnit: 表示以iphone6手机为例的跟字体
  // 值为 37.5时, 表示使用rem方式二的方式进行适配
  // 值为 100是, 表示使用rem方式一的方式进行适配
  // 注意: 这个插件,仅仅是帮助我们将px改成rem. 设置根字体这个事,还需要程序员自己做
  addPostcssPlugins([require('postcss-px2rem')({ remUnit: 100 })]),
  // 使用修饰符语法,针对rc-form这个组件使用
  addDecoratorsLegacy()
)

在utils目录定义移动端适配代码

// 定义移动端适配的代码

function adapter() {
  // 计算字体的大小
  //   const fontSize = document.documentElement.client / 10;
  const fontSize = (document.documentElement.clientWidth * 100) / 375;
  // 设置给根标签
  document.documentElement.style.fontSize = fontSize + "px";
}
adapter()
window.onresize = adapter

在index.js中引入适配rem的文件

import React from "react"
import ReactDOM from "react-dom"

import App from "./APP"

/* 
    引入rem适配的代码 fixled.js这个文件,并没有导入任何内容,只是需要执行一下,所以import后面直接写路径即可
*/
import "./utils/fixed"

ReactDOM.render(<App/>,document.getElementById("root"))

测试

  • 添加app.css文件,给app默认div设置样式,检查这些插件是否生效
*{
    margin:0;
    padding: 0;
}

#box{
    width: 345px;
    height: 150px;
    margin: 15px;
    background-color: red;
}

路由搭建

react-router-dom

 yarn add react-router-dom 

routers.js

  • 在config下面创建routers.js
import React from "react";

const Home = React.lazy(() => import("../pages/Home"));
const Login = React.lazy(() => import("../pages/Login"));
const RegisterPhone = React.lazy(() =>
  import("../pages/Register/RegisterPhone/RegisterPhone")
);
const RegisterCode = React.lazy(() =>
  import("../pages/Register/RegisterCode/RegisterCode")
);
const RegisterPassword = React.lazy(() =>
  import("../pages/Register/RegisterPassword")
);

const RegisterCountry = React.lazy(() => import("../pages/Country"));

// 定义一个数组. 数组里面有多个个数据, 对应的就会动态的渲染出来多少个Route组件
const routes = [
  {
    path: "/",
    component: Home,
    exact: true,
  },
  {
    path: "/home",
    component: Home,
  },
  {
    path: "/login",
    component: Login,
  },
  {
    path: "/register/phone",
    component: RegisterPhone,
  },
  {
    path: "/register/code",
    component: RegisterCode,
  },
  {
    path: "/country",
    component: RegisterCountry,
  },
  {
    path: "/register/password",
    component: RegisterPassword,
  },
];

export { routes };

懒加载

传统的import方式,会将代码中写的所有组件,在最开始答应页面的时候,全部加载下来.性能不好
懒加载: 就是什么时候用到这个组件了,这个组件才加载
但是: 如果使用了懒加载,必须配合suspense这个组件使用
为什么? 因为从加载组件到组件加载成功渲染到页面的这段时间.用户看到的是一个空白的屏幕,用户体验不好.最好就是展示一个正在加载的效果. suspense就是帮助我们加载这个效果的

// 传统
import Home from "../pages/Home";
import Login from "../pages/Login";

// 懒加载
const Home = React.lazy(() => import("../pages/Home"));
const Login = React.lazy(() => import("../pages/Login"));
import { lazy } from "react";
// 使用路由懒加载
// lazy不能单独使用,必须配置Suspence组件才能一起使用
const Home = lazy(() =>
  import(
     "../pages/Home"
  )
);

const routes = [
  {
    path: "/",
    component: Home,
  },
];

export default routes;

Suspense使用

  import {Suspense} from 'react'
  // 使用suspense包裹整个应用
  <Suspense fallback={正在加载的结构,可以设置加载中图片啊之类}> 
      ...结构
  </Suspense>

import React, { Component, Suspense } from "react";
import { Route, BrowserRouter as Router } from "react-router-dom";

import "./app.css";

// 引入要渲染的router
import { routes } from "./config/routes";

export default class App extends Component {
  render() {
    return (
      <Suspense fallback={<div>loading.......</div>}>
        <Router>
          {routes.map((item) => {
            return (
              <Route
                key={item.path}
                path={item.path}
                component={item.component}
                exact={item.exact}
              ></Route>
            );
          })}
        </Router>
      </Suspense>
    );
  }
}

项目

搭建页面

使用antd-mobile组件

标题 NavBar

文本输入 InputItem

上下空白 WhiteSpace

左右空白 WingBlank

警告框 Modal

表单校验

使用rc-form库实现
受控组件建议使用rc-form

安装

yarn add rc-form

引入高阶组件函数

import { createForm } from 'rc-form'

调用createForm()()

  • 将要进行表单效验的组件,传入createForm的第二次调用
  • 使用createForm 得到一个高级组件. 这个高阶组件,会自动传入一个form对象给当前这个组件
export default createForm()(VerifyPhone)

在InputItem使用表单效验

  • 通过props获取. form对象身上有一个getFieldProps函数,可以帮助我们做表单校验
const { getFieldProps } = this.props.form
<InputItem
// getFieldProps第一个参数是字段名, 第二个参数可以忽略, 第三个参数是一个对象
    {...getFieldProps('phone', {
        // rules表示当前表单的校验规则
        rules: [
            {
                // validator表示使用自定义校验规则
                validator: this.validator
            }
        ]
    })}
	clear
	placeholder='请输入手机号'
>
</InputItem>

this.getFieldValue(字段名)

  • 可以获取到我们通过getFieldProps设置的字段名里的值
const phone = this.props.form.getFieldValue('phone')

定义validator函数

validator = (rule, value, callback) => {
     // 第一个参数是一个对象.可以获取到表单量字段名
     // 第二个参数是表单项的值
     // 第三个参数是一个回调函数,必须手动调用一个,表示验证成功
    let isDisabled = true
    if (/^1[3456789][\d]{9}$/.test(value)) {
      isDisabled = false
    }
    this.setState({
      isDisabled
    })
    callback()
  }

Object.keys()

会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

// simple array
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']

// getFoo is a property which isn't enumerable
var myObj = Object.create({}, {
  getFoo: {
    value: function () { return this.foo; }
  } 
});
myObj.foo = 1;
console.log(Object.keys(myObj)); // console: ['foo']

localStorage.setItem( keyName, keyValue)

setItem() 作为 Storage 接口的方法,接受一个键名和值作为参数,将会把键名添加到存储中,如果键名已存在,则更新其对应的值。

  • 注意:localStorage只能存储字符串,不能存储对象和数组
  • 如果要存储数组/对象,应该将数组/对象转成JSON格式的字符串,然后再存储
    下面的函数在本地存储中创建三个数据项。
function populateStorage() {
  localStorage.setItem('bgcolor', 'red');
  localStorage.setItem('font', 'Helvetica');
  localStorage.setItem('image', 'myCat.png');
}
  • 存储对象和数组
     var arr = [{ name: 'zs' }, { age: 18 }]
     // 如果要存数组/对象,应该将数组/对象转成json格式的字符串,然后再存储
     const arrStr = JSON.stringify(arr)
     localStorage.setItem('test', arrStr)

     const str = localStorage.getItem('test')
     console.log(str)
     const res = JSON.parse(str)
     console.log(res)

localStorage.getItem()

getItem() 作为 Storage 接口的方法,接受一个键名(key name)作为参数,并返回对应键名的值(key’s value)。

const phone = this.props.location.state.phone
const phone = localStorage.getItem('phone')

this.props.location.state.xxx

  • 可以获取到push和replace方法传递过来的第二个参数
 const phone = this.props.location.state.phone

 this.props.history.replace('/register/phone', {
      phone
    })

axios

GET

import axios from 'axios'
export function getCountryData() {
  return axios('/common/countryData', {
    method: 'GET'
  })
}

POST

export function loginPhone(phone, code) {
  return axios('/login/phone', {
    method: 'POST',
    data: {
      phone,
      code
    }
  })
}

解决跨域问题

在package.json中添加proxy以后,发送ajax请求直接写地址就好,不需要写服务器地址
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值