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.