[
  {
    "path": ".gitignore",
    "content": "\n.DS_Store\nnode_modules\nminiprogram_npm\n.tea\n.swan\n.vscode-swan\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\ndebug.log*\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Editor directories and files\n.idea\n.vscode\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n\ndist"
  },
  {
    "path": ".npmignore",
    "content": "examples"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 l2j2c3\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "babel.config.json",
    "content": "{\n  \"presets\": [\n    [\"@babel/preset-env\", {\n      \"modules\": \"commonjs\"\n    }],\n    \"@babel/preset-typescript\"\n  ]\n}\n"
  },
  {
    "path": "examples/alipay/app.acss",
    "content": ""
  },
  {
    "path": "examples/alipay/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/alipay/app.json",
    "content": "{\n  \"pages\": [\n    \"pages/index/index\",\n    \"pages/hello/hello\"\n  ],\n  \"window\": {\n    \"defaultTitle\": \"小程序多状态管理\"\n  }\n}\n"
  },
  {
    "path": "examples/alipay/components/header/header.acss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/alipay/components/header/header.axml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" onTap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/alipay/components/header/header.js",
    "content": "import helloStore from '/stores/helloStore'\nimport indexStore from '/stores/indexStore'\nimport globalStore from '/stores/globalStore'\n\nComponent({\n  data: {},\n  \n  didMount() {\n    helloStore.bind(this, '$hello');\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n  },\n\n  didUnmount() {\n    helloStore.unbind(this)\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/alipay/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/alipay/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/alipay/pages/hello/hello.acss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/alipay/pages/hello/hello.axml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" onTap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" onTap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/alipay/pages/hello/hello.js",
    "content": "import helloStore from '/stores/helloStore'\nimport globalStore from '/stores/globalStore'\n\nPage({\n\n  data: {},\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    my.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/alipay/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/alipay/pages/index/index.acss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/alipay/pages/index/index.axml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" onTap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" onTap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/alipay/pages/index/index.js",
    "content": "import indexStore from '/stores/indexStore'\nimport globalStore from '/stores/globalStore'\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    my.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/alipay/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/alipay/stores/globalStore.js",
    "content": "// 全局store\nimport create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/alipay/stores/helloStore.js",
    "content": "import create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/alipay/stores/indexStore.js",
    "content": "import create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/baidu/app.css",
    "content": ""
  },
  {
    "path": "examples/baidu/app.js",
    "content": "App({});\n"
  },
  {
    "path": "examples/baidu/app.json",
    "content": "{\n    \"pages\": [\n        \"pages/index/index\",\n        \"pages/hello/hello\"\n    ],\n    \"window\": {\n        \"navigationBarBackgroundColor\": \"#ffffff\",\n        \"navigationBarTextStyle\": \"black\",\n        \"navigationBarTitleText\": \"智能小程序\",\n        \"backgroundTextStyle\": \"light\"\n    }\n}"
  },
  {
    "path": "examples/baidu/components/header/header.css",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/baidu/components/header/header.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nComponent({\n  lifetimes: {\n    ready() {\n      console.log(this, 1111)\n      helloStore.bind(this, '$hello');\n      indexStore.bind(this, '$index');\n      globalStore.bind(this, '$data');\n    },\n    detached() {\n      helloStore.unbind(this)\n      indexStore.unbind(this)\n      globalStore.unbind(this)\n    },\n  },\n\n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/baidu/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/baidu/components/header/header.swan",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" bind:tap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/baidu/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/baidu/pages/hello/hello.css",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/baidu/pages/hello/hello.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    swan.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/baidu/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/baidu/pages/hello/hello.swan",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bind:tap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" bind:tap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/baidu/pages/index/index.css",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/baidu/pages/index/index.js",
    "content": "const indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    swan.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/baidu/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/baidu/pages/index/index.swan",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bind:tap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" bind:tap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/baidu/project.swan.json",
    "content": "{\n    \"host\": \"baiduboxapp\",\n    \"projectname\": \"swan\",\n    \"setting\": {\n        \"urlCheck\": true\n    },\n    \"swan\": {\n        \"baiduboxapp\": {\n            \"swanJsVersion\": \"3.760.3\",\n            \"extensionJsVersion\": \"1.21.2\"\n        }\n    },\n    \"appid\": \"17767960\",\n    \"compilation-args\": {\n        \"common\": {\n            \"quickPreview\": true\n        },\n        \"forceChanged\": {}\n    }\n}"
  },
  {
    "path": "examples/baidu/stores/globalStore.js",
    "content": "// 全局store\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nmodule.exports = new Store();\n"
  },
  {
    "path": "examples/baidu/stores/helloStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n  \n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/baidu/stores/indexStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/bytedance/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/bytedance/app.json",
    "content": "{\n  \"pages\": [\n    \"pages/index/index\",\n    \"pages/hello/hello\"\n  ],\n  \"window\": {\n    \"navigationBarTitleText\": \"小程序多状态管理\"\n  }\n}"
  },
  {
    "path": "examples/bytedance/app.ttss",
    "content": ""
  },
  {
    "path": "examples/bytedance/components/header/header.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nComponent({\n  \n  lifetimes: {\n    ready() {\n      helloStore.bind(this, '$hello');\n      indexStore.bind(this, '$index');\n      globalStore.bind(this, '$data');\n    },\n    detached() {\n      helloStore.unbind(this)\n      indexStore.unbind(this)\n      globalStore.unbind(this)\n    },\n  },\n\n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/bytedance/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/bytedance/components/header/header.ttml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" bindtap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/bytedance/components/header/header.ttss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/bytedance/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/bytedance/pages/hello/hello.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {},\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    tt.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/bytedance/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/bytedance/pages/hello/hello.ttml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" bindtap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/bytedance/pages/hello/hello.ttss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/bytedance/pages/index/index.js",
    "content": "const indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this,'$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    tt.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/bytedance/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/bytedance/pages/index/index.ttml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" bindtap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/bytedance/pages/index/index.ttss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/bytedance/project.config.json",
    "content": "{\n    \"description\": \"项目配置文件\",\n    \"packOptions\": {\n        \"ignore\": []\n    },\n    \"setting\": {\n        \"bundle\": false,\n        \"userConfirmedBundleSwitch\": false,\n        \"urlCheck\": true,\n        \"scopeDataCheck\": false,\n        \"coverView\": true,\n        \"es6\": true,\n        \"postcss\": true,\n        \"compileHotReLoad\": false,\n        \"lazyloadPlaceholderEnable\": false,\n        \"preloadBackgroundData\": false,\n        \"minified\": true,\n        \"autoAudits\": false,\n        \"newFeature\": false,\n        \"uglifyFileName\": false,\n        \"uploadWithSourceMap\": true,\n        \"useIsolateContext\": true,\n        \"nodeModules\": false,\n        \"enhance\": true,\n        \"useMultiFrameRuntime\": true,\n        \"useApiHook\": true,\n        \"useApiHostProcess\": true,\n        \"showShadowRootInWxmlPanel\": true,\n        \"packNpmManually\": false,\n        \"enableEngineNative\": false,\n        \"packNpmRelationList\": [],\n        \"minifyWXSS\": true,\n        \"showES6CompileOption\": false\n    },\n    \"compileType\": \"miniprogram\",\n    \"libVersion\": \"2.17.0\",\n    \"appid\": \"testAppId\",\n    \"projectname\": \"miniprogram-1\",\n    \"debugOptions\": {\n        \"hidedInDevtools\": []\n    },\n    \"scripts\": {},\n    \"staticServerOptions\": {\n        \"baseURL\": \"\",\n        \"servePath\": \"\"\n    },\n    \"isGameTourist\": false,\n    \"condition\": {\n        \"search\": {\n            \"list\": []\n        },\n        \"conversation\": {\n            \"list\": []\n        },\n        \"game\": {\n            \"list\": []\n        },\n        \"plugin\": {\n            \"list\": []\n        },\n        \"gamePlugin\": {\n            \"list\": []\n        },\n        \"miniprogram\": {\n            \"list\": [],\n            \"current\": -1\n        }\n    }\n}\n"
  },
  {
    "path": "examples/bytedance/sitemap.json",
    "content": "{\n  \"desc\": \"关于本文件的更多信息，请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html\",\n  \"rules\": [{\n  \"action\": \"allow\",\n  \"page\": \"*\"\n  }]\n}"
  },
  {
    "path": "examples/bytedance/stores/globalStore.js",
    "content": "// 全局store\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/bytedance/stores/helloStore.js",
    "content": "\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/bytedance/stores/indexStore.js",
    "content": "\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/dd/app.acss",
    "content": ""
  },
  {
    "path": "examples/dd/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/dd/app.json",
    "content": "{\n  \"pages\": [\n    \"pages/index/index\",\n    \"pages/hello/hello\"\n  ],\n  \"window\": {\n    \"defaultTitle\": \"小程序多状态管理\"\n  }\n}\n"
  },
  {
    "path": "examples/dd/components/header/header.acss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/dd/components/header/header.axml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" onTap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/dd/components/header/header.js",
    "content": "import helloStore from '/stores/helloStore'\nimport indexStore from '/stores/indexStore'\nimport globalStore from '/stores/globalStore'\n\nComponent({\n  didMount() {\n    helloStore.bind(this, '$hello');\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n  },\n  didUnmount() {\n    helloStore.unbind(this)\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/dd/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/dd/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.1.1\"\n  }\n}\n"
  },
  {
    "path": "examples/dd/pages/hello/hello.acss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/dd/pages/hello/hello.axml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" onTap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" onTap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/dd/pages/hello/hello.js",
    "content": "import helloStore from '/stores/helloStore'\nimport globalStore from '/stores/globalStore'\n\nPage({\n\n  data: {},\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n  \n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    dd.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/dd/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/dd/pages/index/index.acss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/dd/pages/index/index.axml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" onTap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" onTap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/dd/pages/index/index.js",
    "content": "import indexStore from '/stores/indexStore'\nimport globalStore from '/stores/globalStore'\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    dd.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/dd/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/dd/stores/globalStore.js",
    "content": "// 全局store\nimport create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/dd/stores/helloStore.js",
    "content": "\nimport create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/dd/stores/indexStore.js",
    "content": "\nimport create from 'mini-stores'\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nexport default new Store();"
  },
  {
    "path": "examples/jd/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/jd/app.json",
    "content": "{\n  \"pages\": [\n    \"pages/index/index\",\n    \"pages/hello/hello\"\n  ],\n  \"window\": {\n    \"navigationBarTitleText\": \"小程序多状态管理\"\n  }\n}"
  },
  {
    "path": "examples/jd/app.jxss",
    "content": ""
  },
  {
    "path": "examples/jd/components/header/header.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nComponent({\n\n  ready() {\n    helloStore.bind(this, '$hello');\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n  },\n\n  detached() {\n    helloStore.unbind(this)\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  methods: {\n    handleChangeLang() {\n        console.log(this, 1111)\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/jd/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/jd/components/header/header.jxml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" bindtap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/jd/components/header/header.jxss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/jd/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/jd/pages/hello/hello.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {},\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n  \n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    jd.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/jd/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/jd/pages/hello/hello.jxml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" bindtap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/jd/pages/hello/hello.jxss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/jd/pages/index/index.js",
    "content": "const indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  handleChangeTitle() {\n      console.log(indexStore.__vms)\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    jd.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/jd/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/jd/pages/index/index.jxml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" bindtap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/jd/pages/index/index.jxss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/jd/project.config.json",
    "content": "{\n  \"description\": \"项目配置文件\",\n  \"packOptions\": {\n    \"ignore\": []\n  },\n  \"setting\": {\n    \"bundle\": false,\n    \"userConfirmedBundleSwitch\": false,\n    \"urlCheck\": true,\n    \"scopeDataCheck\": false,\n    \"coverView\": true,\n    \"es6\": true,\n    \"postcss\": true,\n    \"compileHotReLoad\": false,\n    \"lazyloadPlaceholderEnable\": false,\n    \"preloadBackgroundData\": false,\n    \"minified\": true,\n    \"autoAudits\": false,\n    \"newFeature\": false,\n    \"uglifyFileName\": false,\n    \"uploadWithSourceMap\": true,\n    \"useIsolateContext\": true,\n    \"nodeModules\": false,\n    \"enhance\": true,\n    \"useMultiFrameRuntime\": true,\n    \"useApiHook\": true,\n    \"useApiHostProcess\": true,\n    \"showShadowRootInWxmlPanel\": true,\n    \"packNpmManually\": false,\n    \"enableEngineNative\": false,\n    \"packNpmRelationList\": [],\n    \"minifyWXSS\": true,\n    \"showES6CompileOption\": false\n  },\n  \"compileType\": \"miniprogram\",\n  \"libVersion\": \"2.17.0\",\n  \"appid\": \"wx84727eb836a04125\",\n  \"projectname\": \"miniprogram-1\",\n  \"debugOptions\": {\n    \"hidedInDevtools\": []\n  },\n  \"scripts\": {},\n  \"staticServerOptions\": {\n    \"baseURL\": \"\",\n    \"servePath\": \"\"\n  },\n  \"isGameTourist\": false,\n  \"condition\": {\n    \"search\": {\n      \"list\": []\n    },\n    \"conversation\": {\n      \"list\": []\n    },\n    \"game\": {\n      \"list\": []\n    },\n    \"plugin\": {\n      \"list\": []\n    },\n    \"gamePlugin\": {\n      \"list\": []\n    },\n    \"miniprogram\": {\n      \"list\": []\n    }\n  }\n}"
  },
  {
    "path": "examples/jd/sitemap.json",
    "content": "{\n  \"desc\": \"关于本文件的更多信息，请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html\",\n  \"rules\": [{\n  \"action\": \"allow\",\n  \"page\": \"*\"\n  }]\n}"
  },
  {
    "path": "examples/jd/stores/globalStore.js",
    "content": "// 全局store\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/jd/stores/helloStore.js",
    "content": "\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/jd/stores/indexStore.js",
    "content": "\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/qq/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/qq/app.json",
    "content": "{\n  \"pages\": [\n    \"pages/index/index\",\n    \"pages/hello/hello\"\n  ],\n  \"window\": {\n    \"navigationBarTitleText\": \"小程序多状态管理\"\n  }\n}"
  },
  {
    "path": "examples/qq/app.qss",
    "content": ""
  },
  {
    "path": "examples/qq/components/header/header.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nComponent({\n  lifetimes: {\n    ready() {\n      helloStore.bind(this, '$hello');\n      indexStore.bind(this, '$index');\n      globalStore.bind(this, '$data');\n    },\n    detached() {\n      helloStore.unbind(this)\n      indexStore.unbind(this)\n      globalStore.unbind(this)\n    },\n  },\n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/qq/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/qq/components/header/header.qml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" bindtap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/qq/components/header/header.qss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/qq/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/qq/pages/hello/hello.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {},\n\n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n  \n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    qq.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/qq/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/qq/pages/hello/hello.qml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" bindtap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/qq/pages/hello/hello.qss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/qq/pages/index/index.js",
    "content": "const indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    qq.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/qq/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/qq/pages/index/index.qml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" bindtap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/qq/pages/index/index.qss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/qq/project.config.json",
    "content": "{\n\t\"description\": \"项目配置文件\",\n\t\"packOptions\": {\n\t\t\"ignore\": []\n\t},\n\t\"setting\": {\n\t\t\"bundle\": false,\n\t\t\"userConfirmedBundleSwitch\": false,\n\t\t\"urlCheck\": true,\n\t\t\"scopeDataCheck\": false,\n\t\t\"coverView\": true,\n\t\t\"es6\": true,\n\t\t\"postcss\": true,\n\t\t\"compileHotReLoad\": false,\n\t\t\"lazyloadPlaceholderEnable\": false,\n\t\t\"preloadBackgroundData\": false,\n\t\t\"minified\": true,\n\t\t\"autoAudits\": false,\n\t\t\"newFeature\": false,\n\t\t\"uglifyFileName\": false,\n\t\t\"uploadWithSourceMap\": true,\n\t\t\"useIsolateContext\": true,\n\t\t\"nodeModules\": false,\n\t\t\"enhance\": true,\n\t\t\"useMultiFrameRuntime\": true,\n\t\t\"useApiHook\": true,\n\t\t\"useApiHostProcess\": true,\n\t\t\"showShadowRootInWxmlPanel\": true,\n\t\t\"packNpmManually\": false,\n\t\t\"enableEngineNative\": false,\n\t\t\"packNpmRelationList\": [],\n\t\t\"minifyWXSS\": true,\n\t\t\"showES6CompileOption\": false,\n\t\t\"remoteDebugLogEnable\": false,\n\t\t\"prefetch\": false\n\t},\n\t\"compileType\": \"miniprogram\",\n\t\"libVersion\": \"2.17.0\",\n\t\"appid\": \"wx84727eb836a04125\",\n\t\"projectname\": \"miniprogram-1\",\n\t\"debugOptions\": {\n\t\t\"hidedInDevtools\": []\n\t},\n\t\"scripts\": {},\n\t\"staticServerOptions\": {\n\t\t\"baseURL\": \"\",\n\t\t\"servePath\": \"\"\n\t},\n\t\"isGameTourist\": false,\n\t\"qqappid\": \"1108100302\",\n\t\"condition\": {\n\t\t\"search\": {\n\t\t\t\"list\": []\n\t\t},\n\t\t\"conversation\": {\n\t\t\t\"list\": []\n\t\t},\n\t\t\"game\": {\n\t\t\t\"list\": []\n\t\t},\n\t\t\"plugin\": {\n\t\t\t\"list\": []\n\t\t},\n\t\t\"gamePlugin\": {\n\t\t\t\"list\": []\n\t\t},\n\t\t\"miniprogram\": {\n\t\t\t\"list\": []\n\t\t}\n\t}\n}"
  },
  {
    "path": "examples/qq/sitemap.json",
    "content": "{\n  \"desc\": \"关于本文件的更多信息，请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html\",\n  \"rules\": [{\n  \"action\": \"allow\",\n  \"page\": \"*\"\n  }]\n}"
  },
  {
    "path": "examples/qq/stores/globalStore.js",
    "content": "// 全局store\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/qq/stores/helloStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/qq/stores/indexStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/wx/app.js",
    "content": "App({\n\n  onLaunch(options) {\n\n  },\n\n  onShow(options) {\n\n  },\n});\n"
  },
  {
    "path": "examples/wx/app.json",
    "content": "{\n    \"pages\": [\n        \"pages/index/index\",\n        \"pages/hello/hello\"\n    ],\n    \"window\": {\n        \"navigationBarTitleText\": \"小程序多状态管理\"\n    },\n    \"sitemapLocation\": \"sitemap.json\"\n}"
  },
  {
    "path": "examples/wx/app.wxss",
    "content": ""
  },
  {
    "path": "examples/wx/components/header/header.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore')\n\nComponent({\n  lifetimes: {\n    ready() {\n      helloStore.bind(this, '$hello');\n      indexStore.bind(this, '$index');\n      globalStore.bind(this, '$data');\n    },\n    detached() {\n      helloStore.unbind(this)\n      indexStore.unbind(this)\n      globalStore.unbind(this)\n    },\n  },\n  \n  methods: {\n    handleChangeLang() {\n      globalStore.onChangeLang()\n    },\n  },\n});\n"
  },
  {
    "path": "examples/wx/components/header/header.json",
    "content": "{\n  \"component\": true\n}"
  },
  {
    "path": "examples/wx/components/header/header.wxml",
    "content": "<view class=\"comm-header\">\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    Hello页标题：{{$hello.title}}\n  </view>\n  <view style=\"margin: 20rpx; font-size: 38rpx; color: blue\">\n    index页标题：{{$index.title}}\n  </view>\n  <view>\n    <view>{{$data.description}}</view>\n  </view>\n  <view style=\"margin: 20rpx\">\n    <view style=\"color: blue\">当前语言：{{$data.language==='zh_cn'?'中文':'英文'}}</view>\n    <button type=\"primary\" size=\"mini\" bindtap=\"handleChangeLang\">切换语言</button>\n  </view>\n</view>"
  },
  {
    "path": "examples/wx/components/header/header.wxss",
    "content": ".comm-header {\n  padding: 30rpx 0;\n  background-color: lightgreen;\n  font-weight: bold;\n  font-size: 30rpx;\n  line-height: 1.5;\n  color: #333;\n  text-align: center;\n}"
  },
  {
    "path": "examples/wx/package.json",
    "content": "{\n  \"name\": \"demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"app.js\",\n  \"scripts\": {\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"mini-stores\": \"^1.1.1\"\n  }\n}\n"
  },
  {
    "path": "examples/wx/pages/hello/hello.js",
    "content": "const helloStore = require('../../stores/helloStore')\nconst globalStore = require('../../stores/globalStore')\n\nPage({\n  data: {},\n  \n  onLoad() {\n    helloStore.bind(this, '$hello');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n  \n  onUnload() {\n    helloStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  handleChangeTitle() {\n    helloStore.onChangeTitle()\n  },\n\n  goBack() {\n    wx.navigateBack()\n  }\n});\n"
  },
  {
    "path": "examples/wx/pages/hello/hello.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/wx/pages/hello/hello.wxml",
    "content": "<view class=\"hello\">\n  <header />\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"hello-title\">{{$hello.title}}</view>\n  <view class=\"hello-footer\">\n    <button type=\"primary\" bindtap=\"goBack\">返回上一页</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/wx/pages/hello/hello.wxss",
    "content": ".hello {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n}\n\n.hello-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/wx/pages/index/index.js",
    "content": "const indexStore = require('../../stores/indexStore')\nconst globalStore = require('../../stores/globalStore');\n\nPage({\n\n  data: {\n    privateData: '私有状态'\n  },\n\n  onLoad() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n    globalStore.watch.on('language', console.log, this)\n  },\n\n  onUnload() {\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n  \n  handleChangeTitle() {\n    indexStore.data.title = '首页' + Math.floor(Math.random() * 1000)\n  },\n\n  goPage() {\n    wx.navigateTo({ url: '/pages/hello/hello' })\n  }\n\n});\n"
  },
  {
    "path": "examples/wx/pages/index/index.json",
    "content": "{\n  \"usingComponents\":{\n    \"header\":\"/components/header/header\"\n  }\n}"
  },
  {
    "path": "examples/wx/pages/index/index.wxml",
    "content": "<view class=\"index\">\n  <header />\n  <view class=\"index-title\">{{$index.title}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>\n    <button type=\"primary\" style=\"margin: auto; width: 300rpx\" bindtap=\"handleChangeTitle\">更改标题</button>\n  </view>\n  <view class=\"index-footer\">\n    <button type=\"primary\" bindtap=\"goPage\">下一个页面</button>\n  </view>\n</view>\n"
  },
  {
    "path": "examples/wx/pages/index/index.wxss",
    "content": ".index {\n  height: 100vh;\n  display: flex;\n  flex-direction: column;\n  justify-content: space-between;\n  text-align: center;\n}\n\n.index-title {\n  font-size: 80rpx;\n  font-weight: bolder;\n  text-align: center\n}"
  },
  {
    "path": "examples/wx/project.config.json",
    "content": "{\n  \"description\": \"项目配置文件\",\n  \"packOptions\": {\n    \"ignore\": [],\n    \"include\": []\n  },\n  \"setting\": {\n    \"bundle\": false,\n    \"userConfirmedBundleSwitch\": false,\n    \"urlCheck\": true,\n    \"scopeDataCheck\": false,\n    \"coverView\": true,\n    \"es6\": true,\n    \"postcss\": true,\n    \"compileHotReLoad\": false,\n    \"lazyloadPlaceholderEnable\": false,\n    \"preloadBackgroundData\": false,\n    \"minified\": true,\n    \"autoAudits\": false,\n    \"newFeature\": false,\n    \"uglifyFileName\": false,\n    \"uploadWithSourceMap\": true,\n    \"useIsolateContext\": true,\n    \"nodeModules\": false,\n    \"enhance\": true,\n    \"useMultiFrameRuntime\": true,\n    \"useApiHook\": true,\n    \"useApiHostProcess\": true,\n    \"showShadowRootInWxmlPanel\": true,\n    \"packNpmManually\": false,\n    \"enableEngineNative\": false,\n    \"packNpmRelationList\": [],\n    \"minifyWXSS\": true,\n    \"showES6CompileOption\": false,\n    \"babelSetting\": {\n      \"ignore\": [],\n      \"disablePlugins\": [],\n      \"outputPath\": \"\"\n    },\n    \"condition\": false,\n    \"ignoreUploadUnusedFiles\": true\n  },\n  \"compileType\": \"miniprogram\",\n  \"libVersion\": \"3.9.2\",\n  \"appid\": \"wx84727eb836a04125\",\n  \"projectname\": \"miniprogram-1\",\n  \"condition\": {},\n  \"editorSetting\": {\n    \"tabIndent\": \"insertSpaces\",\n    \"tabSize\": 2\n  }\n}"
  },
  {
    "path": "examples/wx/sitemap.json",
    "content": "{\n  \"desc\": \"关于本文件的更多信息，请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html\",\n  \"rules\": [{\n  \"action\": \"allow\",\n  \"page\": \"*\"\n  }]\n}"
  },
  {
    "path": "examples/wx/stores/globalStore.js",
    "content": "// 全局store\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    corpName: '富土康化肥厂',\n    // 函数属性\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/wx/stores/helloStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: 'Hello页',\n  }\n\n  onChangeTitle() {\n    this.data.title = 'Hello页' + Math.floor(Math.random() * 1000)\n  }\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "examples/wx/stores/indexStore.js",
    "content": "const create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: '首页',\n    a: {\n      b: {\n        c() {\n          return '嵌套节点也支持函数属性-' + this.title\n        }\n      }\n    }\n  }\n\n}\n\nmodule.exports = new Store();"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"mini-stores\",\n  \"version\": \"2.3.0\",\n  \"description\": \"小程序多状态管理 - 解决跨页面跨组件间通信，简洁小巧高性能，支持微信、支付宝、钉钉、百度、字节、QQ等小程序\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"dist/index.js\",\n  \"files\": [\n    \"dist\",\n    \"readme.md\"\n  ],\n  \"scripts\": {\n    \"build\": \"yarn build:types && yarn build:js\",\n    \"build:js\": \"babel src -d dist -x .ts,.js\",\n    \"build:types\": \"tsc\",\n    \"watch\": \"babel src -w -d dist -x .ts,.js\"\n  },\n  \"author\": \"linjc (https://github.com/linjc)\",\n  \"keywords\": [\n    \"mini-stores\",\n    \"小程序状态管理库\",\n    \"小程序全局多状态管理\",\n    \"小程序跨页面组件通信\",\n    \"微信小程序状态管理\",\n    \"钉钉小程序状态管理\",\n    \"支付宝小程序状态管理\",\n    \"京东小程序状态管理\",\n    \"QQ小程序状态管理\",\n    \"百度小程序状态管理\",\n    \"字节小程序状态管理\"\n  ],\n  \"homepage\": \"https://github.com/linjc/mini-stores\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/linjc/mini-stores.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/linjc/mini-stores/issues\"\n  },\n  \"license\": \"MIT\",\n  \"devDependencies\": {\n    \"@babel/cli\": \"^7.27.1\",\n    \"@babel/core\": \"^7.27.1\",\n    \"@babel/preset-env\": \"^7.27.1\",\n    \"@babel/preset-typescript\": \"^7.27.1\",\n    \"babel-preset-env\": \"^1.7.0\",\n    \"miniprogram-api-typings\": \"^4.0.7\",\n    \"typescript\": \"^5.8.3\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# mini-stores - 小程序多状态管理\n\n- [前言](#前言)\n- [安装](#安装)\n- [使用](#使用)\n  - [创建store](#创建store)\n  - [页面内使用](#页面内使用)\n  - [组件内使用](#组件内使用)\n  - [视图上使用](#视图上使用)\n  - [监听状态](#监听状态)\n- [使用建议](#使用建议)\n- [快捷链接](#快捷链接)\n\n## 前言\n小程序没有官方实现的状态管理库，用过redux、vuex、mobx等状态管理库的前端小伙伴都知道，状态管理能很轻松帮我们解决很多跨页面跨组件通信问题。一开始写了一个Emitter类，用事件监听方式去实现全局状态管理，但这种方式相对繁琐且不够直观。于是网上寻找有没有更好的解决方案，最终找到了[westore](https://github.com/Tencent/westore/tree/v1)库，这是由腾讯开源团队研发的微信小程序解决方案，其中针对状态管理的实现很不错，而且还使用专门为小程序开发的[JSON Diff 库](https://github.com/Tencent/westore/blob/v1/utils/diff.js)保证每次以最小的数据量更新状态，比原生setData的性能更好。但由于不支持同时多例store及私有状态等，于是在看了源码之后，基于其核心原理重写了一版，另外根据自身理解做了如下改进：\n\n### 1、优化渲染效率\n每次更新store状态的时候，只对当前页面进行渲染，其他后台态页面延迟更新。这样可以大大减少同时setData的频次，提高渲染效率。\n\n### 2、支持多例store\n一个页面或者组件可以同时使用多个store，且不破坏原有私有状态的定义。\n\n### 3、简化状态触发渲染\n直接更改store的状态值，即可触发组件重渲染，无需手动调用setData方法\n\n### 4、支持多平台\n支持微信/支付宝/钉钉/百度/字节/抖音/QQ/京东等小程序使用。对于其他小程序，理论上也可以直接拿来用，使用时可自行验证。\n\n\n## 安装\n``` js\nnpm i mini-stores --save\n```\n\n## 使用\n\n#### 创建store\n\nstore继承于mini-stores提供的Store类，其中状态定义在data对象内，并支持函数计算属性（计算属性中的this指向store.data对象）\n``` js\nconst create = require('mini-stores')\n\nclass Store extends create.Store {\n\n  data = {\n    title: '小程序多状态管理',\n    language: \"zh_cn\",\n    userName: '李狗蛋',\n    deptName: '化肥质检部门',\n    corpName: '富土康化肥厂',\n    // 函数属性 - 可直接绑定到视图上\n    description() {\n      return `我是${this.userName}，我在${this.corpName}工作`\n    },\n    a: {\n      b: {\n        // 深层嵌套也支持函数属性\n        c() {\n          return this.language + this.description\n        }\n      }\n    }\n  }\n\n  onChangeLang() {\n    if(this.data.language === 'zh_cn') {\n      this.data.language = 'en_US'\n    } else {\n      this.data.language = 'zh_cn'\n    }\n  }\n}\n\nexport default new Store()\n``` \n\n#### 页面内使用\n\n在页面的初始化时（onLoad）绑定store，页面销毁时（onUnload）解除store绑定。\n\nstore.bind方法使用：store.bind(this, '$data'), 第一个参数this为当前页面实例，第二参数为该store在视图上使用的key名。注意该key在视图上使用时，并不是对应store，而是store.data值。另外定义key名注意不要和现有的私有变量同名，个人建议可以加个前缀（如$），这样可以一眼区分它来自全局状态。\n\n\n``` js\nimport globalStore from '/stores/globalStore'\nimport indexStore from '/stores/indexStore'\n\nPage({\n  data: {\n    privateData: '私有状态' // 私有状态还是通过原有的setData更新\n  },\n  onLoad() {\n    // 绑定实例到store上，第二参数定义视图上使用的key名，命名随意，但注意不要和页面data内的私有变量同名\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n  },\n  // 页面销毁时解除绑定\n  onUnload() {\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n  handleChangeTitle() {\n    globalStore.data.title = '新标题'\n  },\n  handleChangeName() {\n    indexStore.changeName()\n  }\n});\n```\n\n#### 组件内使用\n\n和页面内使用一样，在组件初始化时进行store绑定，在组件销毁时解除绑定。\n\n各平台组件生命周期函数写法可能有所区别，根据对应官方文档来写即可。\n\n\n``` js\nimport globalStore from '/stores/globalStore'\nimport indexStore from '/stores/indexStore'\n\nComponent({\n  data: {\n    privateData: '私有状态'\n  },\n  // 阿里系小程序\n  didMount() {\n    indexStore.bind(this, '$index');\n    globalStore.bind(this, '$data');\n  },\n  didUnmount() {\n    // 组件销毁时解除绑定\n    indexStore.unbind(this)\n    globalStore.unbind(this)\n  },\n\n  // 微信小程序等大部分小程序\n  lifetimes: {\n    ready() {\n      indexStore.bind(this, '$index');\n      globalStore.bind(this, '$data');\n    },\n    detached() {\n      // 组件销毁时解除绑定\n      helloStore.unbind(this)\n      globalStore.unbind(this)\n    },\n  },\n  methods: {\n    handleChangeTitle() {\n      globalStore.data.title = '新标题'\n    },\n    handleChangeName() {\n      indexStore.changeName()\n    }\n  }\n});\n```\n\n#### 视图上使用\n简单示例：\n``` js\n<view>\n  <view>{{$index.title}}</view>\n  <view>{{$data.language}}</view>\n  <view>{{$data.description}}</view>\n  <view>{{$index.a.b.c}}</view>\n  <view>{{privateData}}<view>\n</view>\n```\n\n#### 监听状态\n\n添加监听：store.watch.on('key', fn)\n\n移除监听：store.watch.off('key', fn)\n\nkey支持简单的对象点路径写法，从而实现监听深层字段，如：'a.b.c.d'\n\n``` js\nimport globalStore from '/stores/globalStore'\n\nPage({\n  onLoad() {\n    globalStore.bind(this, '$data');\n    // 添加监听\n    globalStore.watch.on('language', this.onWatchLang)\n  },\n  onUnload() {\n    globalStore.unbind(this)\n    // 移除监听，避免内存泄露\n    globalStore.watch.off('language', this.onWatchLang)\n  },\n  onWatchLang(value, oldValue) {\n    console.log('language change:', value, oldValue)\n  },\n});\n```\n\n如果觉得每次写移除监听很繁琐，可以在添加监听时传入组件实例（第三个参数），所有当前实例下的监听事件会在store.unbind时自动移除，参考如下：\n\n``` js\nimport globalStore from '/stores/globalStore'\n\nPage({\n  onLoad() {\n    // 添加监听，第三个参数传入当前实例\n    globalStore.watch.on('language', this.onWatchLang, this)\n  },\n  onUnload() {\n    globalStore.unbind(this)\n  },\n  onWatchLang(value, oldValue) {\n    console.log('language change:', value, oldValue)\n  },\n});\n```\n\n\n## 使用建议\n1、不一定非要使用全局状态管理，涉及到跨页面组件通信时，再考虑使用也可，mini-stores对小程序代码零破坏性，可随时加入或去掉。\n\n2、使用时，建议将状态和逻辑提取到store上，页面只负责处理用户事件的监听和回调，这样的好处是：\n* 保持页面代码简洁，可以快速对页面的用户事件一目了然，更好把控业务。\n* 状态逻辑在独立的js上，方便实现逻辑复用，且更易于代码测试，对使用函数式编程非常友好。\n\n\n使用过程中有什么问题或建议可以在**Issues**进行反馈\n\n## 快捷链接\n\n- [Example示例](./examples)\n- [Github仓库](https://github.com/linjc/mini-stores)\n- [Gitee仓库](https://gitee.com/l2j2c3/mini-stores)\n"
  },
  {
    "path": "src/index.ts",
    "content": "const TYPE_ARRAY = '[object Array]';\nconst TYPE_OBJECT = '[object Object]';\nconst TYPE_FUNCTION = '[object Function]';\n\ntype PlainObject = Record<string, any>;\n\nfunction getType(obj: any): string {\n    return Object.prototype.toString.call(obj);\n}\n\nfunction deepCopy(data: any): any {\n    const type = getType(data);\n    if (type === TYPE_OBJECT) {\n        const obj: PlainObject = {};\n        Object.keys(data).forEach(key => obj[key] = deepCopy(data[key]));\n        return obj;\n    }\n    if (type === TYPE_ARRAY) {\n        return (data as any[]).map(deepCopy);\n    }\n    return data;\n}\n\nfunction getNowPage(): any {\n    const pages = getCurrentPages();\n    return pages[pages.length - 1];\n}\n\nfunction setState(vm: any, data: PlainObject): Promise<void> {\n    vm._new_data = vm._new_data || {};\n    Object.assign(vm._new_data, data);\n    return new Promise(resolve => {\n        Promise.resolve().then(() => {\n            if (vm._new_data) {\n                const diffState = getDiffState(vm._new_data, vm.data);\n                vm._new_data = null;\n                vm.setData(diffState, resolve);\n            } else {\n                resolve();\n            }\n        });\n    });\n}\n\nfunction getDiffState(state: any, preState: any): PlainObject {\n    const newState: PlainObject = {};\n    stateDiff(deepCopy(state), preState, '', newState);\n    return newState;\n}\n\nfunction addDiffState(newState: PlainObject, key: string, val: any): void {\n    if (key !== '') newState[key] = val;\n}\n\nfunction stateDiff(state: any, preState: any, path: string, newState: PlainObject): void {\n    if (state === preState) return;\n\n    const stateType = getType(state);\n    const preStateType = getType(preState);\n\n    if (stateType === TYPE_OBJECT) {\n        const stateKeys = Object.keys(state);\n        const preStateKeys = Object.keys(preState || {});\n        const stateLen = stateKeys.length;\n        const preStateLen = preStateKeys.length;\n\n        if (path !== '') {\n            if (preStateType !== TYPE_OBJECT || stateLen < preStateLen || stateLen === 0 || preStateLen === 0) {\n                addDiffState(newState, path, state);\n                return;\n            }\n            preStateKeys.forEach(key => {\n                if (state[key] === undefined) {\n                    state[key] = null;\n                    if (!stateKeys.includes(key)) {\n                        stateKeys.push(key);\n                    }\n                }\n            });\n        }\n\n        stateKeys.forEach(key => {\n            const subPath = path === '' ? key : `${path}.${key}`;\n            stateDiff(state[key], preState[key], subPath, newState);\n        });\n        return;\n    }\n\n    if (stateType === TYPE_ARRAY) {\n        if (preStateType !== TYPE_ARRAY || state.length < preState.length || state.length === 0 || preState.length === 0) {\n            addDiffState(newState, path, state);\n            return;\n        }\n\n        preState.forEach((_: any, index: number) => {\n            if (state[index] === undefined) state[index] = null;\n        });\n\n        state.forEach((item: any, index: number) => {\n            stateDiff(item, preState[index], `${path}[${index}]`, newState);\n        });\n        return;\n    }\n\n    addDiffState(newState, path, state);\n}\n\nfunction getVmRoute(vm: any): string {\n    return vm.route;\n}\n\nfunction initRoute(vm: any): string {\n    return vm.route || vm.__route__;\n}\n\ninterface BoundVM {\n    vm: any;\n    key: string;\n}\n\ntype WatchCallback = (value: any, oldValue: any) => void\ninterface WatchItem {\n    value: any,\n    paths: string[],\n    callbacks: {\n        vm?: any,\n        callback: WatchCallback,\n    }[]\n}\n\nfunction getValueByPaths(data: any, paths: string[]) {\n    let value = data\n    paths.forEach(key => {\n        value = value?.[key]\n    })\n    return value\n}\n\nexport class Store {\n    private __vms: BoundVM[] = [];\n    private __delayTimer: ReturnType<typeof setTimeout> | null = null;\n    private __updateTimer: any = null;\n    private __watchTimer: any = null;\n    private __watchMap: Record<string, WatchItem> = {}\n    public data: PlainObject = {};\n\n    public watch = {\n        on: (key: string, callback: WatchCallback, vm?: any) => {\n            if (!key || typeof callback !== 'function') {\n                console.warn(`请传入正确参数，如store.watch.on('key', () => {})`)\n                return\n            }\n            key = String(key)\n            if (!this.__watchMap[key]) {\n                const paths = String(key).split('.').filter(f => !!f)\n                if (!paths.length) return\n                this.__watchMap[key] = {\n                    paths,\n                    value: getValueByPaths(this.data, paths),\n                    callbacks: []\n                }\n            }\n            this.__watchMap[key].callbacks.push({ vm, callback })\n        },\n        off: (key: string, callback: WatchCallback) => {\n            key = String(key)\n            if (!this.__watchMap[key]) return\n            this.__watchMap[key].callbacks = this.__watchMap[key].callbacks.filter(f => f.callback !== callback)\n        }\n    }\n\n    constructor() {\n        setTimeout(() => {\n            this.data = this.__createProxy(this.data);\n        }, 0)\n    }\n\n    private __proxyCache = new WeakMap()\n    private __createProxy = (obj: Record<string, any>) => {\n        if (this.__proxyCache.has(obj)) {\n            return this.__proxyCache.get(obj)\n        }\n        const proxy = new Proxy(obj, {\n            get: (target, propKey, receiver) => {\n                const value = Reflect.get(target, propKey, receiver);\n                const type = getType(value)\n                if (type === TYPE_FUNCTION) {\n                    return value.call(this.data)\n                }\n                if (type === TYPE_OBJECT) {\n                    return this.__createProxy(value)\n                }\n                return value\n            },\n            set: (target, propKey, value, receiver) => {\n                clearTimeout(this.__updateTimer)\n                this.__updateTimer = setTimeout(() => this.__update())\n                return Reflect.set(target, propKey, value, receiver);\n            },\n        })\n        this.__proxyCache.set(obj, proxy)\n        return proxy\n    }\n\n    public bind(vm: any, key: string): void {\n        if (!key) {\n            console.error(`请设置store在当前组件实例data中的key，如store.bind(this, '$store')`);\n            return;\n        }\n        vm.data = vm.data || {};\n        vm.data[key] = null;\n        setState(vm, { [key]: this.data });\n\n        if (!this.__vms.some(f => f.vm === vm && f.key === key)) {\n            this.__vms.push({ vm, key });\n            const rootVm = vm.$page || vm.pageinstance || getNowPage() || {};\n            vm.route = initRoute(vm) || initRoute(rootVm);\n        }\n    }\n\n    public unbind(vm: any): void {\n        this.__vms = this.__vms.filter(f => f.vm !== vm);\n        Object.keys(this.__watchMap).forEach(key => {\n            this.__watchMap[key].callbacks = this.__watchMap[key].callbacks.filter(f => f.vm !== vm)\n        })\n    }\n\n    private __update(): void {\n        const nowVm = getNowPage();\n        const nowVmRoute = getVmRoute(nowVm)\n        const delayVms: BoundVM[] = [];\n        this.__vms.forEach(f => {\n            const vmRoute = getVmRoute(f.vm);\n            if (nowVmRoute === vmRoute) {\n                setState(f.vm, { [f.key]: this.data });\n            } else {\n                delayVms.push(f);\n            }\n        });\n\n        clearTimeout(this.__watchTimer)\n        this.__watchTimer = setTimeout(() => {\n            Object.keys(this.__watchMap).forEach(key => {\n                const item = this.__watchMap[key]\n                const value = getValueByPaths(this.data, item.paths)\n                const oldValue = item.value\n                if (oldValue !== value) {\n                    item.value = value\n                    item.callbacks.forEach(f => f.callback(value, oldValue))\n                }\n            })\n        }, 0)\n\n        if (!delayVms.length) return;\n\n        clearTimeout(this.__delayTimer as ReturnType<typeof setTimeout>);\n        this.__delayTimer = setTimeout(() => {\n            delayVms.forEach(f => setState(f.vm, { [f.key]: this.data }));\n        }, 360);\n    }\n\n    public update(): void {\n        this.__update()\n    }\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"declaration\": true,\n    \"emitDeclarationOnly\": true,\n    \"outDir\": \"./dist\",\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"types\": [\n      \"miniprogram-api-typings\"\n    ]\n  },\n  \"include\": [\n    \"src\"\n  ]\n}\n"
  }
]