目录
一、Umi
简介:Umi,中文可发音为乌米,是可扩展的企业级前端应用框架。
Umi 以路由为基础的(就是解决了之前使用react-router-dom的时候使用路由的复杂度)
1.官网
(1)2.0版本:https://v2.umijs.org/
(2)3.0版本:https://v3.umijs.org/
2.安装与运行
1.全局安装 : npm install -g umi@2 或者 yarn global add umi@2
2.测试安装版本: umi -v
3.新建文件夹 把cmd的路径切换到这个文件夹下
4.开始创建项目 yarn create @umijs/umi-app 或者 npm create @umijs/umi-app
5.下载依赖:cd到你刚才创建项目的文件夹下 npm install 或者 yarn
6.运行 yarn start 或者 npm start
3.配置式路由的创建
1.在src下的pages文件夹下 新建你对应的路由页面
2.配置路由规则 在.umirc.ts文件中进行配置
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/', component: '@/pages/index' },
// 仿照默认的内容自行添加
{ path: '/home', component: '@/pages/home/home' },
{ path: '/phone', component: '@/pages/phone/phone' },
],
fastRefresh: {},
});
4.路由导航
4.1编程式--js的方式
import React from 'react'
// 注意引用是来自于umi的
import {Link,history} from "umi"
export default function Topbar() {
let fun=()=>{
// 编程式导航
history.push("/phone")
}
return (
<div>
<Link to="/">首页</Link>
<Link to="/home">home</Link>
<Link to="/phone">手机</Link>
<hr />
<button onClick={fun}>点我去手机</button>
</div>
)
}
4.2声明式--标签
借助Link 这个标签来完成,使用to属性来表明路径 。
import React from 'react'
// 注意引用是来自于umi的
import {Link} from "umi"
export default function Topbar() {
return (
<div>
<Link to="/">首页</Link>
<Link to="/home">home</Link>
<Link to="/phone">手机</Link>
</div>
)
}
5.重定向 --redirect
umirc文件里面进行配置
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/index', component: '@/pages/index' },
// 仿照默认的内容自行添加
{ path: '/home', component: '@/pages/home/home' },
{ path: '/phone', component: '@/pages/phone/phone' },
// 路由重定向 exact精准匹配
{ path: '/', redirect:"/index",exact:true },
],
fastRefresh: {},
});
6.404页面
1.创建对应404页面
2.配置404规则
import { defineConfig } from 'umi';
export default defineConfig({
nodeModulesTransform: {
type: 'none',
},
routes: [
{ path: '/index', component: '@/pages/index' },
// 仿照默认的内容自行添加
{ path: '/home', component: '@/pages/home/home' },
{ path: '/phone', component: '@/pages/phone/phone' },
// 路由重定向 exact精准匹配
{ path: '/', redirect:"/index",exact:true },
// 404页面
{ path: '*', component: '@/pages/no/no' },
],
fastRefresh: {},
});
7.多级路由
1.创建多级路由页面
2.配置多级路由规则(在对应的以及路由规则中进行嵌套)
{
path: '/home',
component: '@/pages/home/home',
// 配置多级路由
routes:[
{ path: '/home/era', component: '@/pages/er/era' },
{ path: '/home/erc', component: '@/pages/er/erc' },
]
},
3.千万不要忘了 设置二级路由出口 (在对应的路由页面中配置)props.children 多级路由的出口
8.约定式路由的创建
umi在创建路由时,我们也可以不需要配置路由规则,从而达到路由效果,这种方式就叫约定式 。
创建页面两种方式
1.手工创建:同原来
2.命令创建:在项目的根路径下 输入 umi g page 你要创建的页面名 (就会在pages文件夹下 自动创建对应的页面)
二、Dva
简介:
dva 首先是一个基于 redux 和 redux-saga 的数据流方案,然后为了简化开发体验 (dva就是对react进行了语法上面的简化 让我们在react中使用状态管理工具变得更简单)
redux-saga 就是redux进行异步操作的一个技术
1.官网
地址:DvaJS
2.安装与运行
1.全局安装 npm install -g dva-cli
2.测试 dva -v
3.cd到指定文件夹之下 dva new 你的项目名
4.cd到项目下面 npm install之后再启动
5.启动 npm start
3.路由
在dva中使用他内置的路由我们可以把路由页面创建到src下的routes文件夹中 当然我们也可以重新创建一个文件夹来容纳路由页面
1.创建路由页面
2.配置路由规则 src文件夹下的router.js文件中来进行编写
import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage';
// 1.引用路由页面
import Home from "./routes/home.jsx"
import Phone from "./routes/phone.jsx"
import User from "./routes/user.jsx"
function RouterConfig({ history }) {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={IndexPage} />
{/* 2.配置路由规则 */}
<Route path="/home" exact component={Home} />
<Route path="/phone" exact component={Phone} />
<Route path="/user" exact component={User} />
</Switch>
</Router>
);
}
export default RouterConfig;
4.路由导航
4.1编程式--js
props.history.push("/去哪里")
注意:使用编程式导航必须在被路由所管理的页面中进行才可以,否则就要使用withRouter这个高阶组件来传递路由跳转的属性
import React from 'react'
// 引用Link组件来自于dva 的路由
import {Link,withRouter} from "dva/router"
function topbar(props) {
let fun=()=>{
// 编程式导航\
// 在组件中定义了一个编程式导航
// 但是在运行的时候发现push没有定义
// 因为 在使用编程式导航的时候 由于当前组件不是被路由所管理的页面 那么他就不具备路由跳转的功能
// 就会出现push没有定义
// 所以我们就要使用HOC--高阶组件--withRouter来解决
props.history.push("/user")
}
return (
<div>
{/* 声明式导航 */}
<Link to="/">首页</Link>
<Link to="/home">home</Link>
<Link to="/phone">phone</Link>
<Link to="/user">user</Link>
{/* 编程式 */}
<button onClick={fun}>点我去user</button>
</div>
)
}
export default withRouter(topbar)
4.2声明式--标签组件
import React from 'react'
// 引用Link组件来自于dva 的路由
import {Link} from "dva/router"
export default function topbar() {
return (
<div>
{/* 声明式导航 */}
<Link to="/">首页</Link>
<Link to="/home">home</Link>
<Link to="/phone">phone</Link>
<Link to="/user">user</Link>
</div>
)
}
5.model
dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。
(dva中的model 就是用来把状态管理工具进行模块化设置的,为什么要设置模块化?
因为组件多了 数据与修改就变得很多,如果我们把一个项目的所有数据与修改都放在一起,后期维护就很麻烦,所以这个时候我们就可以进行模块拆分)
1.在src的modules文件夹中 创建对应的模块文件
2.编写内容
export default {
namespace: 'userm',//命名空间---就是给当前这个模块起个名字(唯一的)
state: {
name:"我是user模块中的数据"
},//存放数据的
subscriptions: {//类似于一个监听 在里面可以绑定很多个监听的方案
},
effects: {//类似于vuex的actions 进行异步触发的
},
reducers: {// 修改上面的state的地方
},
};
3.把我们新建的模块和项目建立关联
在srtc下的index.js中建立
import dva from 'dva';
import './index.css';
// 1. Initialize
const app = dva();
// 2. Plugins
// app.use({});
// 3. Model 就是建立我们模块与项目的位置
// app.model(require('./models/example').default);
app.model(require('./models/homem').default);
app.model(require('./models/phonem').default);
app.model(require('./models/userm').default);
// 4. Router
app.router(require('./router').default);
// 5. Start
app.start('#root');
6.读取数据
import React from 'react'
import Topbar from "../components/topbar.jsx"
// 1.引用组件和模块的链接工具--connect 是一个方法 当这个方法被调用的时候他才是一个链接的高阶组件
import { connect } from 'dva'
function Home(props) {
return (
<div>
<Topbar></Topbar>
{/* props.state.你要引用的模块的命名空间名字.数据名 */}
<h1>我想读取dva中模块的数据----{props.state.homem.name}</h1>
<h1>我想读取dva中另一个模块的数据----{props.state.userm.name}</h1>
</div>
)
}
// 2.设置数据
export default connect(state=>({state}))(Home)
7.修改数据
1.在组件内通过dispatch来触发修改
import React from 'react'
import Topbar from "../components/topbar.jsx"
import { connect } from 'dva'
function Phone(props) {
let fun=()=>{
// 触发dva的数据修改
// dispatch({type:模块的命名空间名字/你的reducer的名字})
props.dispatch({type:"phonem/UP_NAME"})
}
return (
<div>
<Topbar></Topbar>
phone----{props.state.phonem.name}
<button onClick={fun}>点我修改数据</button>
</div>
)
}
export default connect(state=>({state}))(Phone)
2.编写对应修改的reducers
export default {
namespace: 'phonem',//命名空间---就是给当前这个模块起个名字(唯一的)
state: {
name:"我是phone模块中的数据"
},//存放数据的
subscriptions: {//类似于一个监听 在里面可以绑定很多个监听的方案
},
effects: {//类似于vuex的actions 进行异步触发的
},
reducers: {// 修改上面的state的地方
// state:就是上面的数据源
// payload就是接收dispatch的第二个参数
UP_NAME(state,payload){
return {...state,name:"我吧phone的数据修改了"}
}
},
};
8.effects--异步触发
扩展-Generator
在dva中如果我们要使用effects来进行异步触发 那么我们需要使用es6中新特性之--- Generator
Generator 函数的作用:让我们的函数可以根据我们开发者的需求走走停停
1.如果我们想控制函数的执行或者暂停 那么我们需要把函数变成generator函数 就是在function关键字 与函数名之间加一个*号
function *fun(){
console.log(111);
console.log(222);
console.log(333);
}
2.我们需要让函数根据我们的需要走走停停 那么我们就必须在函数中加入表示 来表明暂停的位置是哪里 yield(就是函数暂停的分割线)
function *fun(){
console.log(111);
yield
console.log(222);
yield
console.log(333);
}
3.我们在调用的时候 还需要告诉当前的generator函数 你要执行 next()
function *fun(){
console.log(111);
yield
console.log(222);
yield
console.log(333);
}
// 我们要执行函数中的内容
let funger=fun()
// 想让函数执行
funger.next()
funger.next()
9、effect使用
1.在组件中还是使用dispatch来触发
import Topbar from "../components/topbar.jsx"
import {connect} from "dva"
function User(props) {
let fun=()=>{
// 触发effects进行异步操作
// props.dispatch({type:"你要调用的模块命名空间名字/effect的名字"})
props.dispatch({type:"userm/LINK"})
}
return (
<div>
<Topbar></Topbar>
user
<button onClick={fun}>点我触发异步操作</button>
</div>
)
}
export default connect()(User)
2.编写effects异步触发器
export default {
namespace: 'userm',//命名空间---就是给当前这个模块起个名字(唯一的)
state: {
name:"我是user模块中的数据"
},//存放数据的
subscriptions: {//类似于一个监听 在里面可以绑定很多个监听的方案
},
effects: {//类似于vuex的actions 进行异步触发的 effects的函数必须是一个Generator函数
*LINK(){
console.log("我被触发了");
}
},
reducers: {// 修改上面的state的地方
},
};
3.设置请求
在dva中默认已经帮助我们封装好了异步请求 我们不需要单独去配置与下载 在service文件夹下新建文件 创建请求
import request from '../utils/request';
export function query() {
return request('http://localhost:8888/userlist/getlink');
}
4.把写好的请求在effects中使用
// 1.引用我们刚才写好的请求
import {query} from "../services/userlink.js"
export default {
namespace: 'userm',
state: {
name:"我是user模块中的数据"
},
subscriptions: {
},
effects: {
// 2.使用异步请求
// call 调用异步操作 并且得到成功的值
*LINK({payload},{put,call}){
console.log("我被触发了");
// 下一步 使用call来获取成功的返回值
let data= yield call(query
}
},
reducers: {
},
};
5.把请求成功的数据复制给state方便组件使用( 先要交给reducers )
// 1.引用我们刚才写好的请求
import {query} from "../services/userlink.js"
export default {
namespace: 'userm',
state: {
name:"我是user模块中的数据"
},
subscriptions: {
},
effects: {
// 2.使用异步请求
// call 调用异步操作 并且得到成功的值
// put把effects中触发reducers
*LINK({payload},{put,call}){
console.log("我被触发了");
// 下一步 使用call来获取成功的返回值
let data= yield call(query
// 把请求来的数据通过reducers修改给state
// 下一步 通过put触发reducers
yield put({type:"UP_NAME",data})
}
},
reducers: {
},
};
6编写对应的reduicers
// 1.引用我们刚才写好的请求
import {query} from "../services/userlink.js"
export default {
namespace: 'userm',
state: {
name:"我是user模块中的数据"
},
subscriptions: {
},
effects: {
// 2.使用异步请求
// call 调用异步操作 并且得到成功的值
// put把effects中触发reducers
*LINK({payload},{put,call}){
console.log("我被触发了");
// 下一步 使用call来获取成功的返回值
let data= yield call(query
// 把请求来的数据通过reducers修改给state
// 下一步 通过put触发reducers
yield put({type:"UP_NAME",data})
}
},
reducers: {
// 设置修改
UP_NAME(state,payload){
return {...state,name:payload.data}
}
},
};
7 在页面读取数据
import Topbar from "../components/topbar.jsx"
import {connect} from "dva"
function User(props) {
let fun=()=>{
// 触发effects进行异步操作
// props.dispatch({type:"你要调用的模块命名空间名字/effect的名字"})
props.dispatch({type:"userm/LINK"})
}
return (
<div>
<Topbar></Topbar>
user---{props.state.userm.name}
<button onClick={fun}>点我触发异步操作</button>
</div>
)
}
export default connect(state=>({state}))(User)
8 在运行之后出现了跨域问题 添加跨域 项目的根路径下有一个webpackrc的文件中添加跨域
{
"proxy":{
"/api":{
"target":"http://localhost:8888",
"changeOrigin":true,
"pathRewrite":{
"^/api":"/"
}
}
}
}
9.修改请求地址为/api
import request from '../utils/request';
export function query() {
return request('/api/userlist/getlink');
}
10.修改下请求的传递数据
// 1.引用我们刚才写好的请求
import {query} from "../services/userlink.js"
export default {
namespace: 'userm',
state: {
name:"我是user模块中的数据"
},
subscriptions: {
},
effects: {
// 2.使用异步请求
// call 调用异步操作 并且得到成功的值
// put把effects中触发reducers
*LINK({payload},{put,call}){
console.log("我被触发了");
// 下一步 使用call来获取成功的返回值
let data= yield call(query)
console.log(data.data.msg);
// 把请求来的数据通过reducers修改给state
// 下一步 通过put触发reducers
yield put({type:"UP_NAME",data:data.data.msg})
}
},
reducers: {
// 设置修改
UP_NAME(state,payload){
return {...state,name:payload.data}
}
},
};
subscriptions 设置一个监听
可以在里面设置一些监听函数 必须页面修改了 鼠标移动了等等等