Dva+Antd-mobile项目实践

1.项目简介

1.1 介绍

本项目为生成日历器,用户输入信息及选择图片后即可生成日历。

1.2 项目地址

源码:github.com/Wind1ike/Ca…

DEMO:wind1ike.github.io/Calendar/

1.3 截图



2.安装与配置

2.1 安装

(安装请使用科学上网,不然安装速度很慢)

npm i dva-cli -g
dva new calendar
cd calendar
npm i babel-import-plugin antd-mobile prop-types -D
复制代码

2.2 配置

.webpackrc

{
    "extraBabelPlugins": [
         ["import", { "libraryName": "antd-mobile", "style": true }]  //按需加载antd-mobile样式文件
    ]
}
复制代码

3.开发

3.1 编写入口文件

/scr/index.js

import dva from 'dva';
import createHistory from 'history/createBrowserHistory';
import './index.css';

// 1. Initialize
const app = dva({
    history: createHistory()
});

// 2. Plugins
// app.use({});    //插件

// 3. Model
app.model(require('./models/calendar').default);    //加载数据model文件

// 4. Router
app.router(require('./router').default);    //加载路由文件

// 5. Start
app.start('#root');     //启动程序

复制代码

3.2 编写路由文件

该项目可分为两个路由页面,一个为用户填写信息的页面,另一个为生成的日历页面。

/src/router.js

import React from 'react';
import { Router, Route, Switch } from 'dva/router';
import IndexPage from './routes/IndexPage';
import Canvas from './routes/Canvas';

function RouterConfig({ history, text }) {
  return (
    history={
     history}>
      
        "/" exact component={IndexPage} />
        "/canvas" exact component={Canvas} />
      
    
  );
}

export default RouterConfig;

复制代码

3.3 编写组件布局

/src/routes/IndexPage.jsx

import React from 'react';
import Header from '../components/IndexPage/Header';
import InputBox from '../components/IndexPage/InputBox';

function IndexPage() {
  return (
    
); } IndexPage.propTypes = { }; export default IndexPage; 复制代码

/src/components/IndexPage/Header.jsx

import { NavBar } from 'antd-mobile';
import styles from './Header.css';

function Header() {
    return (
        "light"
        className={styles['single-top-nav-bar']}
        >
            

'am-navbar-title']}>日历生成器

) } export default Header; 复制代码

/src/components/IndexPage/InputBox.jsx

import { List, TextareaItem, InputItem, DatePickerView, ImagePicker, Button, Modal } from 'antd-mobile';
import { connect } from 'dva';
import { routerRedux } from 'dva/router';
import React from 'react';

class InputBox extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            text: '',
            todo: '',
            notTodo: '',
            date: 0,
            files: [],
            picture: null,
            isShowModal: false
        }
    }
    
    render() {
        return (
            
                 '文本信息'}>
                    "内容"
                    placeholder=""
                    data-seed="logId"
                    rows="5"
                    value={this.state.text}
                    onChange={(text)=> this.setState({text})}>
                     this.setState({todo: text})}>宜
                     this.setState({notTodo: text})}>忌
                
                 '选择日期'}>
                    "date" 
                    value={this.state.date}
                    onChange={(date)=> this.setState({date: date})}/>
                
                 '选择图片'}>
                     this.setState({picture: files[0], files})}/>
                
                false}
                title="检查是否为填写内容或未选择图片!"
                footer={[{ text: 'Ok', onPress: () => { this.setState({isShowModal: false}) } }]}
                wrapProps={
     { onTouchStart: this.onWrapTouchStart }}
                />
                
            
        )
    }

    onSubmit() {
        if(!(this.state.text && this.state.picture)) {
            this.setState({isShowModal: true});
            return ;
        }

        this.props.dispatch(routerRedux.push('/canvas'));   //切换路由
    }
}


export default InputBox;

复制代码

/scr/routes/Canvas.jsx

import React from 'react';

class Canvas extends React.Component {

    componentDidMount() {
        this.canvas.height = document.body.scrollHeight;
        this.canvas.width = document.body.scrollWidth;

        this.cxt = this.canvas.getContext('2d');
    }

    render() {
        return (
             this.canvas = el}>
        )
    }

    
}

export default Canvas;
复制代码

3.4 编写model文件

Dva中采用Redux来管理数据模型,只有一个Store来保存数据。

Store:保存数据的地方,只能通过Reducers返回新的状态

Action:组件通过connect函数包装后会有this.props.dispatch方法,调用该方法来触发相应的Action。Action中通过调用put函数调用相应的Reducers

Reducers:Reducers从Store中获取旧状态,并根据Action中传过来的数据组成新的状态并返回。

/src/models/calendar.js

export default {

  namespace: 'calendar',

  state: {  // 状态
    text: '',
    todo: '',
    notTodo: '',
    date: 0,
    picture: null
  },

  subscriptions: {
    setup({ dispatch, history }) {  // 监听路由触发动作
    },
  },

  effects: {    // actions
    *submit({ payload }, { call, put }) {  
      yield put({
        type: 'save' ,  //调用reducers中save函数
        payload,
      });
    },
  },

  reducers: {
    save(state, action) {
      return { ...state, ...action.payload };   //返回新的State,不修改旧的State
    },
  },

};
复制代码

修改 /src/components/IndexPage/InputBox.jsx

...
import { connect } from 'dva';
...
class InputBox extends React.Component {
   constructor(props) {
        super(props);
        let date;
        
        if(this.props.date) {
            date = new Date(this.props.date);
        } else {
            date = new Date();
        }
        console.log(this.props)
        this.state = {
            text: this.props.text,
            todo: this.props.todo,
            notTodo: this.props.notTodo,
            date: date,
            files: [],
            picture: null,
            isShowModal: false
        }
    }

    ...

    onSubmit() {
        if(!(this.state.text && this.state.picture)) {
            this.setState({isShowModal: true});
            return ;
        }

        const { text, todo, notTodo, date, picture } = this.state;

        this.props.dispatch({
            type: 'calendar/submit',
            payload: { text, todo, notTodo, picture, date: date.getTime() }
        });     //触发命名空间中submit的Actions

        this.props.dispatch(routerRedux.push('/canvas'));   //切换路由
    }
}

function mapStateToProps(state) {   //该函数用来把Store中的state转换成组件的props
    return state.calendar;
}

export default connect(mapStateToProps)(InputBox);  //通过connnect函数把state注入组件的props中

复制代码

修改 /src/routes/Canvas.jsx

...
import { connect } from 'dva';
...
class Canvas extends React.Component {
    componentDidMount() {
        this.canvas.height = document.body.scrollHeight;
        this.canvas.width = document.body.scrollWidth;

        this.cxt = this.canvas.getContext('2d');
        this.drawImage();
        this.drawDate();
        this.drawText();
        this.drawEvent();
    }
    ...
    (大部分代码为操作canvas代码,不贴出来,有需要可以去看源码)
}
function mapStateToProps(state) {   //该函数用来把Store中的state转换成组件的props
    return state.calendar;
}

export default connect(mapStateToProps)(Canvas);    //通过connnect函数把state注入组件的props中
复制代码

4.总结

本项目通过触发同步Actions来进行交互,没有网络请求等异步操作,实现较为简单。


你可能感兴趣的:(javascript,运维)