1. Project Introduction

1.1 introduction

This project is to generate a calendar, the user input information and select pictures can generate a calendar.

1.2 Project Address

Source: github.com/Wind1ike/Ca…

DEMO: wind1ike. Making. IO/Calendar /

1.3 screenshot





2. Installation and configuration

2.1 installation

(Please use scientific Internet to install, otherwise the installation speed is slow)

npm i dva-cli -g
dva new calendar
cd calendar
npm i babel-import-plugin antd-mobile prop-types -D
Copy the code

2.2 configuration

.webpackrc

{
    "extraBabelPlugins": [["import", { "libraryName": "antd-mobile"."style": true}] // Load the antD-mobile style file on demand]}Copy the code

3. The development

3.1 Preparation of import files

/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); // 4. Router app. Router (require('./router').default); 5. Start app.start()'#root'); // Start the programCopy the code

3.2 Compiling routing Files

The project can be divided into two routing pages, one for the user to fill in the information and the other for the generated calendar page.

/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 (
    <Router history= {history}>
      <Switch>
        <Route path="/" exact component={IndexPage} />
        <Route path="/canvas" exact component={Canvas} />
      </Switch>
    </Router>
  );
}

export default RouterConfig;

Copy the code

3.3 Writing component layouts

/src/routes/IndexPage.jsx

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

function IndexPage() {
  return (
    <div>
      <Header></Header>
      <InputBox></InputBox>
    </div>
  );
}

IndexPage.propTypes = {
};

export default IndexPage;

Copy the code

/src/components/IndexPage/Header.jsx

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

function Header() {
    return (
        <NavBar
        mode="light"
        className={styles['single-top-nav-bar']}
        >
            <p className={styles['am-navbar-title'</p> </NavBar>)}export default Header;

Copy the code

/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 (
            <React.Fragment>
                <List renderHeader={()=> 'Text message'}>
                    <TextareaItem
                    title="Content"
                    placeholder=""
                    data-seed="logId"
                    rows="5"value={this.state.text} onChange={(text)=> this.setState({text})}></TextareaItem> <InputItem value={this.state.todo} onChange={(text)=> this.setState({todo: </InputItem> <InputItem value={this.state.notTodo} onChange={(text)=> this.setState({notTodo: Cream < / InputItem text})} > > < / List > < List renderHeader = {() = >'Select date'}>
                    <DatePickerView
                    mode="date" 
                    value={this.state.date}
                    onChange={(date)=> this.setState({date: date})}/>
                </List>
                <List renderHeader={()=> 'Select picture'}>
                    <ImagePicker 
                    files={this.state.files}
                    selectable={this.state.files.length < 1}
                    onChange={(files)=> this.setState({picture: files[0], files})}/>
                </List>
                <Modal
                visible={this.state.isShowModal}
                transparent
                maskClosable={false}
                title="Check if it is filled in or not selected!"
                footer={[{ text: 'Ok', onPress: () => { this.setState({isShowModal: false}) } }]}
                wrapProps={{ onTouchStart: this.onWrapTouchStart }}
                />
                <Button
                type="primary"OnClick = {() = > enclosing onSubmit ()} > generate images < / Button > < / React fragments >)}onSubmit() {
        if(! (this.state.text && this.state.picture)) { this.setState({isShowModal:true});
            return ;
        }

        this.props.dispatch(routerRedux.push('/canvas')); // Switch routes}}export default InputBox;

Copy the code

/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 (
            <canvas 
            ref={(el)=> this.canvas = el}></canvas>
        )
    }

    
}

export default Canvas;
Copy the code

3.4 Writing the Model file

Redux is used in Dva to manage the data model, and there is only one Store to hold the data.

Store: The place where data is saved, and the new state can only be returned through Reducers

Action: The component wrapped in the connect function has the this.props. Dispatch method, which is called to trigger the corresponding Action. The corresponding Reducers are invoked in the Action by calling the put function

Reducers:Reducers take the old state from the Store and form the new state based on the data passed in the Action and return it.

/src/models/calendar.js

export default {

  namespace: 'calendar', state: {// state text:' ',
    todo: ' ',
    notTodo: ' ',
    date: 0,
    picture: null
  },

  subscriptions: {
    setup({ dispatch, history}) {// Actions *submit({payload}, {call, put}) {yield put({// actions *submit({payload}, {call, put}) {yield put({type: 'save'// Call the reducers save function payload,}); }, }, reducers: { save(state, action) {return{... state, ... action.payload }; // Return the new State without modifying the old State},},};Copy the code

Modify/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 in the namespace this.props. Dispatch (RouterRedux.push ('/canvas')); // Switch routes}}functionMapStateToProps (state) {// This function is used to convert the state in the Store to the props of the componentreturn state.calendar;
}

exportdefault connect(mapStateToProps)(InputBox); // Inject state into the props of the component via the connnect functionCopy the code

Modify/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(); }... (Most of the code is canvas code, not posted, if necessary, you can go to see the source code)}functionMapStateToProps (state) {// This function is used to convert the state in the Store to the props of the componentreturn state.calendar;
}

exportdefault connect(mapStateToProps)(Canvas); // Inject state into the props of the component via the connnect functionCopy the code

4. To summarize

This project by triggering synchronous Actions for interaction, no network requests and other asynchronous operations, the implementation is relatively simple.