├── src ├── app.scss ├── pages │ ├── class │ │ ├── index.scss │ │ ├── store.ts │ │ └── index.tsx │ ├── home │ │ ├── index.scss │ │ └── index.tsx │ ├── useLocalStore │ │ ├── index.scss │ │ └── index.tsx │ ├── useAsObservableSource │ │ ├── index.scss │ │ ├── index.tsx │ │ └── multiplier.tsx │ └── useContext │ │ ├── index.scss │ │ └── index.tsx ├── app.config.ts ├── store │ ├── counter.ts │ └── todo.ts ├── app.tsx └── index.html ├── README.md ├── .eslintrc.js ├── .gitignore ├── config ├── dev.js ├── prod.js └── index.js ├── .editorconfig ├── babel.config.js ├── project.config.json ├── global.d.ts ├── tsconfig.json └── package.json /src/app.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/class/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/home/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/useLocalStore/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/useAsObservableSource/index.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # taro-mobx-sample 2 | Taro mobx sample 3 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'extends': ['taro/react'] 3 | } 4 | -------------------------------------------------------------------------------- /src/pages/useContext/index.scss: -------------------------------------------------------------------------------- 1 | .completed { 2 | text-decoration: line-through; 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | deploy_versions/ 3 | .temp/ 4 | .rn_temp/ 5 | node_modules/ 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /config/dev.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"development"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: {} 9 | } 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // babel-preset-taro 更多选项和默认值: 2 | // https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md 3 | module.exports = { 4 | presets: [ 5 | ['taro', { 6 | framework: 'react', 7 | ts: true 8 | }] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "miniprogramRoot": "dist/", 3 | "projectname": "taro-mobx-sample", 4 | "description": "", 5 | "appid": "touristappid", 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": false, 9 | "postcss": false, 10 | "minified": false 11 | }, 12 | "compileType": "miniprogram", 13 | "simulatorType": "wechat", 14 | "simulatorPluginLibVersion": {}, 15 | "condition": {} 16 | } -------------------------------------------------------------------------------- /src/app.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | pages: [ 3 | 'pages/home/index', 4 | 'pages/class/index', 5 | 'pages/useContext/index', 6 | 'pages/useLocalStore/index', 7 | 'pages/useAsObservableSource/index' 8 | ], 9 | window: { 10 | backgroundTextStyle: 'light', 11 | navigationBarBackgroundColor: '#fff', 12 | navigationBarTitleText: 'WeChat', 13 | navigationBarTextStyle: 'black' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/class/store.ts: -------------------------------------------------------------------------------- 1 | import { observable, action } from 'mobx' 2 | 3 | class CounterStore { 4 | @observable counter = 0 5 | 6 | @action.bound 7 | increment() { 8 | this.counter++ 9 | } 10 | 11 | @action.bound 12 | decrement() { 13 | this.counter-- 14 | } 15 | 16 | @action.bound 17 | incrementAsync() { 18 | setTimeout(() => this.counter++, 1000) 19 | } 20 | } 21 | 22 | export default new CounterStore() -------------------------------------------------------------------------------- /src/store/counter.ts: -------------------------------------------------------------------------------- 1 | import { observable, action } from 'mobx' 2 | 3 | class CounterStore { 4 | @observable counter = 0 5 | 6 | @action.bound 7 | increment() { 8 | this.counter++ 9 | } 10 | 11 | @action.bound 12 | decrement() { 13 | this.counter-- 14 | } 15 | 16 | @action.bound 17 | incrementAsync() { 18 | setTimeout(() => this.counter++, 1000) 19 | } 20 | } 21 | 22 | export default new CounterStore() -------------------------------------------------------------------------------- /config/prod.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | NODE_ENV: '"production"' 4 | }, 5 | defineConstants: { 6 | }, 7 | mini: {}, 8 | h5: { 9 | /** 10 | * 如果h5端编译后体积过大,可以使用webpack-bundle-analyzer插件对打包体积进行分析。 11 | * 参考代码如下: 12 | * webpackChain (chain) { 13 | * chain.plugin('analyzer') 14 | * .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, []) 15 | * } 16 | */ 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/pages/useAsObservableSource/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { View, Button } from '@tarojs/components' 3 | import Multiplier from './multiplier' 4 | 5 | import './index.scss' 6 | 7 | function Index() { 8 | const [multiplier, setMultiplier] = useState(0) 9 | return ( 10 | 11 | 12 | 13 | 14 | ) 15 | } 16 | 17 | export default Index -------------------------------------------------------------------------------- /src/app.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { Provider } from 'mobx-react' 3 | 4 | import counterStore from './store/counter' 5 | 6 | import './app.scss' 7 | 8 | class App extends Component { 9 | componentDidMount () {} 10 | 11 | componentDidShow () {} 12 | 13 | componentDidHide () {} 14 | 15 | componentDidCatchError () {} 16 | 17 | // this.props.children 就是要渲染的页面 18 | render () { 19 | return ( 20 | 21 | {this.props.children} 22 | 23 | ) 24 | } 25 | } 26 | 27 | export default App 28 | -------------------------------------------------------------------------------- /src/pages/class/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { View, Button, Text } from '@tarojs/components' 3 | import { inject, observer } from 'mobx-react' 4 | 5 | @inject('counterStore') 6 | @observer 7 | export default class Index extends Component { 8 | render() { 9 | return ( 10 | 11 | 12 | 13 | 14 | {this.props.counterStore.counter} 15 | 16 | ) 17 | } 18 | } -------------------------------------------------------------------------------- /global.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.png"; 2 | declare module "*.gif"; 3 | declare module "*.jpg"; 4 | declare module "*.jpeg"; 5 | declare module "*.svg"; 6 | declare module "*.css"; 7 | declare module "*.less"; 8 | declare module "*.scss"; 9 | declare module "*.sass"; 10 | declare module "*.styl"; 11 | 12 | declare namespace JSX { 13 | interface IntrinsicElements { 14 | 'import': React.DetailedHTMLProps, HTMLEmbedElement> 15 | } 16 | } 17 | 18 | // @ts-ignore 19 | declare const process: { 20 | env: { 21 | TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd'; 22 | [key: string]: any; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/home/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Taro from '@tarojs/taro' 3 | import { Button, View } from '@tarojs/components' 4 | 5 | function Index() { 6 | const goPage = (page) => { 7 | Taro.navigateTo({ 8 | url: `/pages/${page}/index` 9 | }) 10 | } 11 | 12 | return ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | } 21 | 22 | export default Index; -------------------------------------------------------------------------------- /src/store/todo.ts: -------------------------------------------------------------------------------- 1 | import { observable, computed, action } from 'mobx' 2 | import { createContext } from 'react'; 3 | 4 | interface Todo { 5 | id: number; 6 | title: string; 7 | completed: boolean; 8 | } 9 | 10 | class TodoStore { 11 | @observable todos: Todo[] = [] 12 | 13 | @computed get total() { 14 | return this.todos.length 15 | } 16 | 17 | @computed get completedCount() { 18 | return this.todos.filter(item => item.completed).length 19 | } 20 | 21 | @action.bound 22 | add() { 23 | const id = this.todos.length + 1; 24 | this.todos.push({ 25 | id, 26 | title: `Item ${id}`, 27 | completed: false 28 | }) 29 | } 30 | 31 | @action.bound 32 | toggle(index) { 33 | this.todos[index].completed = !this.todos[index].completed 34 | } 35 | } 36 | 37 | export default createContext(new TodoStore()) -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "commonjs", 5 | "removeComments": false, 6 | "preserveConstEnums": true, 7 | "moduleResolution": "node", 8 | "experimentalDecorators": true, 9 | "noImplicitAny": false, 10 | "allowSyntheticDefaultImports": true, 11 | "outDir": "lib", 12 | "noUnusedLocals": true, 13 | "noUnusedParameters": true, 14 | "strictNullChecks": true, 15 | "sourceMap": true, 16 | "baseUrl": ".", 17 | "rootDir": ".", 18 | "jsx": "react", 19 | "jsxFactory": "React.createElement", 20 | "allowJs": true, 21 | "resolveJsonModule": true, 22 | "typeRoots": [ 23 | "node_modules/@types", 24 | "global.d.ts" 25 | ] 26 | }, 27 | "exclude": [ 28 | "node_modules", 29 | "dist" 30 | ], 31 | "compileOnSave": false 32 | } 33 | -------------------------------------------------------------------------------- /src/pages/useAsObservableSource/multiplier.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View, Button, Text } from '@tarojs/components' 3 | import { useAsObservableSource, useLocalStore, observer } from 'mobx-react' 4 | 5 | function Multiplier(props) { 6 | const observableProps = useAsObservableSource(props) 7 | const store = useLocalStore(() => ({ 8 | counter: 1, 9 | get multiplied() { 10 | return observableProps.multiplier * store.counter 11 | }, 12 | increment() { 13 | store.counter += 1 14 | } 15 | })) 16 | 17 | const { multiplier } = observableProps 18 | const { multiplied, counter, increment } = store 19 | return ( 20 | 21 | multiplier({multiplier}) * counter({counter}) = {multiplied} 22 | 23 | 24 | ) 25 | } 26 | 27 | export default observer(Multiplier) -------------------------------------------------------------------------------- /src/pages/useContext/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react' 2 | import { View, Text, Button } from '@tarojs/components' 3 | import { observer } from 'mobx-react' 4 | import Store from '../../store/todo' 5 | import './index.scss' 6 | 7 | function Index() { 8 | const { todos, toggle, add, completedCount, total } = useContext(Store) as any 9 | const list = todos.map((todo, index) => { 10 | const { title, id, completed } = todo 11 | return ( 12 | toggle(index)} 15 | className={completed ? 'completed' : 'un-completed' } 16 | > 17 | {title} 18 | 19 | ) 20 | }) 21 | return ( 22 | 23 | {list} 24 | 已完成:{ completedCount } / {total} 25 | 26 | 27 | ) 28 | } 29 | 30 | export default observer(Index); -------------------------------------------------------------------------------- /src/pages/useLocalStore/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { View, Text, Button } from '@tarojs/components' 3 | import { useLocalStore, observer } from 'mobx-react' 4 | import 'mobx-react-lite/batchingForReactDom' 5 | 6 | import './index.scss' 7 | 8 | function Index() { 9 | const store = useLocalStore(() => ({ 10 | counter: 0, 11 | increment() { 12 | store.counter++ 13 | }, 14 | decrement() { 15 | store.counter-- 16 | }, 17 | incrementAsync() { 18 | setTimeout(() => store.counter++, 1000) 19 | } 20 | })) 21 | 22 | const { counter, increment, decrement, incrementAsync } = store; 23 | return ( 24 | 25 | 26 | 27 | 28 | {counter} 29 | 30 | ) 31 | } 32 | 33 | export default observer(Index) -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | projectName: 'taro-mobx-sample', 3 | date: '2020-7-3', 4 | designWidth: 750, 5 | deviceRatio: { 6 | 640: 2.34 / 2, 7 | 750: 1, 8 | 828: 1.81 / 2 9 | }, 10 | sourceRoot: 'src', 11 | outputRoot: 'dist', 12 | plugins: [], 13 | defineConstants: { 14 | }, 15 | copy: { 16 | patterns: [ 17 | ], 18 | options: { 19 | } 20 | }, 21 | framework: 'react', 22 | mini: { 23 | postcss: { 24 | pxtransform: { 25 | enable: true, 26 | config: { 27 | 28 | } 29 | }, 30 | url: { 31 | enable: true, 32 | config: { 33 | limit: 1024 // 设定转换尺寸上限 34 | } 35 | }, 36 | cssModules: { 37 | enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true 38 | config: { 39 | namingPattern: 'module', // 转换模式,取值为 global/module 40 | generateScopedName: '[name]__[local]___[hash:base64:5]' 41 | } 42 | } 43 | } 44 | }, 45 | h5: { 46 | publicPath: '/', 47 | staticDirectory: 'static', 48 | postcss: { 49 | autoprefixer: { 50 | enable: true, 51 | config: { 52 | } 53 | }, 54 | cssModules: { 55 | enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true 56 | config: { 57 | namingPattern: 'module', // 转换模式,取值为 global/module 58 | generateScopedName: '[name]__[local]___[hash:base64:5]' 59 | } 60 | } 61 | } 62 | } 63 | } 64 | 65 | module.exports = function (merge) { 66 | if (process.env.NODE_ENV === 'development') { 67 | return merge({}, config, require('./dev')) 68 | } 69 | return merge({}, config, require('./prod')) 70 | } 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "taro-mobx-sample", 3 | "version": "1.0.0", 4 | "private": true, 5 | "description": "", 6 | "templateInfo": { 7 | "name": "mobx", 8 | "typescript": true, 9 | "css": "sass" 10 | }, 11 | "scripts": { 12 | "build:weapp": "taro build --type weapp", 13 | "build:swan": "taro build --type swan", 14 | "build:alipay": "taro build --type alipay", 15 | "build:tt": "taro build --type tt", 16 | "build:h5": "taro build --type h5", 17 | "build:rn": "taro build --type rn", 18 | "build:qq": "taro build --type qq", 19 | "build:quickapp": "taro build --type quickapp", 20 | "dev:weapp": "npm run build:weapp -- --watch", 21 | "dev:swan": "npm run build:swan -- --watch", 22 | "dev:alipay": "npm run build:alipay -- --watch", 23 | "dev:tt": "npm run build:tt -- --watch", 24 | "dev:h5": "npm run build:h5 -- --watch", 25 | "dev:rn": "npm run build:rn -- --watch", 26 | "dev:qq": "npm run build:qq -- --watch", 27 | "dev:quickapp": "npm run build:quickapp -- --watch" 28 | }, 29 | "browserslist": [ 30 | "last 3 versions", 31 | "Android >= 4.1", 32 | "ios >= 8" 33 | ], 34 | "author": "", 35 | "license": "MIT", 36 | "dependencies": { 37 | "@babel/runtime": "^7.7.7", 38 | "@tarojs/runtime": "3.0.2", 39 | "@tarojs/taro": "3.0.2", 40 | "@tarojs/components": "3.0.2", 41 | "mobx": "^4.8.0", 42 | "mobx-react": "^6.1.4", 43 | "react-dom": "^16.10.0", 44 | "@tarojs/react": "3.0.2", 45 | "react": "^16.10.0" 46 | }, 47 | "devDependencies": { 48 | "@types/webpack-env": "^1.13.6", 49 | "@types/react": "^16.0.0", 50 | "@tarojs/mini-runner": "3.0.2", 51 | "@babel/core": "^7.8.0", 52 | "@tarojs/webpack-runner": "3.0.2", 53 | "babel-preset-taro": "3.0.2", 54 | "eslint-config-taro": "3.0.2", 55 | "eslint": "^6.8.0", 56 | "eslint-plugin-react": "^7.8.2", 57 | "eslint-plugin-import": "^2.12.0", 58 | "eslint-plugin-react-hooks": "^1.6.1", 59 | "stylelint": "9.3.0", 60 | "@typescript-eslint/parser": "^2.x", 61 | "@typescript-eslint/eslint-plugin": "^2.x", 62 | "typescript": "^3.7.0" 63 | } 64 | } 65 | --------------------------------------------------------------------------------