first commit
36
.babelrc
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"env",
|
||||||
|
{
|
||||||
|
"modules": false,
|
||||||
|
"targets": {
|
||||||
|
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stage-2"
|
||||||
|
],
|
||||||
|
"plugins": [
|
||||||
|
"transform-vue-jsx",
|
||||||
|
"transform-runtime",
|
||||||
|
[
|
||||||
|
"import",
|
||||||
|
{
|
||||||
|
"libraryName": "vant",
|
||||||
|
"libraryDirectory": "es",
|
||||||
|
"style": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"test": {
|
||||||
|
"presets": ["env", "stage-2"],
|
||||||
|
"plugins": [
|
||||||
|
"transform-vue-jsx",
|
||||||
|
"transform-es2015-modules-commonjs",
|
||||||
|
"dynamic-import-node"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
.editorconfig
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
6
.eslintignore
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
/build/
|
||||||
|
/config/
|
||||||
|
/dist/
|
||||||
|
/*.js
|
||||||
|
/test/unit/coverage/
|
||||||
|
/src/
|
29
.eslintrc.js
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
// https://eslint.org/docs/user-guide/configuring
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
parserOptions: {
|
||||||
|
parser: 'babel-eslint'
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||||
|
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||||
|
'plugin:vue/essential',
|
||||||
|
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
|
||||||
|
'standard'
|
||||||
|
],
|
||||||
|
// required to lint *.vue files
|
||||||
|
plugins: [
|
||||||
|
'vue'
|
||||||
|
],
|
||||||
|
// add your custom rules here
|
||||||
|
rules: {
|
||||||
|
// allow async-await
|
||||||
|
'generator-star-spacing': 'off',
|
||||||
|
// allow debugger during development
|
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||||
|
}
|
||||||
|
}
|
21
.gitignore
vendored
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
||||||
|
/dist/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
/test/unit/coverage/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
|
||||||
|
#Hbuilder
|
||||||
|
unpackage/debug/
|
||||||
|
unpackage/release/
|
||||||
|
|
||||||
|
/docs/.vuepress/dist
|
10
.postcssrc.js
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
"plugins": {
|
||||||
|
"postcss-import": {},
|
||||||
|
"postcss-url": {},
|
||||||
|
// to edit target browsers: use "browserslist" field in package.json
|
||||||
|
"autoprefixer": {}
|
||||||
|
}
|
||||||
|
}
|
61
.project
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>mogo-h5plus</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.aptana.ide.core.unifiedBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.pandora.projects.ui.MKeyBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>com.pandora.projects.ui.MKeyNature</nature>
|
||||||
|
<nature>com.aptana.projects.webnature</nature>
|
||||||
|
</natures>
|
||||||
|
<filteredResources>
|
||||||
|
<filter>
|
||||||
|
<id>1528104404363</id>
|
||||||
|
<name></name>
|
||||||
|
<type>26</type>
|
||||||
|
<matcher>
|
||||||
|
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||||
|
<arguments>1.0-name-matches-false-false-node_modules</arguments>
|
||||||
|
</matcher>
|
||||||
|
</filter>
|
||||||
|
<filter>
|
||||||
|
<id>1528770016589</id>
|
||||||
|
<name></name>
|
||||||
|
<type>26</type>
|
||||||
|
<matcher>
|
||||||
|
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||||
|
<arguments>1.0-name-matches-false-false-node_modules</arguments>
|
||||||
|
</matcher>
|
||||||
|
</filter>
|
||||||
|
<filter>
|
||||||
|
<id>1530342398198</id>
|
||||||
|
<name></name>
|
||||||
|
<type>26</type>
|
||||||
|
<matcher>
|
||||||
|
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||||
|
<arguments>1.0-name-matches-false-false-node_modules</arguments>
|
||||||
|
</matcher>
|
||||||
|
</filter>
|
||||||
|
<filter>
|
||||||
|
<id>1530684374172</id>
|
||||||
|
<name></name>
|
||||||
|
<type>26</type>
|
||||||
|
<matcher>
|
||||||
|
<id>org.eclipse.ui.ide.multiFilter</id>
|
||||||
|
<arguments>1.0-name-matches-false-false-node_modules</arguments>
|
||||||
|
</matcher>
|
||||||
|
</filter>
|
||||||
|
</filteredResources>
|
||||||
|
</projectDescription>
|
210
README.md
Executable file
@ -0,0 +1,210 @@
|
|||||||
|
<div align=center><img width="50%" src="https://tyaqing.github.io/mogo-h5plus/logo.png"/></div>
|
||||||
|
|
||||||
|
### 使用案例
|
||||||
|
| [湖南省运会(ios已上架)](https://fir.im/kncq) | [MogoH5+](https://fir.im/p52j) | [闲时帮](https://itunes.apple.com/cn/app/%E9%97%B2%E6%97%B6%E5%B8%AE-%E4%BE%BF%E6%8D%B7%E7%94%9F%E6%B4%BB-%E5%8F%A3%E8%A2%8B%E6%9C%8D%E5%8A%A1/id1381313264?mt=8) | [闲时帮技术端]( https://itunes.apple.com/cn/app/%E9%97%B2%E6%97%B6%E5%B8%AE-%E6%8A%80%E6%9C%AF%E7%AB%AF/id1381313742?mt=8)|
|
||||||
|
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |-|-|
|
||||||
|
|  |  |||
|
||||||
|
|
||||||
|
| [集客坊](https://fir.im/h315) | [安全防护系统](https://fir.im/xqm6) | [蜜诺](https://a.app.qq.com/o/simple.jsp?pkgname=com.meneo.com) |敬请期待 |
|
||||||
|
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |-|-|
|
||||||
|
|  |  |||
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# MogoH5+ 多页面网页解决脚手架
|
||||||
|
|
||||||
|
结合 Hbuilder 使用,可以快速开发 WebApp
|
||||||
|
|
||||||
|
- `支持 Npm 生态`
|
||||||
|
- `支持 vue 语法,以及 vue 生态,比如 vux,mint,vant`
|
||||||
|
- `支持 ES6/ES7 语法`
|
||||||
|
- `使用 VConsole 调试`
|
||||||
|
- `VSCode 友好`
|
||||||
|
- `局域网便捷调试,不插数据线也可以调试`
|
||||||
|
- `支持mui的使用`
|
||||||
|
|
||||||
|
## [文档地址](https://tyaqing.github.io/mogo-h5plus/)
|
||||||
|
|
||||||
|
### MogoH5+ QQ 交流群 780150310
|
||||||
|
|
||||||
|
### [Hotfix](https://github.com/tyaqing/hotfix) 让您的Hbuilder APP应用快速拥有更新能力.
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
您的赞助会使`MogoH5+`发展的更好.
|
||||||
|
|
||||||
|
| 微信 | 支付宝 |
|
||||||
|
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||||
|
| <img width="200" src="https://tyaqing.github.io/mogo-h5plus/wxpay.JPG" alt="foo"> | <img width="200" src="https://tyaqing.github.io/mogo-h5plus/alipay.JPG" alt="foo"> |
|
||||||
|
|
||||||
|
## 更新记录
|
||||||
|
|
||||||
|
### 2.0.0 [20180813]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
1. `vue`以`commonChunk`的形式加载,多个页面加载同一个`vue`,减少了体积.
|
||||||
|
2. `mui`都会已公共文件的形式加载,减少了打包后的体积.
|
||||||
|
3. 修改了`webpack`部分配置,减少体积的同时,编译速度提高了很多.
|
||||||
|
4. 可以在`config/index.js`中配置是否载入`VConsole`,意味着你可以在`build`环境中使用`VConsole`
|
||||||
|
5. 加入`h5plus-hotfix`模块,启用应用的热更新
|
||||||
|
|
||||||
|
#### [修改]
|
||||||
|
|
||||||
|
1. 移除了内置热更新,热更新以新项目`hotfix`单独维护
|
||||||
|
2. 修复了购物车侧滑可以直接返回
|
||||||
|
3. 删除了mui演示页中`import`加载的`mui.css`
|
||||||
|
4. 将模板`index.html`部分js转移到`common.js`
|
||||||
|
5. 解决ios假死的问题,修改了`fastclick`的npm源
|
||||||
|
|
||||||
|
#### [升级指南]
|
||||||
|
|
||||||
|
1. 使用mui的开发者需要删除掉 vue页面中加载的`mui.css`,只要在`page.json`使用了`|mui`,脚手架已经自动加载了mui的css和js
|
||||||
|
2. 修改过index.html的开发者,需要注意内容变化做适应修改
|
||||||
|
|
||||||
|
### 1.3.0 [20180727]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
1. 增加`热更新/迭代`集成,具体文档查看[热更新/迭代](../practice/hotfix.md)
|
||||||
|
2. 增加自定义返回实现,返回按钮可以[自定义返回按钮事件](./qa.html#自定义返回按钮事件)
|
||||||
|
3. 增加"商品加入购物车"功能实例演示页面间通讯
|
||||||
|
4. 新增 VConsole 以 webpack 插件的形式加载,`run build`会自动去掉
|
||||||
|
|
||||||
|
#### [修复]
|
||||||
|
|
||||||
|
1. 修复了超多页面下调试慢的问题,使用`html-webpack-plugin-for-multihtml`解决
|
||||||
|
2. 修改了版本文档
|
||||||
|
|
||||||
|
#### [升级指导]
|
||||||
|
|
||||||
|
1. 将 VConsole 在 common.js 中删掉,因为已经以 webpack 插件形式加载
|
||||||
|
2. `utils` 是我们会经常修改的, 如果有自己的工具库,请另建文件夹
|
||||||
|
|
||||||
|
### 1.2.0 [20180719]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
- 增加预加载窗口打开方式,根据不同场景使用不同的打开方式,可以大大提高 webview 的打开速度,首页已加入使用案例
|
||||||
|
- 由于 VConsole 并不能解决全部调试问题,增加一个`print`方法,用于在 Hbuilder 上打印对象
|
||||||
|
|
||||||
|
#### [速度优化方案]
|
||||||
|
|
||||||
|
最近许多反映脚手架很慢的可以参考一下优化方案,可以大大提高调试/打包速度.
|
||||||
|
|
||||||
|
1.2 的版本中移除了一些不必要的插件,应该会快那么一点吧.追求速度的继续往下看.
|
||||||
|
|
||||||
|
由于 demo 需要展示各种 ui,加载了各种的 ui 的 loader,所以如果开发者用不到可以将其移除.
|
||||||
|
|
||||||
|
##### 1.如果不使用 VUX
|
||||||
|
|
||||||
|
注释掉 `vux-loader` 即可,在`webpack.base.conf.js`中,修改以下代码
|
||||||
|
|
||||||
|
```
|
||||||
|
const vuxLoader = require("vux-loader");
|
||||||
|
|
||||||
|
module.exports = vuxLoader.merge(webpackConfig, {
|
||||||
|
plugins: ["vux-ui"]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
修改后
|
||||||
|
|
||||||
|
```
|
||||||
|
module.exports = webpackConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 2.如果不使用 vant
|
||||||
|
|
||||||
|
移除掉`.babalrc`中以下代码
|
||||||
|
|
||||||
|
```
|
||||||
|
[
|
||||||
|
"import",
|
||||||
|
{
|
||||||
|
"libraryName": "vant",
|
||||||
|
"libraryDirectory": "es",
|
||||||
|
"style": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 3.优化建议
|
||||||
|
|
||||||
|
对于一些简单的页面其实可以不用 ui 框架,加载的时候会很快
|
||||||
|
使用 ui 框架大概也只会增加 100-200ms 的 js 运行时间,窗口过渡 200ms 的话,基本上不会影响用户体验
|
||||||
|
如果使用大量组件,增加的时间可能会比较大,这个时候可以考虑预加载这个窗口了.
|
||||||
|
|
||||||
|
参考:http://ask.dcloud.net.cn/article/25
|
||||||
|
|
||||||
|
#### [升级方案]
|
||||||
|
|
||||||
|
几乎每个版本都是兼容的,所以只要将`src`中的文件转移到新版本就 ok 啦!
|
||||||
|
|
||||||
|
#### [终极解决:webpack4]
|
||||||
|
|
||||||
|
由于官方的 `webpack3` 脚手架速度也提升不了多少了,所以 `1.2` 之后的 `1.x` 版本之后可能几乎不会对脚手架做修改了,只会增加很多实用的使用案例和工具方法
|
||||||
|
|
||||||
|
不过现在已经开始对 `webpack4` 开始研究了 webpack4 `2.0`版本见啦
|
||||||
|
|
||||||
|
### 1.1.0 [20180706]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
- `page.json`可以配置是否加载 mui 或者是否使用 plusready
|
||||||
|
- 增加`fire`页面传值函数,详情可见商品详情页和首页的自定义事件
|
||||||
|
|
||||||
|
#### [修复]
|
||||||
|
|
||||||
|
- 修复了资源路径加载问题(需修改`page.json`配置)
|
||||||
|
- 修复了 mui 加载不灵活的问题,减少打包的体积
|
||||||
|
- 修复了 mui 字体文件加载失败的问题
|
||||||
|
|
||||||
|
#### 1.0.x 到 1.1.x
|
||||||
|
|
||||||
|
由于之前资源路径的问题,目前的解决方案是修改`page.json`的配置,将原来的以路径作为键`mui/index`写成`mui.index`即可,如下
|
||||||
|
|
||||||
|
如果要使用 mui 就加入 `|mui`, 如果要使用 mui 就加入 `|plusReady`,不用则不加.
|
||||||
|
|
||||||
|
> plusReady 在安卓手机上提前载入可能会影响页面打开速度,解决方法有两种:1 不提前使 plus 生效 2.预加载 plus
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mui.index|mui|plusReady": "./src/page/mui/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 注意事项
|
||||||
|
|
||||||
|
请在`created`生命周期里面接收事件,否则会因为视图刷新多次执行.
|
||||||
|
|
||||||
|
### 1.0.1 [20180704]
|
||||||
|
|
||||||
|
- 修复了 background 图片路径打包后不正确的问题
|
||||||
|
|
||||||
|
### 1.0.0 [20180630]
|
||||||
|
|
||||||
|
- 使用 vue 官方脚手架作为基层,健壮性得到`史诗级`提升
|
||||||
|
- 添加了 vux 的支持
|
||||||
|
- 修改的 mui 的加载方式
|
||||||
|
- 配置方面有部分变化,详情请看文档
|
||||||
|
- 升级了安卓 app
|
||||||
|
|
||||||
|
### 0.3.0 [20180628]
|
||||||
|
|
||||||
|
- 解决了因为新增/删除页面导致的 webpack 错误
|
||||||
|
- 添加了 openWebview 的 extras 参数
|
||||||
|
|
||||||
|
### 0.2.0 [20180623]
|
||||||
|
|
||||||
|
- 添加了对 mui 样式和 js 的支持
|
||||||
|
|
||||||
|
## 部分截图
|
||||||
|
|
||||||
|
<div align=center><img width="50%" src="https://github.com/tyaqing/mogo-h5plus/blob/master/docs/.vuepress/public/s1.png?raw=true"/></div>
|
||||||
|
|
||||||
|
<div align=center><img width="50%" src="https://github.com/tyaqing/mogo-h5plus/blob/master/docs/.vuepress/public/s2.png?raw=true"/></div>
|
||||||
|
|
||||||
|
<div align=center><img width="50%" src="https://github.com/tyaqing/mogo-h5plus/blob/master/docs/.vuepress/public/s2.png?raw=true"/></div>
|
41
build/build.js
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
'use strict'
|
||||||
|
require('./check-versions')()
|
||||||
|
|
||||||
|
process.env.NODE_ENV = 'production'
|
||||||
|
|
||||||
|
const ora = require('ora')
|
||||||
|
const rm = require('rimraf')
|
||||||
|
const path = require('path')
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const webpack = require('webpack')
|
||||||
|
const config = require('../config')
|
||||||
|
const webpackConfig = require('./webpack.prod.conf')
|
||||||
|
|
||||||
|
const spinner = ora('building for production...')
|
||||||
|
spinner.start()
|
||||||
|
|
||||||
|
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||||
|
if (err) throw err
|
||||||
|
webpack(webpackConfig, (err, stats) => {
|
||||||
|
spinner.stop()
|
||||||
|
if (err) throw err
|
||||||
|
process.stdout.write(stats.toString({
|
||||||
|
colors: true,
|
||||||
|
modules: false,
|
||||||
|
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
|
||||||
|
chunks: false,
|
||||||
|
chunkModules: false
|
||||||
|
}) + '\n\n')
|
||||||
|
|
||||||
|
if (stats.hasErrors()) {
|
||||||
|
console.log(chalk.red(' Build failed with errors.\n'))
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(chalk.cyan(' Build complete.\n'))
|
||||||
|
console.log(chalk.yellow(
|
||||||
|
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||||
|
' Opening index.html over file:// won\'t work.\n'
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
54
build/check-versions.js
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict'
|
||||||
|
const chalk = require('chalk')
|
||||||
|
const semver = require('semver')
|
||||||
|
const packageConfig = require('../package.json')
|
||||||
|
const shell = require('shelljs')
|
||||||
|
|
||||||
|
function exec (cmd) {
|
||||||
|
return require('child_process').execSync(cmd).toString().trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionRequirements = [
|
||||||
|
{
|
||||||
|
name: 'node',
|
||||||
|
currentVersion: semver.clean(process.version),
|
||||||
|
versionRequirement: packageConfig.engines.node
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (shell.which('npm')) {
|
||||||
|
versionRequirements.push({
|
||||||
|
name: 'npm',
|
||||||
|
currentVersion: exec('npm --version'),
|
||||||
|
versionRequirement: packageConfig.engines.npm
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function () {
|
||||||
|
const warnings = []
|
||||||
|
|
||||||
|
for (let i = 0; i < versionRequirements.length; i++) {
|
||||||
|
const mod = versionRequirements[i]
|
||||||
|
|
||||||
|
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||||
|
warnings.push(mod.name + ': ' +
|
||||||
|
chalk.red(mod.currentVersion) + ' should be ' +
|
||||||
|
chalk.green(mod.versionRequirement)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (warnings.length) {
|
||||||
|
console.log('')
|
||||||
|
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||||
|
console.log()
|
||||||
|
|
||||||
|
for (let i = 0; i < warnings.length; i++) {
|
||||||
|
const warning = warnings[i]
|
||||||
|
console.log(' ' + warning)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
BIN
build/logo.png
Executable file
After Width: | Height: | Size: 6.7 KiB |
4
build/mui-loader.js
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
const fs = require('fs')
|
||||||
|
|
||||||
|
// 获取mui的script
|
||||||
|
module.exports = fs.readFileSync("./src/assets/mui/mui.min.js").toString();
|
56
build/multipage.js
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const path = require('path');
|
||||||
|
const HtmlWebpackPlugin = require("html-webpack-plugin-for-multihtml");
|
||||||
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
|
const config = require("../config");
|
||||||
|
// 通过页面配置文件过去页面json
|
||||||
|
function generateByConfig() {
|
||||||
|
return JSON.parse(fs.readFileSync("./src/page.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成extraEntry
|
||||||
|
const extraEntry = generateByConfig();
|
||||||
|
|
||||||
|
let newExtraEntry = {};
|
||||||
|
|
||||||
|
// 生成HtmlWebpackPlugin
|
||||||
|
let extraHtmlWebpackPlugins = [];
|
||||||
|
let haveMui = 0;
|
||||||
|
for (let i in extraEntry) {
|
||||||
|
// 配置是否使用mui plusready
|
||||||
|
const useMui = /\S+\|mui/.test(i);
|
||||||
|
const usePlusReady = /\S+\|plusReady/.test(i);
|
||||||
|
let chunk = useMui ? i.replace("|mui", "") : i;
|
||||||
|
// 如果用了mui就要导入mui资源
|
||||||
|
useMui && haveMui++;
|
||||||
|
// 提前加载plus
|
||||||
|
if (usePlusReady) chunk = chunk.replace("|plusReady", "");
|
||||||
|
newExtraEntry[chunk] = extraEntry[i];
|
||||||
|
extraHtmlWebpackPlugins.push(
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
filename: chunk + ".html",
|
||||||
|
template: "index.html",
|
||||||
|
multihtmlCache: true,
|
||||||
|
chunks: [chunk, 'vue'],
|
||||||
|
muiCssString: useMui ? '<link rel="stylesheet" href="assets/mui/mui.css">' : "",
|
||||||
|
muiScriptString: useMui ? ' <script src="assets/mui/mui.min.js"></script>' : "",
|
||||||
|
plusReady: usePlusReady ? '<script src="html5plus://ready"></script>' : ""
|
||||||
|
// 获取mui的script
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 复制mui资源
|
||||||
|
if (haveMui) {
|
||||||
|
extraHtmlWebpackPlugins.push(
|
||||||
|
new CopyWebpackPlugin([
|
||||||
|
{
|
||||||
|
from: path.resolve(__dirname, "../src/assets/mui"),
|
||||||
|
to: config.build.assetsSubDirectory + '/mui',
|
||||||
|
ignore: [".*"]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.extraEntry = newExtraEntry;
|
||||||
|
exports.extraHtmlWebpackPlugins = extraHtmlWebpackPlugins;
|
105
build/utils.js
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
"use strict";
|
||||||
|
const path = require("path");
|
||||||
|
const config = require("../config");
|
||||||
|
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||||
|
const packageConfig = require("../package.json");
|
||||||
|
|
||||||
|
exports.assetsPath = function(_path) {
|
||||||
|
const assetsSubDirectory =
|
||||||
|
process.env.NODE_ENV === "production"
|
||||||
|
? config.build.assetsSubDirectory
|
||||||
|
: config.dev.assetsSubDirectory;
|
||||||
|
|
||||||
|
return path.posix.join(assetsSubDirectory, _path);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.cssLoaders = function(options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
const cssLoader = {
|
||||||
|
loader: "css-loader",
|
||||||
|
options: {
|
||||||
|
sourceMap: options.sourceMap
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const postcssLoader = {
|
||||||
|
loader: "postcss-loader",
|
||||||
|
options: {
|
||||||
|
sourceMap: options.sourceMap
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate loader string to be used with extract text plugin
|
||||||
|
function generateLoaders(loader, loaderOptions) {
|
||||||
|
const loaders = options.usePostCSS
|
||||||
|
? [cssLoader, postcssLoader]
|
||||||
|
: [cssLoader];
|
||||||
|
|
||||||
|
if (loader) {
|
||||||
|
loaders.push({
|
||||||
|
loader: loader + "-loader",
|
||||||
|
options: Object.assign({}, loaderOptions, {
|
||||||
|
sourceMap: options.sourceMap
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract CSS when that option is specified
|
||||||
|
// (which is the case during production build)
|
||||||
|
if (options.extract) {
|
||||||
|
return ExtractTextPlugin.extract({
|
||||||
|
use: loaders,
|
||||||
|
fallback: "vue-style-loader",
|
||||||
|
publicPath: "../../"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return ["vue-style-loader"].concat(loaders);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||||
|
return {
|
||||||
|
css: generateLoaders(),
|
||||||
|
postcss: generateLoaders(),
|
||||||
|
less: generateLoaders("less"),
|
||||||
|
sass: generateLoaders("sass", { indentedSyntax: true }),
|
||||||
|
scss: generateLoaders("sass"),
|
||||||
|
stylus: generateLoaders("stylus"),
|
||||||
|
styl: generateLoaders("stylus")
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate loaders for standalone style files (outside of .vue)
|
||||||
|
exports.styleLoaders = function(options) {
|
||||||
|
const output = [];
|
||||||
|
const loaders = exports.cssLoaders(options);
|
||||||
|
|
||||||
|
for (const extension in loaders) {
|
||||||
|
const loader = loaders[extension];
|
||||||
|
output.push({
|
||||||
|
test: new RegExp("\\." + extension + "$"),
|
||||||
|
use: loader
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.createNotifierCallback = () => {
|
||||||
|
const notifier = require("node-notifier");
|
||||||
|
|
||||||
|
return (severity, errors) => {
|
||||||
|
if (severity !== "error") return;
|
||||||
|
|
||||||
|
const error = errors[0];
|
||||||
|
const filename = error.file && error.file.split("!").pop();
|
||||||
|
|
||||||
|
notifier.notify({
|
||||||
|
title: packageConfig.name,
|
||||||
|
message: severity + ": " + error.name,
|
||||||
|
subtitle: filename || "",
|
||||||
|
icon: path.join(__dirname, "logo.png")
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
22
build/vue-loader.conf.js
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
'use strict'
|
||||||
|
const utils = require('./utils')
|
||||||
|
const config = require('../config')
|
||||||
|
const isProduction = process.env.NODE_ENV === 'production'
|
||||||
|
const sourceMapEnabled = isProduction
|
||||||
|
? config.build.productionSourceMap
|
||||||
|
: config.dev.cssSourceMap
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
loaders: utils.cssLoaders({
|
||||||
|
sourceMap: sourceMapEnabled,
|
||||||
|
extract: isProduction
|
||||||
|
}),
|
||||||
|
cssSourceMap: sourceMapEnabled,
|
||||||
|
cacheBusting: config.dev.cacheBusting,
|
||||||
|
transformToRequire: {
|
||||||
|
video: ['src', 'poster'],
|
||||||
|
source: 'src',
|
||||||
|
img: 'src',
|
||||||
|
image: 'xlink:href'
|
||||||
|
}
|
||||||
|
}
|
141
build/webpack.base.conf.js
Executable file
@ -0,0 +1,141 @@
|
|||||||
|
"use strict";
|
||||||
|
const path = require("path");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const utils = require("./utils");
|
||||||
|
const config = require("../config");
|
||||||
|
const vueLoaderConfig = require("./vue-loader.conf");
|
||||||
|
const multiBuilder = require("./multipage");
|
||||||
|
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
|
||||||
|
var vConsolePlugin = require("vconsole-webpack-plugin");
|
||||||
|
|
||||||
|
const { extraEntry, extraHtmlWebpackPlugins } = multiBuilder;
|
||||||
|
|
||||||
|
function resolve(dir) {
|
||||||
|
return path.join(__dirname, "..", dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
const createLintingRule = () => ({
|
||||||
|
test: /\.(js|vue)$/,
|
||||||
|
loader: "eslint-loader",
|
||||||
|
enforce: "pre",
|
||||||
|
include: [resolve("src"), resolve("test")],
|
||||||
|
options: {
|
||||||
|
formatter: require("eslint-friendly-formatter"),
|
||||||
|
emitWarning: !config.dev.showEslintErrorsInOverlay
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 替换代理的链接 定义替换内容
|
||||||
|
let Defines = {};
|
||||||
|
const devServer = {
|
||||||
|
proxy: config.dev.proxyTable
|
||||||
|
};
|
||||||
|
for (let p in devServer.proxy) {
|
||||||
|
Defines[devServer.proxy[p].name] = JSON.stringify(p);
|
||||||
|
// devServer.proxy[p].name;
|
||||||
|
}
|
||||||
|
// console.log(process.env.NODE_ENV);
|
||||||
|
if (process.env.NODE_ENV === "production") {
|
||||||
|
for (let p in devServer.proxy) {
|
||||||
|
Defines[devServer.proxy[p].name] = JSON.stringify(
|
||||||
|
devServer.proxy[p].target
|
||||||
|
);
|
||||||
|
// devServer.proxy[p].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const webpackConfig = {
|
||||||
|
context: path.resolve(__dirname, "../"),
|
||||||
|
entry: {
|
||||||
|
...extraEntry,
|
||||||
|
vue: ['vue'],
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
path: config.build.assetsRoot,
|
||||||
|
filename: "[name].js"
|
||||||
|
// publicPath:
|
||||||
|
// process.env.NODE_ENV === "production"
|
||||||
|
// ? config.build.assetsPublicPath
|
||||||
|
// : config.dev.assetsPublicPath
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: [".js", ".vue", ".json"],
|
||||||
|
alias: {
|
||||||
|
vue$: "vue/dist/vue.esm.js",
|
||||||
|
"@": resolve("src"),
|
||||||
|
mui: resolve("src") + "/assets/mui/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
...(config.dev.useEslint ? [createLintingRule()] : []),
|
||||||
|
{
|
||||||
|
test: /\.vue$/,
|
||||||
|
loader: "vue-loader",
|
||||||
|
options: vueLoaderConfig
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.js$/,
|
||||||
|
loader: "babel-loader",
|
||||||
|
include: [
|
||||||
|
resolve("src"),
|
||||||
|
resolve("test"),
|
||||||
|
resolve("node_modules/webpack-dev-server/client")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||||
|
loader: "url-loader",
|
||||||
|
options: {
|
||||||
|
limit: 10000,
|
||||||
|
name: utils.assetsPath("img/[name].[ext]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||||
|
loader: "url-loader",
|
||||||
|
options: {
|
||||||
|
limit: 10000,
|
||||||
|
name: utils.assetsPath("media/[name].[ext]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||||
|
loader: "url-loader",
|
||||||
|
options: {
|
||||||
|
limit: 10000,
|
||||||
|
name: utils.assetsPath("fonts/[name].[ext]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
node: {
|
||||||
|
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
||||||
|
// source contains it (although only uses it if it's native).
|
||||||
|
setImmediate: false,
|
||||||
|
// prevent webpack from injecting mocks to Node native modules
|
||||||
|
// that does not make sense for the client
|
||||||
|
dgram: "empty",
|
||||||
|
fs: "empty",
|
||||||
|
net: "empty",
|
||||||
|
tls: "empty",
|
||||||
|
child_process: "empty"
|
||||||
|
},
|
||||||
|
plugins: [...extraHtmlWebpackPlugins, new webpack.DefinePlugin(Defines),
|
||||||
|
new vConsolePlugin({
|
||||||
|
enable: config.dev.vConsole // 发布代码前记得改回 false
|
||||||
|
}),
|
||||||
|
new CommonsChunkPlugin({
|
||||||
|
name: ["vue"],
|
||||||
|
minChunks: 2
|
||||||
|
|
||||||
|
})]
|
||||||
|
};
|
||||||
|
|
||||||
|
const vuxLoader = require("vux-loader");
|
||||||
|
|
||||||
|
module.exports = vuxLoader.merge(webpackConfig, {
|
||||||
|
plugins: ["vux-ui"]
|
||||||
|
});
|
85
build/webpack.dev.conf.js
Executable file
@ -0,0 +1,85 @@
|
|||||||
|
"use strict";
|
||||||
|
const utils = require("./utils");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const config = require("../config");
|
||||||
|
const merge = require("webpack-merge");
|
||||||
|
const path = require("path");
|
||||||
|
const baseWebpackConfig = require("./webpack.base.conf");
|
||||||
|
|
||||||
|
|
||||||
|
const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin");
|
||||||
|
const portfinder = require("portfinder");
|
||||||
|
|
||||||
|
const HOST = process.env.HOST;
|
||||||
|
const PORT = process.env.PORT && Number(process.env.PORT);
|
||||||
|
|
||||||
|
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||||
|
module: {
|
||||||
|
rules: utils.styleLoaders({
|
||||||
|
sourceMap: config.dev.cssSourceMap,
|
||||||
|
usePostCSS: true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// cheap-module-eval-source-map is faster for development
|
||||||
|
devtool: config.dev.devtool,
|
||||||
|
// these devServer options should be customized in /config/index.js
|
||||||
|
devServer: {
|
||||||
|
clientLogLevel: "warning",
|
||||||
|
hot: true,
|
||||||
|
contentBase: false, // since we use CopyWebpackPlugin.
|
||||||
|
compress: true,
|
||||||
|
host: HOST || config.dev.host,
|
||||||
|
port: PORT || config.dev.port,
|
||||||
|
open: config.dev.autoOpenBrowser,
|
||||||
|
overlay: config.dev.errorOverlay
|
||||||
|
? { warnings: false, errors: true }
|
||||||
|
: false,
|
||||||
|
publicPath: config.dev.assetsPublicPath,
|
||||||
|
proxy: config.dev.proxyTable,
|
||||||
|
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||||
|
watchOptions: {
|
||||||
|
poll: config.dev.poll
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
"process.env": require("../config/dev.env")
|
||||||
|
}),
|
||||||
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
|
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
||||||
|
new webpack.NoEmitOnErrorsPlugin(),
|
||||||
|
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = new Promise((resolve, reject) => {
|
||||||
|
portfinder.basePort = process.env.PORT || config.dev.port;
|
||||||
|
portfinder.getPort((err, port) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
// publish the new Port, necessary for e2e tests
|
||||||
|
process.env.PORT = port;
|
||||||
|
// add port to devServer config
|
||||||
|
devWebpackConfig.devServer.port = port;
|
||||||
|
|
||||||
|
// Add FriendlyErrorsPlugin
|
||||||
|
devWebpackConfig.plugins.push(
|
||||||
|
new FriendlyErrorsPlugin({
|
||||||
|
compilationSuccessInfo: {
|
||||||
|
messages: [
|
||||||
|
`Your application is running here: http://${
|
||||||
|
devWebpackConfig.devServer.host
|
||||||
|
}:${port}`
|
||||||
|
]
|
||||||
|
},
|
||||||
|
onErrors: config.dev.notifyOnErrors
|
||||||
|
? utils.createNotifierCallback()
|
||||||
|
: undefined
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
resolve(devWebpackConfig);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
145
build/webpack.prod.conf.js
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
"use strict";
|
||||||
|
const path = require("path");
|
||||||
|
const utils = require("./utils");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const config = require("../config");
|
||||||
|
const merge = require("webpack-merge");
|
||||||
|
const baseWebpackConfig = require("./webpack.base.conf");
|
||||||
|
|
||||||
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||||
|
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||||
|
const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin");
|
||||||
|
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
|
||||||
|
|
||||||
|
const env =
|
||||||
|
process.env.NODE_ENV === "testing"
|
||||||
|
? require("../config/test.env")
|
||||||
|
: require("../config/prod.env");
|
||||||
|
|
||||||
|
const webpackConfig = merge(baseWebpackConfig, {
|
||||||
|
module: {
|
||||||
|
rules: utils.styleLoaders({
|
||||||
|
sourceMap: config.build.productionSourceMap,
|
||||||
|
extract: true,
|
||||||
|
usePostCSS: true
|
||||||
|
})
|
||||||
|
},
|
||||||
|
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
||||||
|
output: {
|
||||||
|
path: config.build.assetsRoot,
|
||||||
|
// filename: utils.assetsPath("js/[name].js")
|
||||||
|
// chunkFilename: utils.assetsPath("js/[id].[chunkhash].js")
|
||||||
|
// path: path.resolve(__dirname, "dist"),
|
||||||
|
filename: "[name].js"
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
"process.env": env
|
||||||
|
}),
|
||||||
|
new UglifyJsPlugin({
|
||||||
|
uglifyOptions: {
|
||||||
|
compress: {
|
||||||
|
warnings: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sourceMap: config.build.productionSourceMap,
|
||||||
|
parallel: true
|
||||||
|
}),
|
||||||
|
// extract css into its own file
|
||||||
|
new ExtractTextPlugin({
|
||||||
|
filename: utils.assetsPath("css/[name].css"),
|
||||||
|
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
||||||
|
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
||||||
|
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
|
||||||
|
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
||||||
|
allChunks: true
|
||||||
|
}),
|
||||||
|
// Compress extracted CSS. We are using this plugin so that possible
|
||||||
|
// duplicated CSS from different components can be deduped.
|
||||||
|
new OptimizeCSSPlugin({
|
||||||
|
cssProcessorOptions: config.build.productionSourceMap
|
||||||
|
? { safe: true, map: { inline: false } }
|
||||||
|
: { safe: true }
|
||||||
|
}),
|
||||||
|
// generate dist index.html with correct asset hash for caching.
|
||||||
|
// you can customize output by editing /index.html
|
||||||
|
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||||
|
// new HtmlWebpackPlugin({
|
||||||
|
// filename:
|
||||||
|
// process.env.NODE_ENV === "testing" ? "index.html" : config.build.index,
|
||||||
|
// template: "index.html",
|
||||||
|
// chunks: ["app"],
|
||||||
|
// inject: true,
|
||||||
|
// minify: {
|
||||||
|
// removeComments: true,
|
||||||
|
// collapseWhitespace: true,
|
||||||
|
// removeAttributeQuotes: true
|
||||||
|
// // more options:
|
||||||
|
// // https://github.com/kangax/html-minifier#options-quick-reference
|
||||||
|
// },
|
||||||
|
// // necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||||
|
// chunksSortMode: "dependency"
|
||||||
|
// }),
|
||||||
|
// keep module.id stable when vendor modules does not change
|
||||||
|
// new webpack.HashedModuleIdsPlugin(),
|
||||||
|
// enable scope hoisting
|
||||||
|
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||||
|
// split vendor js into its own file
|
||||||
|
// new webpack.optimize.CommonsChunkPlugin({
|
||||||
|
// name: 'vendor',
|
||||||
|
// minChunks(module) {
|
||||||
|
// // any required modules inside node_modules are extracted to vendor
|
||||||
|
// return (
|
||||||
|
// module.resource &&
|
||||||
|
// /\.js$/.test(module.resource) &&
|
||||||
|
// module.resource.indexOf(
|
||||||
|
// path.join(__dirname, '../node_modules')
|
||||||
|
// ) === 0
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// // extract webpack runtime and module manifest to its own file in order to
|
||||||
|
// // prevent vendor hash from being updated whenever app bundle is updated
|
||||||
|
// new webpack.optimize.CommonsChunkPlugin({
|
||||||
|
// name: 'manifest',
|
||||||
|
// minChunks: Infinity
|
||||||
|
// }),
|
||||||
|
// // This instance extracts shared chunks from code splitted chunks and bundles them
|
||||||
|
// // in a separate chunk, similar to the vendor chunk
|
||||||
|
// // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
||||||
|
// new webpack.optimize.CommonsChunkPlugin({
|
||||||
|
// name: 'app',
|
||||||
|
// async: 'vendor-async',
|
||||||
|
// children: true,
|
||||||
|
// minChunks: 3
|
||||||
|
// }),
|
||||||
|
|
||||||
|
// copy custom static assets
|
||||||
|
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
if (config.build.productionGzip) {
|
||||||
|
const CompressionWebpackPlugin = require("compression-webpack-plugin");
|
||||||
|
|
||||||
|
webpackConfig.plugins.push(
|
||||||
|
new CompressionWebpackPlugin({
|
||||||
|
asset: "[path].gz[query]",
|
||||||
|
algorithm: "gzip",
|
||||||
|
test: new RegExp(
|
||||||
|
"\\.(" + config.build.productionGzipExtensions.join("|") + ")$"
|
||||||
|
),
|
||||||
|
threshold: 10240,
|
||||||
|
minRatio: 0.8
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.build.bundleAnalyzerReport) {
|
||||||
|
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
||||||
|
.BundleAnalyzerPlugin;
|
||||||
|
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = webpackConfig;
|
7
config/dev.env.js
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict'
|
||||||
|
const merge = require('webpack-merge')
|
||||||
|
const prodEnv = require('./prod.env')
|
||||||
|
|
||||||
|
module.exports = merge(prodEnv, {
|
||||||
|
NODE_ENV: '"development"'
|
||||||
|
})
|
100
config/index.js
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
"use strict";
|
||||||
|
// Template version: 1.3.1
|
||||||
|
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const ip = require("ip");
|
||||||
|
module.exports = {
|
||||||
|
dev: {
|
||||||
|
// Paths
|
||||||
|
vConsole: true, //是否显示VConsole
|
||||||
|
assetsSubDirectory: "static",
|
||||||
|
assetsPublicPath: "/",
|
||||||
|
proxyTable: {
|
||||||
|
"/api": {
|
||||||
|
name: "DOUBANAPI",
|
||||||
|
target: "https://api.douban.com",
|
||||||
|
pathRewrite: { "^/api": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
"/localApi": {
|
||||||
|
name: "LOCALAPI",
|
||||||
|
target: "http://127.0.0.1:7001",
|
||||||
|
pathRewrite: { "^/localApi": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
"/femirror": {
|
||||||
|
name: "FemirrorAPI",
|
||||||
|
target: "https://api.hotfix.femirror.com",
|
||||||
|
pathRewrite: { "^/femirror": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Various Dev Server settings
|
||||||
|
host: ip.address(), // can be overwritten by process.env.HOST
|
||||||
|
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||||
|
autoOpenBrowser: false,
|
||||||
|
errorOverlay: true,
|
||||||
|
notifyOnErrors: true,
|
||||||
|
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
||||||
|
|
||||||
|
// Use Eslint Loader?
|
||||||
|
// If true, your code will be linted during bundling and
|
||||||
|
// linting errors and warnings will be shown in the console.
|
||||||
|
useEslint: true,
|
||||||
|
// If true, eslint errors and warnings will also be shown in the error overlay
|
||||||
|
// in the browser.
|
||||||
|
showEslintErrorsInOverlay: false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source Maps
|
||||||
|
*/
|
||||||
|
|
||||||
|
// https://webpack.js.org/configuration/devtool/#development
|
||||||
|
devtool: "cheap-module-eval-source-map",
|
||||||
|
|
||||||
|
// If you have problems debugging vue-files in devtools,
|
||||||
|
// set this to false - it *may* help
|
||||||
|
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||||
|
cacheBusting: true,
|
||||||
|
|
||||||
|
cssSourceMap: true
|
||||||
|
},
|
||||||
|
|
||||||
|
build: {
|
||||||
|
|
||||||
|
vConsole: true, //是否显示VConsole
|
||||||
|
// Template for index.html
|
||||||
|
index: path.resolve(__dirname, "../dist/index.html"),
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
assetsRoot: path.resolve(__dirname, "../dist"),
|
||||||
|
assetsSubDirectory: "assets",
|
||||||
|
assetsPublicPath: "/",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Source Maps
|
||||||
|
*/
|
||||||
|
|
||||||
|
productionSourceMap: false,
|
||||||
|
// https://webpack.js.org/configuration/devtool/#production
|
||||||
|
// devtool: '#source-map',
|
||||||
|
|
||||||
|
// Gzip off by default as many popular static hosts such as
|
||||||
|
// Surge or Netlify already gzip all static assets for you.
|
||||||
|
// Before setting to `true`, make sure to:
|
||||||
|
// npm install --save-dev compression-webpack-plugin
|
||||||
|
productionGzip: false,
|
||||||
|
productionGzipExtensions: ["js", "css"],
|
||||||
|
|
||||||
|
// Run the build command with an extra argument to
|
||||||
|
// View the bundle analyzer report after build finishes:
|
||||||
|
// `npm run build --report`
|
||||||
|
// Set to `true` or `false` to always turn it on or off
|
||||||
|
bundleAnalyzerReport: process.env.npm_config_report
|
||||||
|
}
|
||||||
|
};
|
4
config/prod.env.js
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
'use strict'
|
||||||
|
module.exports = {
|
||||||
|
NODE_ENV: '"production"'
|
||||||
|
}
|
7
config/test.env.js
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
'use strict'
|
||||||
|
const merge = require('webpack-merge')
|
||||||
|
const devEnv = require('./dev.env')
|
||||||
|
|
||||||
|
module.exports = merge(devEnv, {
|
||||||
|
NODE_ENV: '"testing"'
|
||||||
|
})
|
53
docs/.vuepress/config.js
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
module.exports = {
|
||||||
|
title: "MogoH5+",
|
||||||
|
description: "快速开发WebApp的多页面脚手架工具,致力于打造H5+应用生态.",
|
||||||
|
base: "/mogo-h5plus/",
|
||||||
|
themeConfig: {
|
||||||
|
nav: [
|
||||||
|
{ text: "主页", link: "/" },
|
||||||
|
{ text: "MogoH5+", link: "/guide/guide.md" },
|
||||||
|
{ text: "Hotfix", link: "/hotfix/introduction.md" },
|
||||||
|
{ text: "H5+文档", link: "http://www.html5plus.org/doc/h5p.html" }
|
||||||
|
],
|
||||||
|
repo: "tyaqing/mogo-h5plus",
|
||||||
|
search: true,
|
||||||
|
sidebar: {
|
||||||
|
"/guide/": [
|
||||||
|
{
|
||||||
|
title: "指南|Guide",
|
||||||
|
collapsable: false,
|
||||||
|
children: [
|
||||||
|
"introduction",
|
||||||
|
"development",
|
||||||
|
"production",
|
||||||
|
"update_log",
|
||||||
|
"qa"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "最佳实践|Practice",
|
||||||
|
collapsable: false,
|
||||||
|
children: ["practice/webview", "practice/details"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "关于|About",
|
||||||
|
collapsable: false,
|
||||||
|
children: ["about"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/hotfix/": [{
|
||||||
|
title: "新版本|V1",
|
||||||
|
collapsable: false,
|
||||||
|
children: [
|
||||||
|
"introduction", "config", "hotfitxFemirror"
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
title: "旧版本|Old",
|
||||||
|
collapsable: true,
|
||||||
|
children: [
|
||||||
|
"old/introduction", "old/usage", "old/hotfix", "old/hotfitxFemirror"
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
4
docs/.vuepress/override.styl
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
$accentColor = #F7782E
|
||||||
|
$textColor = #2c3e50
|
||||||
|
$borderColor = #eaecef
|
||||||
|
$codeBgColor = #282c34
|
BIN
docs/.vuepress/public/IMG_0040.PNG
Executable file
After Width: | Height: | Size: 96 KiB |
BIN
docs/.vuepress/public/S80805-211149.jpg
Executable file
After Width: | Height: | Size: 335 KiB |
BIN
docs/.vuepress/public/S80806-112100.jpg
Executable file
After Width: | Height: | Size: 161 KiB |
BIN
docs/.vuepress/public/alipay.JPG
Executable file
After Width: | Height: | Size: 40 KiB |
BIN
docs/.vuepress/public/h1.png
Executable file
After Width: | Height: | Size: 46 KiB |
BIN
docs/.vuepress/public/h2.png
Executable file
After Width: | Height: | Size: 103 KiB |
BIN
docs/.vuepress/public/h3.png
Executable file
After Width: | Height: | Size: 30 KiB |
BIN
docs/.vuepress/public/hotfix/1.png
Executable file
After Width: | Height: | Size: 66 KiB |
BIN
docs/.vuepress/public/hotfix/2.png
Executable file
After Width: | Height: | Size: 62 KiB |
BIN
docs/.vuepress/public/hotfix/3.png
Executable file
After Width: | Height: | Size: 98 KiB |
BIN
docs/.vuepress/public/hotfix/4.png
Executable file
After Width: | Height: | Size: 96 KiB |
BIN
docs/.vuepress/public/hotfix/5.png
Executable file
After Width: | Height: | Size: 97 KiB |
BIN
docs/.vuepress/public/logo.png
Executable file
After Width: | Height: | Size: 23 KiB |
BIN
docs/.vuepress/public/s0.png
Executable file
After Width: | Height: | Size: 101 KiB |
BIN
docs/.vuepress/public/s1.png
Executable file
After Width: | Height: | Size: 95 KiB |
BIN
docs/.vuepress/public/s2.png
Executable file
After Width: | Height: | Size: 141 KiB |
BIN
docs/.vuepress/public/s3.png
Executable file
After Width: | Height: | Size: 133 KiB |
BIN
docs/.vuepress/public/wxpay.JPG
Executable file
After Width: | Height: | Size: 85 KiB |
14
docs/README.md
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
home: true
|
||||||
|
heroImage: /logo.png
|
||||||
|
actionText: 查看文档 →
|
||||||
|
actionLink: /guide/introduction.md
|
||||||
|
features:
|
||||||
|
- title: Vue多页面
|
||||||
|
details: 使用vue+webpack+babel构建的多页面脚手架,开发,调试非常便捷.
|
||||||
|
- title: 热更新
|
||||||
|
details: 几部简单的操作就可以更新自己的APP,无需繁琐的审核
|
||||||
|
- title: 云应用
|
||||||
|
details: 你可以将此想象成[微信-小程序]的关系,快速迭代您的app
|
||||||
|
footer: MIT Licensed | Copyright © 2018
|
||||||
|
---
|
27
docs/deploy.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# 确保脚本抛出遇到的错误
|
||||||
|
# set -e
|
||||||
|
|
||||||
|
# 生成静态文件
|
||||||
|
# npm run docs:build
|
||||||
|
|
||||||
|
vuepress build
|
||||||
|
|
||||||
|
# 进入生成的文件夹
|
||||||
|
cd .vuepress/dist
|
||||||
|
|
||||||
|
# 如果是发布到自定义域名
|
||||||
|
# echo 'www.example.com' > CNAME
|
||||||
|
|
||||||
|
git init
|
||||||
|
git add -A
|
||||||
|
git commit -m 'deploy'
|
||||||
|
|
||||||
|
# 如果发布到 https://<USERNAME>.github.io
|
||||||
|
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git master
|
||||||
|
|
||||||
|
# 如果发布到 https://<USERNAME>.github.io/<REPO>
|
||||||
|
git push -f https://github.com/tyaqing/mogo-h5plus.git master:gh-pages
|
||||||
|
|
||||||
|
cd -
|
13
docs/guide/about.md
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
# 关于
|
||||||
|
|
||||||
|
## 框架
|
||||||
|
|
||||||
|
框架由我个人维护,由于热爱,几乎每周都会有更新,同样关于脚手架周边的服务也在慢慢整合,致力于打造一个优质的 webapp 开发体验.
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
您的赞助会使`MogoH5+`发展的更好,所赞助的资金都将提升`FEmirror 云更新`服务.
|
||||||
|
|
||||||
|
| 微信 | 支付宝 |
|
||||||
|
| ---------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
|
| <img width="200" :src="$withBase('/wxpay.JPG')" alt="foo"> | <img width="200" :src="$withBase('/alipay.JPG')" alt="foo"> |
|
220
docs/guide/development.md
Executable file
@ -0,0 +1,220 @@
|
|||||||
|
# 开发
|
||||||
|
|
||||||
|
## 下载脚手架
|
||||||
|
|
||||||
|
首先下载脚手架
|
||||||
|
脚手架项目地址[MogoH5+](https://github.com/tyaqing/mogo-h5plus)
|
||||||
|
|
||||||
|
### Git clone
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/tyaqing/mogo-h5plus.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 直接下载
|
||||||
|
|
||||||
|
[下载地址](https://github.com/tyaqing/mogo-h5plus/archive/master.zip)
|
||||||
|
|
||||||
|
下载后把目录直接导入到 Hbuilder.
|
||||||
|
|
||||||
|
## 运行脚手架
|
||||||
|
|
||||||
|
```bash
|
||||||
|
// 1 进入项目主目录
|
||||||
|
cd mogo-h5plus
|
||||||
|
// 2 安装npm依赖
|
||||||
|
npm i // 或者 yarn 请不要使用cnpm
|
||||||
|
// 3 调试运行
|
||||||
|
npm start
|
||||||
|
|
||||||
|
// 运行结果如下
|
||||||
|
ℹ 「wds」: Project is running at http://192.168.199.155:8080/
|
||||||
|
ℹ 「wds」: webpack output is served from /
|
||||||
|
ℹ 「wdm」: Hash: e597725cca065f694fbd
|
||||||
|
Version: webpack 4.10.2
|
||||||
|
Time: 4959ms
|
||||||
|
```
|
||||||
|
|
||||||
|
直接下载项目然后根据需求定制打包,最后通过 Hbuilder 云打包即可生成 APP.
|
||||||
|
|
||||||
|
> 本文自带一个案例是使用 VantUI 开发的几个界面,如果你喜欢其他 UI 同样可以替换成其他的 UI.
|
||||||
|
|
||||||
|
## 真机调试
|
||||||
|
|
||||||
|
将打印出来的 ip 地址,我们打印出来的是`http://192.168.199.155:8080/`,将这个填入页面入口.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后使用 Hbuilder 基座进行调试测试.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 新建页面
|
||||||
|
|
||||||
|
假如我们要新建一个名称为`list`的页面作为商品列表,我们就要在`./src/page/goods`下新建`list.js`和`list.vue`两个文件.`list.js`作为多页面的入口,`list.vue`,脚手架自带了几个页面可供参考.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"index|plusReady": "./src/main.js",
|
||||||
|
"goods.detail": "./src/page/goods/detail.js",
|
||||||
|
"goods.cart": "./src/page/goods/cart.js",
|
||||||
|
"mui.index|mui|plusReady": "./src/page/mui/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 访问页面
|
||||||
|
|
||||||
|
```js
|
||||||
|
openWebview({ url: "./goods.cart.html", id: "goods.cart" });
|
||||||
|
openWebview({ url: "./mui.index.html", id: "mui.index" });
|
||||||
|
```
|
||||||
|
|
||||||
|
这里要注意 2 个细节:
|
||||||
|
|
||||||
|
1. 后缀一定是`.html`
|
||||||
|
2. id 要按照页面的规范,不要出现重复 id
|
||||||
|
|
||||||
|
### 删除页面
|
||||||
|
|
||||||
|
如果删除页面了页面,也需要删除`page.json`相应的页面描述代码
|
||||||
|
|
||||||
|
> 实现原理是监听了`page.json`,一旦`page.json`发生改变,会重启`webpack`
|
||||||
|
|
||||||
|
## 新建组件
|
||||||
|
|
||||||
|
组件放入`./src/components`目录下,如果组件较多,可自行建立目录.比如 demo 中使用的 Logo 组件可以作为参考.
|
||||||
|
|
||||||
|
## 新建工具库
|
||||||
|
|
||||||
|
工具库`./src/utils`主要放一些公用函数,比如请求,打开 webview,支付,分享等执行函数.
|
||||||
|
demo 中封装了部分来自 mui 的函数比如`自定义事件`,`webview`.这些函数可以作为参考.
|
||||||
|
|
||||||
|
`common.js` 是每个页面都需要加载的一个 js,里面加载了`fastclick`和`vconsole`.如果全局需要加统计,全局执行的函数,可以放在这个文件里面.
|
||||||
|
|
||||||
|
`./src/utils` 做了 `alias`别名,可以 直接这样加载 `import common from "Utils/common"`.
|
||||||
|
|
||||||
|
> utils 是我们会经常修改的, 如果有自己的工具库,请另建文件夹
|
||||||
|
|
||||||
|
## 请求代理配置 Proxy
|
||||||
|
|
||||||
|
首先,只有开发的过程中才会有跨域的情况.App 中不存在跨域.
|
||||||
|
|
||||||
|
**为什么会有跨域呢?**
|
||||||
|
|
||||||
|
`MogoH5+`的调试是使用`npm run dev`构建了一个局域网服务器的,比如`http://192.168.199.155:8080/`,这样的好处就是视图修改同步很快,不受 Hbuilder 的限制.
|
||||||
|
|
||||||
|
起初考虑过`webpack watch`来实现,但是发现`watch`之后的文件变化 HBuilder 无法第一时间反应,也就是说,修改了一个界面,需要等 Hbuilder 发现`文件差异`才会去更新真机的试图.因此才考虑局域网服务器的.
|
||||||
|
|
||||||
|
### 请求库
|
||||||
|
|
||||||
|
demo 的请求使用的是 `axios`,同样你喜欢什么库都可以自己去封装.
|
||||||
|
|
||||||
|
常见的请求库有`fetch`,`request`,`SuperAgent`,`jquery-ajax`.
|
||||||
|
|
||||||
|
### 跨域
|
||||||
|
|
||||||
|
由于`npm start`后,调试网页是挂在局域网上,并且作为 Hbuilder 的`页面入口`,因此,在请求时会出现`跨域`.
|
||||||
|
|
||||||
|
在`/config/index.js`中使用本地代理,将下面的`https://api.douban.com`修改成自己使用的业务域名即可.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
name:"DOUBANAPI", // 自己取名
|
||||||
|
target: "https://api.douban.com",
|
||||||
|
pathRewrite: { "^/api": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
"/baidu_api": {
|
||||||
|
name:"BAIDUAPI", // 自己取名
|
||||||
|
target: "https://api.baidu.com",
|
||||||
|
pathRewrite: { "^/baidu_api": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果有更多业务域名可以继续在`proxy`添加.
|
||||||
|
|
||||||
|
只有开发的时候才会有跨域问题,打包后的文件网址会被替换成被代理的网址,因此发送请求一定要加上名称`DOUBANAPI`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
request({
|
||||||
|
url: DOUBANAPI + "/bookList" // 在打包后会变成 https://api.baidu.com/bookList
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 调试
|
||||||
|
|
||||||
|
### VConsole
|
||||||
|
|
||||||
|
在 Hbuilder 中调试会有诸多问题,比如:
|
||||||
|
|
||||||
|
- 不能直接打印`数组`,`对象`,需要转成字符串.
|
||||||
|
- 即使使用`webview调试`,仍然不能打印出数组,在 mac 上使用也非常不方便.
|
||||||
|
|
||||||
|
使用`VConsole`,调试的问题基本就脱离 Hbuilder 了,使用`VConsole`主要优点如下
|
||||||
|
|
||||||
|
- 可以打印数组,对象
|
||||||
|
- 可以查看请求,cookie,Localstorage
|
||||||
|
- 在`System`栏目中可以看到页面加载速度
|
||||||
|
- 可以查看元素
|
||||||
|
|
||||||
|
基本上就是一个简化的`开发者工具栏`,对于调试来说非常简便了.
|
||||||
|
|
||||||
|
### print 函数
|
||||||
|
|
||||||
|
由于 `VConsole` 并不能解决全部调试问题,比如页面关闭后调试信息消失,增加一个 `print` 方法,用于在 Hbuilder 上打印对象
|
||||||
|
|
||||||
|
```js
|
||||||
|
print(someObjorArray);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用 mui
|
||||||
|
|
||||||
|
1. 首先在`page.json`中给需要使用`mui`的页面加入`|mui`,这一步,`mui`的`js`将会嵌入到改页面当中.
|
||||||
|
|
||||||
|
2. 使用相对路径加入 mui 的 css,加入方式如下:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<style lang="less">
|
||||||
|
@import '../../assets/mui/mui.css';
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用 vux/vant
|
||||||
|
|
||||||
|
系统默认安装了`vux`和`vux-loader`,`vant`也是默认添加的,直接 import 使用即可.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { Group, Calendar, Cell, Badge, CellBox, XButton } from "vux";
|
||||||
|
```
|
||||||
|
|
||||||
|
> 如果您不使用 vux,或 vant,可以将其编译器去除来提高您的开发构建效率.[具体方式](qa.html#速度优化方案)
|
||||||
|
|
||||||
|
## page.json 配置
|
||||||
|
|
||||||
|
这是一份来自`demo`的页面配置,多页面的主要配置也是来自这里,具体实现细节请参看[多页面的实现]
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"index|plusReady": "./src/main.js",
|
||||||
|
"goods.detail": "./src/page/goods/detail.js",
|
||||||
|
"goods.cart": "./src/page/goods/cart.js",
|
||||||
|
"mui.index|mui|plusReady": "./src/page/mui/index.js",
|
||||||
|
"user.index": "./src/page/user/index.js",
|
||||||
|
"vux.index|plusReady": "./src/page/vux/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
在配置的`键`中发现了`|`符号,`|`后面的值表示页面加载参数,这里主要对一些参数作解释
|
||||||
|
|
||||||
|
| 参数 | 解释 | 备注 |
|
||||||
|
| ----------- | -------------------------------------------------------------- | -------------- |
|
||||||
|
| `mui` | 在页面中加载 mui,使用后 mui 会挂在到`window`上 | / |
|
||||||
|
| `plusReady` | 是否使 plus 提前生效 ,提前生效就可以不用监听 plus 是否已经生效 | 仅在安卓上有效 |
|
||||||
|
|
||||||
|
> 注意:plus 在安卓上提前生效会增加 50-200ms(根据性能)的加载时间,可以通过增加窗口过场动画的时间弥补,或者预加载窗口
|
257
docs/guide/guide.md
Executable file
@ -0,0 +1,257 @@
|
|||||||
|
# 简介
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`MogoH5+` 是一个 vue 多页面**脚手架工具**,结合 H5+可以快速开发安卓与苹果 APP.
|
||||||
|
|
||||||
|
即使不适用 Hbuilder 打包成 APP,本脚手架同样可以作为多页面网页生成的参考项目.
|
||||||
|
|
||||||
|
### [APP 演示下载地址](https://fir.im/p52j)
|
||||||
|
|
||||||
|
## 特性
|
||||||
|
|
||||||
|
- `支持 Npm 生态`
|
||||||
|
- `支持 vue 语法,以及 vue 生态,比如 mint,vant`
|
||||||
|
- `支持 ES6/ES7 语法`
|
||||||
|
- `使用 VConsole 调试`
|
||||||
|
- `VSCode 友好`
|
||||||
|
- `局域网便捷调试,不插数据线也可以调试`
|
||||||
|
- `支持mui`
|
||||||
|
|
||||||
|
# 快速上手
|
||||||
|
|
||||||
|
## 下载脚手架
|
||||||
|
|
||||||
|
首先下载脚手架
|
||||||
|
脚手架项目地址[MogoH5+](https://github.com/tyaqing/mogo-h5plus)
|
||||||
|
|
||||||
|
### Git clone
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone https://github.com/tyaqing/mogo-h5plus.git
|
||||||
|
```
|
||||||
|
|
||||||
|
### 直接下载
|
||||||
|
|
||||||
|
[下载地址](https://github.com/tyaqing/mogo-h5plus/archive/master.zip)
|
||||||
|
|
||||||
|
下载后把目录直接导入到 Hbuilder.
|
||||||
|
|
||||||
|
## 运行脚手架
|
||||||
|
|
||||||
|
```
|
||||||
|
// 1 进入项目主目录
|
||||||
|
cd mogo-h5plus
|
||||||
|
// 2 安装npm依赖
|
||||||
|
npm i // 或者 yarn
|
||||||
|
// 3 调试运行
|
||||||
|
npm start
|
||||||
|
|
||||||
|
// 运行结果如下
|
||||||
|
ℹ 「wds」: Project is running at http://192.168.199.155:8080/
|
||||||
|
ℹ 「wds」: webpack output is served from /
|
||||||
|
ℹ 「wdm」: Hash: e597725cca065f694fbd
|
||||||
|
Version: webpack 4.10.2
|
||||||
|
Time: 4959ms
|
||||||
|
```
|
||||||
|
|
||||||
|
直接下载项目然后根据需求定制打包,最后通过 Hbuilder 云打包即可生成 APP.
|
||||||
|
|
||||||
|
> 本文自带一个案例是使用 VantUI 开发的几个界面,如果你喜欢其他 UI 同样可以替换成其他的 UI.
|
||||||
|
|
||||||
|
## 真机调试
|
||||||
|
|
||||||
|
将打印出来的 ip 地址,我们打印出来的是`http://192.168.199.155:8080/`,将这个填入页面入口.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后使用 Hbuilder 基座进行调试测试.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
主要怎么使用 MogoH5+做正式的开发,在开发过程中一定要遵守**目录规则**,否则会有意想不到的错误.
|
||||||
|
|
||||||
|
### 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── assets // 静态资源
|
||||||
|
├── docs // 文档
|
||||||
|
├── index.html // 入口模板
|
||||||
|
├── jsconfig.json //js配置
|
||||||
|
├── manifest.json //hbuilder 入口文件
|
||||||
|
├── src
|
||||||
|
│ ├── components //组件文件夹
|
||||||
|
│ │ └── List.vue //组件
|
||||||
|
│ ├── index.js //主页入口文件
|
||||||
|
│ ├── index.vue // 主页vue文件
|
||||||
|
│ ├── page // 页面
|
||||||
|
│ └── utils // 工具
|
||||||
|
├── unpackage // hbuilder 构建目录
|
||||||
|
│ └── res
|
||||||
|
└── webpack.config.js //webpack配置目录
|
||||||
|
```
|
||||||
|
|
||||||
|
### 新建页面
|
||||||
|
|
||||||
|
假如我们要新建一个名称为`list`的页面作为商品列表,我们就要在`./src/page/goods`下新建`list.js`和`list.vue`两个文件.`list.js`作为多页面的入口,`list.vue`,脚手架自带了几个页面可供参考.
|
||||||
|
|
||||||
|
::: tip 路由
|
||||||
|
遵循相对路径原则,如果在`src`访问这个页面则就是`./goods/list.html`
|
||||||
|
!!! 后缀一定是`.html`
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 新建页面/删除页面[0.3.0]
|
||||||
|
|
||||||
|
0.3.0 的新建页面和 0.2.0 是兼容的,但是建议您使用 0.3.0 的`page.json`,这样会减少很多因为新建,删除页面产生的错误
|
||||||
|
如果您需要更自由的页面结构,比如三级目录.可以按照`page.json`格式添加即可.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"goods/detail": "./src/page/goods/detail.js",
|
||||||
|
"map/map": "./src/page/map/map.js",
|
||||||
|
"mui/index": "./src/page/mui/index.js",
|
||||||
|
"user/index": "./src/page/user/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
比如您需要一个添加一个三级级页面,可以按照下面的方法添加,
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
...
|
||||||
|
"user/index/point": "./src/page/user/point/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果删除页面了页面,也需要删除`page.json`相应的页面描述代码
|
||||||
|
|
||||||
|
> 实现原理是监听了`page.json`,一旦`page.json`发生改变,会重启`webpack`
|
||||||
|
|
||||||
|
### 新建组件
|
||||||
|
|
||||||
|
组件放入`./src/components`目录下,如果组件较多,可自行建立目录.比如 demo 中使用的 Logo 组件可以作为参考.
|
||||||
|
|
||||||
|
### 新建工具库
|
||||||
|
|
||||||
|
工具库`./src/utils`主要放一些公用函数,比如请求,打开 webview,支付,分享等执行函数.
|
||||||
|
demo 中封装了部分来自 mui 的函数比如`自定义事件`,`webview`.这些函数可以作为参考.
|
||||||
|
|
||||||
|
::: tip
|
||||||
|
`common.js` 是每个页面都需要加载的一个 js,里面加载了`fastclick`和`vconsole`.如果全局需要加统计,全局执行的函数,可以放在这个文件里面.
|
||||||
|
|
||||||
|
`./src/utils` 做了 `alias`别名,可以 直接这样加载 `import common from "Utils/common"`.
|
||||||
|
:::
|
||||||
|
|
||||||
|
### 发送请求
|
||||||
|
|
||||||
|
#### 请求库
|
||||||
|
|
||||||
|
demo 的请求使用的是 `axios`,同样你喜欢什么库都可以自己去封装.
|
||||||
|
|
||||||
|
常见的请求库有`fetch`,`request`,`SuperAgent`,`jquery-ajax`.
|
||||||
|
|
||||||
|
#### 跨域
|
||||||
|
|
||||||
|
由于`npm start`后,调试网页是挂在局域网上,并且作为 Hbuilder 的`页面入口`,因此,在请求时会出现`跨域`.
|
||||||
|
|
||||||
|
在`./build.js`中使用本地代理,将下面的`https://api.douban.com`修改成自己使用的业务域名即可.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
name:"DOUBANAPI", // 自己取名
|
||||||
|
target: "https://api.douban.com",
|
||||||
|
pathRewrite: { "^/api": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
"/baidu_api": {
|
||||||
|
name:"BAIDUAPI", // 自己取名
|
||||||
|
target: "https://api.baidu.com",
|
||||||
|
pathRewrite: { "^/api": "" },
|
||||||
|
changeOrigin: true,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
如果有更多业务域名可以继续在`proxy`添加.
|
||||||
|
|
||||||
|
::: tip 注意
|
||||||
|
只有开发的时候才会有跨域问题,打包后的文件网址会被替换成被代理的网址,因此发送请求一定要加上名称`DOUBANAPI`
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
request({
|
||||||
|
url: DOUBANAPI + "/bookList"
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## 调试
|
||||||
|
|
||||||
|
在 Hbuilder 中调试会有诸多问题,比如:
|
||||||
|
|
||||||
|
- 不能直接打印`数组`,`对象`,需要转成字符串.
|
||||||
|
- 即使使用`webview调试`,仍然不能打印出数组,在 mac 上使用也非常不方便.
|
||||||
|
|
||||||
|
使用`VConsole`,调试的问题基本就脱离 Hbuilder 了,使用`VConsole`主要优点如下
|
||||||
|
|
||||||
|
- 可以打印数组,对象
|
||||||
|
- 可以查看请求,cookie,Localstorage
|
||||||
|
- 在`System`栏目中可以看到页面加载速度
|
||||||
|
- 可以查看元素
|
||||||
|
|
||||||
|
基本上就是一个简化的`开发者工具栏`,对于调试来说非常简便了.
|
||||||
|
|
||||||
|
## 打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
运行命令后会有一个`dist`目录,里面的经过压缩的静态文件.
|
||||||
|
|
||||||
|
### Hbuilder 发行打包
|
||||||
|
|
||||||
|
在使用 Hbuilder 制作安装包前,请将`入口文件`修改成`dist/index.html`.
|
||||||
|
然后可以安心的打包了.
|
||||||
|
|
||||||
|
## 如何使用 mui
|
||||||
|
|
||||||
|
mui 默认未加载,但是相对应的 js 和 css 放在了 `assets` 目录下.如果需要使用,请按下面步骤操作
|
||||||
|
|
||||||
|
### 1.去掉加载注释
|
||||||
|
|
||||||
|
在根目录下去掉下面两段标签的注释
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- 如果有使用mui,就不要注释下面两个标签 -->
|
||||||
|
<link rel="stylesheet" href="<%= htmlWebpackPlugin.options.muiSourcePath %>assets/css/mui.min.css">
|
||||||
|
<script src="<%= htmlWebpackPlugin.options.muiSourcePath %>assets/js/mui.min.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.使用`npm run build:mui`打包
|
||||||
|
|
||||||
|
> 这个命令会复制`assets`中的文件到打包目录.
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
常见问题一般来说就是白屏问题,或者页面不存在,可能有以下几种情况
|
||||||
|
|
||||||
|
**Q1:删除一些页面后控制台报错**
|
||||||
|
|
||||||
|
这是由于`HtmlWebpackPlugin`没有找到模板的问题,只需要重新`npm start`即可.
|
||||||
|
|
||||||
|
**Q2:`npm start`控制台报语法错误**
|
||||||
|
|
||||||
|
请升级你的 node 到最新版本
|
||||||
|
|
||||||
|
**Q3:`npm start`后出现空白页面无法显示**
|
||||||
|
|
||||||
|
1. 电脑和调试的手机需要在同一个局域网下面
|
||||||
|
2. `npm start`后如果局域网 ip 地址有变,请同时在 manifest.json 中修改页面入口
|
53
docs/guide/introduction.md
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
# 介绍
|
||||||
|
|
||||||
|
> MogoH5+ 是以一个 `vue+webpack` 的多页面脚手架,配合[HTML5+](http://www.html5plus.org/doc/h5p.html)使用可以快速开发安卓/苹果应用.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
下载 DEMO 体验[MogoH5+](https://fir.im/p52j)
|
||||||
|
|
||||||
|
文档是以`1.3.0`的基础上编写,如果您正在使用老版本出现问题,请加入 QQ 群 780150310 询问
|
||||||
|
|
||||||
|
## 特点
|
||||||
|
|
||||||
|
- **Vue 支持** 通过 vue 框架双向绑定等优点,可以快速开发出响应式 app 界面
|
||||||
|
- **ES6/ES7 支持** 支持使用 `ES7/ES8`甚至更加新的 ES 规范,享受 `async/await`
|
||||||
|
- **热更新** 支持`热更新`,自动化热更新平台正在内测中
|
||||||
|
- **npm 生态** 支持使用 `npm` 安装管理第三方依赖
|
||||||
|
- **css 预编译** 支持使用 `Less` 等
|
||||||
|
- **局域网调试** 无须数据线连接即可`调试`
|
||||||
|
- **vconsole 支持** 手机上享受`Chrome Dev Tools`一样的体验
|
||||||
|
|
||||||
|
想继续写,估计还可以写很多,很多...大概表达就是,这个东西很强大!
|
||||||
|
|
||||||
|
## 什么是 HTML5+
|
||||||
|
|
||||||
|
`HTML5+` 是一个运行环境,在这个环境下的网页都可以使用 `HTML5+`的 API,比如摄像头,定位,推送等原生 APP 才有的功能.
|
||||||
|
|
||||||
|
而这个运行环境的壳需要用`Hbuilder`来生成,所以需要搭配`Hbuilder`使用.
|
||||||
|
|
||||||
|
## 入门解疑
|
||||||
|
|
||||||
|
如果你要开发大型复杂 APP,游戏,请绕道....
|
||||||
|
|
||||||
|
### 兼容问题
|
||||||
|
|
||||||
|
`webapp`的本质就是`webview`,`webviwe` 也已经非常的成熟,比如小程序,因此,你知道如何处理网页兼容问题就可以了
|
||||||
|
|
||||||
|
### 性能问题
|
||||||
|
|
||||||
|
使用多`webview`来管理窗口,几乎满足大多数中小型 APP 的开发,可以安装 Demo 体验.
|
||||||
|
|
||||||
|
目前手机的性能越来越强,只要使用规范,可以接近原生界面.
|
||||||
|
|
||||||
|
### 与 mui 的关系
|
||||||
|
|
||||||
|
`mui`只是一个 ui 框架,`mui.js`中封装了很多`HTML5+`的方法.如果您追求性能,我们建议您最好不要使用任何 ui 框架.
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
您的赞助会使`MogoH5+`发展的更好,所赞助的资金都将提升`FEmirror 云更新`服务.
|
||||||
|
|
||||||
|
| 微信 | 支付宝 |
|
||||||
|
| ---------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
|
| <img width="200" :src="$withBase('/wxpay.JPG')" alt="foo"> | <img width="200" :src="$withBase('/alipay.JPG')" alt="foo"> |
|
7
docs/guide/practice/details.md
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
# 实现细节
|
||||||
|
|
||||||
|
## 多页面的实现
|
||||||
|
|
||||||
|
## nodemon 的使用
|
||||||
|
|
||||||
|
## mui 的加载
|
9
docs/guide/practice/webview.md
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# Webview
|
||||||
|
|
||||||
|
## openWebview()
|
||||||
|
|
||||||
|
## openWebviewFast()
|
||||||
|
|
||||||
|
## preLoad()
|
||||||
|
|
||||||
|
## showWebviewById()
|
18
docs/guide/production.md
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
# 发布
|
||||||
|
|
||||||
|
## 打包
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
运行命令后会有一个`dist`目录,里面的经过压缩的静态文件.
|
||||||
|
|
||||||
|
### Hbuilder 发行打包
|
||||||
|
|
||||||
|
在使用 Hbuilder 制作安装包前,请将`入口文件`修改成`dist/index.html`.
|
||||||
|
然后可以安心的打包了.
|
||||||
|
|
||||||
|
## 热更新包
|
||||||
|
|
||||||
|
在 Hbuilder 菜单栏中选择`发布`->`制作移动APP资源升级包`,得到的`wgt`文件是可以用来更新的
|
84
docs/guide/qa.md
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
# 常见问题
|
||||||
|
|
||||||
|
常见问题一般来说就是白屏问题,或者页面不存在,可能有以下几种情况
|
||||||
|
|
||||||
|
**Q1:删除一些页面后控制台报错**
|
||||||
|
|
||||||
|
这是由于`HtmlWebpackPlugin`没有找到模板的问题,只需要重新`npm start`即可.
|
||||||
|
|
||||||
|
**Q2:`npm start`控制台报语法错误**
|
||||||
|
|
||||||
|
请升级你的 node 到最新版本
|
||||||
|
|
||||||
|
**Q3:`npm start`后出现空白页面无法显示**
|
||||||
|
|
||||||
|
1. 电脑和调试的手机需要在同一个局域网下面
|
||||||
|
2. `npm start`后如果局域网 ip 地址有变,请同时在 manifest.json 中修改页面入口
|
||||||
|
|
||||||
|
## 速度优化方案
|
||||||
|
|
||||||
|
最近许多反映脚手架很慢的可以参考一下优化方案,可以大大提高调试/打包速度.
|
||||||
|
|
||||||
|
1.2 的版本中移除了一些不必要的插件,应该会快那么一点吧.追求速度的继续往下看.
|
||||||
|
|
||||||
|
由于 demo 需要展示各种 ui,加载了各种的 ui 的 loader,所以如果开发者用不到可以将其移除.
|
||||||
|
|
||||||
|
### 1.如果不使用 VUX
|
||||||
|
|
||||||
|
注释掉 `vux-loader` 即可,在`webpack.base.conf.js`中,修改以下代码
|
||||||
|
|
||||||
|
```js
|
||||||
|
const vuxLoader = require("vux-loader");
|
||||||
|
|
||||||
|
module.exports = vuxLoader.merge(webpackConfig, {
|
||||||
|
plugins: ["vux-ui"]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
修改后
|
||||||
|
|
||||||
|
```js
|
||||||
|
module.exports = webpackConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.如果不使用 vant
|
||||||
|
|
||||||
|
移除掉`.babalrc`中以下代码
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
"import",
|
||||||
|
{
|
||||||
|
"libraryName": "vant",
|
||||||
|
"libraryDirectory": "es",
|
||||||
|
"style": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 自定义返回按钮事件
|
||||||
|
|
||||||
|
演示可以在 demo 中购物车页面查看,实现代码如下
|
||||||
|
|
||||||
|
```js
|
||||||
|
plus.key.removeEventListener("backbutton", function() {
|
||||||
|
console.log(5555);
|
||||||
|
});
|
||||||
|
plus.key.addEventListener(
|
||||||
|
"backbutton",
|
||||||
|
function() {
|
||||||
|
// nativeUI.conf
|
||||||
|
// nativeUI.con
|
||||||
|
confirm("确认要离开么?").then(e => {
|
||||||
|
if (e.index === 0) {
|
||||||
|
plus.nativeUI.toast("离开了");
|
||||||
|
const ws = plus.webview.currentWebview();
|
||||||
|
ws.hide();
|
||||||
|
} else {
|
||||||
|
plus.nativeUI.toast("留住了");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
```
|
140
docs/guide/update_log.md
Executable file
@ -0,0 +1,140 @@
|
|||||||
|
# 更新日志
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 1.3.0 [20180727]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
1. 增加`热更新/迭代`集成,具体文档查看[热更新/迭代](../practice/hotfix.md)
|
||||||
|
2. 增加自定义返回实现,返回按钮可以[自定义返回按钮事件](./qa.html#自定义返回按钮事件)
|
||||||
|
3. 增加"商品加入购物车"功能实例演示页面间通讯
|
||||||
|
4. 新增 VConsole 以 webpack 插件的形式加载,`run build`会自动去掉
|
||||||
|
|
||||||
|
#### [修复]
|
||||||
|
|
||||||
|
1. 修复了超多页面下调试慢的问题,使用`html-webpack-plugin-for-multihtml`解决
|
||||||
|
2. 修改了版本文档
|
||||||
|
|
||||||
|
#### [升级指导]
|
||||||
|
|
||||||
|
1. 将 VConsole 在 common.js 中删掉,因为已经以 webpack 插件形式加载
|
||||||
|
2. `utils` 是我们会经常修改的, 如果有自己的工具库,请另建文件夹
|
||||||
|
|
||||||
|
### 1.2.0 [20180719]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
- 增加预加载窗口打开方式,根据不同场景使用不同的打开方式,可以大大提高 webview 的打开速度,首页已加入使用案例
|
||||||
|
- 由于 VConsole 并不能解决全部调试问题,增加一个`print`方法,用于在 Hbuilder 上打印对象
|
||||||
|
|
||||||
|
#### [速度优化方案]
|
||||||
|
|
||||||
|
最近许多反映脚手架很慢的可以参考一下优化方案,可以大大提高调试/打包速度.
|
||||||
|
|
||||||
|
1.2 的版本中移除了一些不必要的插件,应该会快那么一点吧.追求速度的继续往下看.
|
||||||
|
|
||||||
|
由于 demo 需要展示各种 ui,加载了各种的 ui 的 loader,所以如果开发者用不到可以将其移除.
|
||||||
|
|
||||||
|
##### 1.如果不使用 VUX
|
||||||
|
|
||||||
|
注释掉 `vux-loader` 即可,在`webpack.base.conf.js`中,修改以下代码
|
||||||
|
|
||||||
|
```
|
||||||
|
const vuxLoader = require("vux-loader");
|
||||||
|
|
||||||
|
module.exports = vuxLoader.merge(webpackConfig, {
|
||||||
|
plugins: ["vux-ui"]
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
修改后
|
||||||
|
|
||||||
|
```
|
||||||
|
module.exports = webpackConfig;
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 2.如果不使用 vant
|
||||||
|
|
||||||
|
移除掉`.babalrc`中以下代码
|
||||||
|
|
||||||
|
```
|
||||||
|
[
|
||||||
|
"import",
|
||||||
|
{
|
||||||
|
"libraryName": "vant",
|
||||||
|
"libraryDirectory": "es",
|
||||||
|
"style": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 3.优化建议
|
||||||
|
|
||||||
|
对于一些简单的页面其实可以不用 ui 框架,加载的时候会很快
|
||||||
|
使用 ui 框架大概也只会增加 100-200ms 的 js 运行时间,窗口过渡 200ms 的话,基本上不会影响用户体验
|
||||||
|
如果使用大量组件,增加的时间可能会比较大,这个时候可以考虑预加载这个窗口了.
|
||||||
|
|
||||||
|
参考:http://ask.dcloud.net.cn/article/25
|
||||||
|
|
||||||
|
#### [升级方案]
|
||||||
|
|
||||||
|
几乎每个版本都是兼容的,所以只要将`src`中的文件转移到新版本就 ok 啦!
|
||||||
|
|
||||||
|
#### [终极解决:webpack4]
|
||||||
|
|
||||||
|
由于官方的 `webpack3` 脚手架速度也提升不了多少了,所以 `1.2` 之后的 `1.x` 版本之后可能几乎不会对脚手架做修改了,只会增加很多实用的使用案例和工具方法
|
||||||
|
|
||||||
|
不过现在已经开始对 `webpack4` 开始研究了 webpack4 `2.0`版本见啦
|
||||||
|
|
||||||
|
### 1.1.0 [20180706]
|
||||||
|
|
||||||
|
#### [新增]
|
||||||
|
|
||||||
|
- `page.json`可以配置是否加载 mui 或者是否使用 plusready
|
||||||
|
- 增加`fire`页面传值函数,详情可见商品详情页和首页的自定义事件
|
||||||
|
|
||||||
|
#### [修复]
|
||||||
|
|
||||||
|
- 修复了资源路径加载问题(需修改`page.json`配置)
|
||||||
|
- 修复了 mui 加载不灵活的问题,减少打包的体积
|
||||||
|
- 修复了 mui 字体文件加载失败的问题
|
||||||
|
|
||||||
|
#### 1.0.x 到 1.1.x
|
||||||
|
|
||||||
|
由于之前资源路径的问题,目前的解决方案是修改`page.json`的配置,将原来的以路径作为键`mui/index`写成`mui.index`即可,如下
|
||||||
|
|
||||||
|
如果要使用 mui 就加入 `|mui`, 如果要使用 mui 就加入 `|plusReady`,不用则不加.
|
||||||
|
|
||||||
|
> plusReady 在安卓手机上提前载入可能会影响页面打开速度,解决方法有两种:1 不提前使 plus 生效 2.预加载 plus
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mui.index|mui|plusReady": "./src/page/mui/index.js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 注意事项
|
||||||
|
|
||||||
|
请在`created`生命周期里面接收事件,否则会因为视图刷新多次执行.
|
||||||
|
|
||||||
|
### 1.0.1 [20180704]
|
||||||
|
|
||||||
|
- 修复了 background 图片路径打包后不正确的问题
|
||||||
|
|
||||||
|
### 1.0.0 [20180630]
|
||||||
|
|
||||||
|
- 使用 vue 官方脚手架作为基层,健壮性得到`史诗级`提升
|
||||||
|
- 添加了 vux 的支持
|
||||||
|
- 修改的 mui 的加载方式
|
||||||
|
- 配置方面有部分变化,详情请看文档
|
||||||
|
- 升级了安卓 app
|
||||||
|
|
||||||
|
### 0.3.0 [20180628]
|
||||||
|
|
||||||
|
- 解决了因为新增/删除页面导致的 webpack 错误
|
||||||
|
- 添加了 openWebview 的 extras 参数
|
||||||
|
|
||||||
|
### 0.2.0 [20180623]
|
||||||
|
|
||||||
|
- 添加了对 mui 样式和 js 的支持
|
74
docs/hotfix/config.md
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
# Hotfix配置
|
||||||
|
|
||||||
|
热更新能够不提交应用商店审核而修改 APP 内容,使得 app 的迭代变的非常灵活.
|
||||||
|
|
||||||
|
`MogoH5+`在`1.3.0`后加入了`热更新/安装更新`的集成.同时,我们的`热更新服务器`也在内测中,将在不久公测使用.您无需后端就可以完成整个软件的`热更新/安装更新`服务.
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
在使用热更新前,请看完这份介绍再使用.
|
||||||
|
|
||||||
|
### 热更新
|
||||||
|
|
||||||
|
对于安卓来说,热更新是没有任何问题的,但是苹果您可以看下面这段话.
|
||||||
|
|
||||||
|
#### App store 应用更新说明(引自 dcloud)
|
||||||
|
|
||||||
|
> 应用资源更新肯定是违反 apple 政策的,但目前看起来它也不管。你在官网案例那里下载 Appstore 版本的那些 app,大多启动后都会提示更新,反正也都没下架。如果你不是很大的公司,apple 不会理睬你。如果你是大公司,建议不要做整体更新,每次更新几个页面,也不要提示更新后需要重启,这样会安全点。
|
||||||
|
|
||||||
|
作者本人的实践中也经常使用热更新,名声不大,不频繁基本上可以自由使用.
|
||||||
|
同样,我们加入了`静默更新`这种比较无脑的更新.
|
||||||
|
|
||||||
|
### 安装更新
|
||||||
|
|
||||||
|
安装更新在这里指的就是更新大版本,比如添加了模块,必须重新安装.
|
||||||
|
|
||||||
|
#### 在安卓的安装更新
|
||||||
|
|
||||||
|
1. 可以让 APP 提示,然后用户选择自己下载安装
|
||||||
|
2. 应用商店更新
|
||||||
|
|
||||||
|
#### 在苹果的安装更新
|
||||||
|
|
||||||
|
1. 必须提交 AppStore 提交审核
|
||||||
|
|
||||||
|
在这里顺便提一下,苹果用户的习惯一般是自己主动更新.
|
||||||
|
在苹果应用商店的大厂 app (微信,淘宝,京东) 更新几乎不会受到 app 的更新推送,也没有所谓`检查更新`的功能,也就是说,更新是用户主动操作的.我们的`迭代`同样也遵循这条`行规`.
|
||||||
|
|
||||||
|
|
||||||
|
## Hotfix参数
|
||||||
|
|
||||||
|
|参数|说明|类型|
|
||||||
|
|-|-|---|
|
||||||
|
|`url`|更新请求地址|string|
|
||||||
|
|`before(data)`| `data`返回的是请求后的`json`数据; 可在函数中执行安装前进行的操作,在此函数中,可以做一些确认操作,返回`Promise.resolve()`则执行下载安装,不返回或返回其他则不执行下载安装|`Promise`|
|
||||||
|
|`success`|安装完成后执行的动作,比如重启app|`void`|
|
||||||
|
|`error(e)`|返回error对象,一般在调试中使用|`Error`|
|
||||||
|
|`onProgress(n)`|下载进度,`n`为0-100的下载进度|`int`|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 后端接收的数据格式
|
||||||
|
|
||||||
|
`checkUpdate(url)` 是以 `POST` 去访问 URL 的.数据类型为`application/json`
|
||||||
|
|
||||||
|
| 名称 | 描述 | 类型 |
|
||||||
|
| ------- | ------------------------------- | ------ |
|
||||||
|
| version | app 当前的版本 ,如 2.1.0 | string |
|
||||||
|
| os | app 设备的系统信息 比如系统版本 | json |
|
||||||
|
| device | app 设备的设备信息 比如 uuid | json |
|
||||||
|
|
||||||
|
## 后端返回的数据格式
|
||||||
|
|
||||||
|
下面是一个完整的数据返回 返回格式为`application/json` ,返回状态码为`200`.
|
||||||
|
|
||||||
|
> 注意 : 返回`200`以外的状态码将不被处理,如果想自行处理可以改写代码
|
||||||
|
|
||||||
|
| 名称 | 描述 | 参数 |
|
||||||
|
| -------------- | --------------------------------------------------------------- | ------------------------ |
|
||||||
|
| name | 版本号 如果检测的版本大于本地版本就会更新 | string |
|
||||||
|
| title | 升级提示标题 | string |
|
||||||
|
| description | 升级提示内容 | string |
|
||||||
|
| platform | 符合升级的平台 ios:升级苹果 android:升级安卓 both:都更新 | `ios` ,`android`, `both` |
|
||||||
|
| hotupdate_type | 更新提示 silence:静默更新 tip:提示更新 (apk 的安装是需要提示的) | `silence`,`tip` |
|
||||||
|
| android_url | 更新下载地址 以`.apk`,`.wgt`结尾的 http 地址 | url |
|
35
docs/hotfix/hotfitxFemirror.md
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
# Hotfix 云更新
|
||||||
|
|
||||||
|
Hotfix 云更新的架构设计是`Mysql`+`Redis`+`Egg.js(typescript)`.对内存占用极低,可用性比较高.
|
||||||
|
|
||||||
|
`Hotfix 云更新` 是一个自动化更新平台,无需后端也可以完成 app 日常更新.
|
||||||
|
|
||||||
|
> Hotfix 云更新仅提供测试性功能,不能保障服务的`稳定性`,因此,如果您有商业需求,可以联系作者进行有偿`私有化部署`.
|
||||||
|
|
||||||
|
<img :src="$withBase('/h2.png')" alt="foo">
|
||||||
|
|
||||||
|
## [访问网站](https://hotfix.femirror.com/)
|
||||||
|
|
||||||
|
## 使用指南
|
||||||
|
|
||||||
|
### 注册
|
||||||
|
|
||||||
|
使用`Github`授权登录.
|
||||||
|
|
||||||
|
### 操作步骤
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<img style="box-shadow:0 0 20px #ccc" :src="$withBase('/hotfix/1.png')" alt="foo">
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<img style="box-shadow:0 0 20px #ccc" :src="$withBase('/hotfix/2.png')" alt="foo">
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<img style="box-shadow:0 0 20px #ccc" :src="$withBase('/hotfix/3.png')" alt="foo">
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<img style="box-shadow:0 0 20px #ccc" :src="$withBase('/hotfix/4.png')" alt="foo">
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<img style="box-shadow:0 0 20px #ccc" :src="$withBase('/hotfix/5.png')" alt="foo">
|
70
docs/hotfix/introduction.md
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
# 介绍
|
||||||
|
|
||||||
|
> `Hotfix`+`FEmirror 云更新` 只需`几分钟` , 让您的 H5+应用快速拥有热更新功能.
|
||||||
|
|
||||||
|
|
||||||
|
| iphone 热更新 效果如下 | 安卓热更新效果如下 | 安卓安装更新如下 |
|
||||||
|
| ---------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||||
|
| <img width="400" :src="$withBase('/IMG_0040.PNG')" alt="foo"> | <img width="400" :src="$withBase('/S80805-211149.jpg')" alt="foo"> | <img width="400" :src="$withBase('/S80806-112100.jpg')" alt="foo"> |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 快速使用 [项目地址](https://github.com/tyaqing/hotfix)
|
||||||
|
|
||||||
|
### 安装
|
||||||
|
#### npm 安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm i h5plus-hotfix -S
|
||||||
|
```
|
||||||
|
|
||||||
|
#### script加载
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="hotfix-bs.js"></script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用
|
||||||
|
|
||||||
|
```js
|
||||||
|
hotfix({
|
||||||
|
url: updateUrl,
|
||||||
|
before(data) {
|
||||||
|
// 确认安装
|
||||||
|
return new Promise(resolve => {
|
||||||
|
plus.nativeUI.confirm(data.title, (selected) => {
|
||||||
|
if (selected.index === 0) {
|
||||||
|
plus.nativeUI.showWaiting("下载更新文件...");
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
title: data.description,
|
||||||
|
buttons: ["确认更新", "取消"],
|
||||||
|
verticalAlign: "bottom"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
success() {
|
||||||
|
console.log('安装成功')
|
||||||
|
plus.runtime.restart(); // 重启app
|
||||||
|
plus.nativeUI.closeWaiting();
|
||||||
|
},
|
||||||
|
error(e) {
|
||||||
|
// 错误显示
|
||||||
|
plus.nativeUI.closeWaiting();
|
||||||
|
console.log("安装wgt文件失败[" + e.code + "]:" + e.message);
|
||||||
|
plus.nativeUI.alert("安装wgt文件失败[" + e.code + "]:" + e.message);
|
||||||
|
},
|
||||||
|
onProgress(p) {
|
||||||
|
console.log(p) // 下载进度
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
您的赞助会使`MogoH5+`发展的更好,所赞助的资金都将提升`FEmirror 云更新`服务.
|
||||||
|
|
||||||
|
| 微信 | 支付宝 |
|
||||||
|
| ---------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
|
| <img width="200" :src="$withBase('/wxpay.JPG')" alt="foo"> | <img width="200" :src="$withBase('/alipay.JPG')" alt="foo"> |
|
59
docs/hotfix/old/hotfitxFemirror.md
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
# FEmirror 云更新
|
||||||
|
|
||||||
|
`FEmirror 云更新` 是一个自动化更新平台,无需后端也可以完成 app 日常更新.
|
||||||
|
|
||||||
|
<img :src="$withBase('/h2.png')" alt="foo">
|
||||||
|
|
||||||
|
## [访问网站](https://hotfix.femirror.com/)
|
||||||
|
|
||||||
|
## 使用指南
|
||||||
|
|
||||||
|
### 注册
|
||||||
|
|
||||||
|
使用`Github`授权登录.
|
||||||
|
|
||||||
|
### 上传更新包
|
||||||
|
|
||||||
|
点击左侧`点击/拖动上传升级包`按钮上传升级文件.
|
||||||
|
|
||||||
|
可以上传`apk`,`wgt`两种类型的文件.
|
||||||
|
|
||||||
|
文件上传成功后在`应用管理`列表中会出现您刚刚上传的更新包信息.
|
||||||
|
|
||||||
|
<img :src="$withBase('/h3.png')" alt="foo">
|
||||||
|
|
||||||
|
### wgt 热更新的发布
|
||||||
|
|
||||||
|
点击`发布`按钮,如下图,提供几种参数供您选择.
|
||||||
|
|
||||||
|
<img :src="$withBase('/h1.png')" alt="foo">
|
||||||
|
#### 更新方式的选择
|
||||||
|
|
||||||
|
1. 静默更新 : 使用`checkUpdate`方法后检查更新,如果有更新会自动下载 app,整个过程没有任何提示,用户第二次打开 app 就会出现更新后的效果.
|
||||||
|
2. 提示更新 : 使用`checkUpdate`方法后检查更新,如果有则会弹出确认框,用户确认后会提示正在下载,正在安装,安装完成重启,更新完成等提示.
|
||||||
|
|
||||||
|
#### 更新平台的选择
|
||||||
|
|
||||||
|
如果只需要某一个平台更新,可以根据需求选择
|
||||||
|
|
||||||
|
| iphone 效果如下 | 安卓效果如下 |
|
||||||
|
| ---------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||||
|
| <img width="380" :src="$withBase('/IMG_0040.PNG')" alt="foo"> | <img width="380" :src="$withBase('/S80805-211149.jpg')" alt="foo"> |
|
||||||
|
|
||||||
|
### app 更新的发布
|
||||||
|
|
||||||
|
app 更新只适用于`安卓 apk` 类型,也就是下载更新包后执行安装.
|
||||||
|
|
||||||
|
### 关闭更新
|
||||||
|
|
||||||
|
在应用详情的右上角可以关闭更新,关闭更新后用户检查更新后不会作处理
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 提示版本不一致
|
||||||
|
|
||||||
|
在调试热更新的时候必须使用自定义基座,否则得到的版本是 `Hbuilder H5+ App` 的版本.
|
||||||
|
|
||||||
|
### 更新替换
|
||||||
|
|
||||||
|
由于这种热更新是替换更新,新的热更新包如果有问题,可能导致 app 无法使用,请测试成功后再发布,或者您上传一个专用于测试的 app
|
122
docs/hotfix/old/hotfix.md
Executable file
@ -0,0 +1,122 @@
|
|||||||
|
# Hotfix [项目地址](https://github.com/tyaqing/hotfix)
|
||||||
|
|
||||||
|
热更新能够不提交应用商店审核而修改 APP 内容,使得 app 的迭代变的非常灵活.
|
||||||
|
|
||||||
|
`MogoH5+`在`1.3.0`后加入了`热更新/安装更新`的集成.同时,我们的`热更新服务器`也在内测中,将在不久公测使用.您无需后端就可以完成整个软件的`热更新/安装更新`服务.
|
||||||
|
|
||||||
|
| iphone 热更新 效果如下 | 安卓热更新效果如下 | 安卓安装更新如下 |
|
||||||
|
| ---------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||||
|
| <img width="400" :src="$withBase('/IMG_0040.PNG')" alt="foo"> | <img width="400" :src="$withBase('/S80805-211149.jpg')" alt="foo"> | <img width="400" :src="$withBase('/S80806-112100.jpg')" alt="foo"> |
|
||||||
|
|
||||||
|
## 介绍
|
||||||
|
|
||||||
|
在使用热更新前,请看完这份介绍再使用.
|
||||||
|
|
||||||
|
### 热更新
|
||||||
|
|
||||||
|
对于安卓来说,热更新是没有任何问题的,但是苹果您可以看下面这段话.
|
||||||
|
|
||||||
|
#### App store 应用更新说明(引自 dcloud)
|
||||||
|
|
||||||
|
> 应用资源更新肯定是违反 apple 政策的,但目前看起来它也不管。你在官网案例那里下载 Appstore 版本的那些 app,大多启动后都会提示更新,反正也都没下架。如果你不是很大的公司,apple 不会理睬你。如果你是大公司,建议不要做整体更新,每次更新几个页面,也不要提示更新后需要重启,这样会安全点。
|
||||||
|
|
||||||
|
作者本人的实践中也经常使用热更新,名声不大,不频繁基本上可以自由使用.
|
||||||
|
同样,我们加入了`静默更新`这种比较无脑的更新.
|
||||||
|
|
||||||
|
### 安装更新
|
||||||
|
|
||||||
|
安装更新在这里指的就是更新大版本,比如添加了模块,必须重新安装.
|
||||||
|
|
||||||
|
#### 在安卓的安装更新
|
||||||
|
|
||||||
|
1. 可以让 APP 提示,然后用户选择自己下载安装
|
||||||
|
2. 应用商店更新
|
||||||
|
|
||||||
|
#### 在苹果的安装更新
|
||||||
|
|
||||||
|
1. 必须提交 AppStore 提交审核
|
||||||
|
|
||||||
|
在这里顺便提一下,苹果用户的习惯一般是自己主动更新.
|
||||||
|
在苹果应用商店的大厂 app (微信,淘宝,京东) 更新几乎不会受到 app 的更新推送,也没有所谓`检查更新`的功能,也就是说,更新是用户主动操作的.我们的`迭代`同样也遵循这条`行规`.
|
||||||
|
|
||||||
|
## 引入方式
|
||||||
|
|
||||||
|
可以在`main.js`中添加`checkUpdate(URL);`,打开 app 就会自动检测.还可以放在`检查更新`的按钮上触发.
|
||||||
|
|
||||||
|
### ES6 Module 引入
|
||||||
|
|
||||||
|
首先在`page.json`把用到`checkUpdate`的页面加上管道`|plusReady`.
|
||||||
|
|
||||||
|
然后加载使用.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { checkUpdate } from "./utils/hotfix";
|
||||||
|
checkUpdate(URL); // 填入您检查api的url地址
|
||||||
|
```
|
||||||
|
|
||||||
|
### `<script>`方式引入
|
||||||
|
|
||||||
|
这种用于没有使用脚手架的开发者
|
||||||
|
|
||||||
|
```html
|
||||||
|
<title>APP</title>
|
||||||
|
<script src="html5plus://ready"></script> // 这段必须加载title底下
|
||||||
|
....
|
||||||
|
<script src="path/hotfix-bs.js"></script>
|
||||||
|
<script>
|
||||||
|
checkUpdate('https://api.hotfix.femirror.com/public/app/checkUpdate?bundleId=你的appId'); // 填入您检查api的url地址
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 热更新配置
|
||||||
|
|
||||||
|
热更新分为两种,在 ios 和安卓都可以使用:
|
||||||
|
|
||||||
|
1. 静默更新 : 使用`checkUpdate`方法后检查更新,如果有更新会自动下载 app,整个过程没有任何提示,用户第二次打开 app 就会出现更新后的效果.
|
||||||
|
2. 提示更新 : 使用`checkUpdate`方法后检查更新,如果有则会弹出确认框,用户确认后会提示正在下载,正在安装,安装完成重启,更新完成等提示.
|
||||||
|
|
||||||
|
如果您更新后不想立即重启,可以注释掉`hotfix.js`中的函数`plus.runtime.restart();`,这样,app 会在用户第二打开的时候自动完成更新.
|
||||||
|
|
||||||
|
## 后端接收的数据格式
|
||||||
|
|
||||||
|
`checkUpdate(url)` 是以 `POST` 去访问 URL 的.数据类型为`application/json`
|
||||||
|
|
||||||
|
| 名称 | 描述 | 类型 |
|
||||||
|
| ------- | ------------------------------- | ------ |
|
||||||
|
| version | app 当前的版本 ,如 2.1.0 | string |
|
||||||
|
| os | app 设备的系统信息 比如系统版本 | json |
|
||||||
|
| device | app 设备的设备信息 比如 uuid | json |
|
||||||
|
|
||||||
|
## 后端返回的数据格式
|
||||||
|
|
||||||
|
下面是一个完整的数据返回 返回格式为`application/json` ,返回状态码为`200`.
|
||||||
|
|
||||||
|
> 注意 : 返回`200`以外的状态码将不被处理,如果想自行处理可以改写代码
|
||||||
|
|
||||||
|
| 名称 | 描述 | 参数 |
|
||||||
|
| -------------- | --------------------------------------------------------------- | ------------------------ |
|
||||||
|
| name | 版本号 如果检测的版本大于本地版本就会更新 | string |
|
||||||
|
| title | 升级提示标题 | string |
|
||||||
|
| description | 升级提示内容 | string |
|
||||||
|
| platform | 符合升级的平台 ios:升级苹果 android:升级安卓 both:都更新 | `ios` ,`android`, `both` |
|
||||||
|
| type | 安装类型 wgt:热更新 apk:安装更新 | `wgt`,`apk` |
|
||||||
|
| hotupdate_type | 更新提示 silence:静默更新 tip:提示更新 (apk 的安装是需要提示的) | `silence`,`tip` |
|
||||||
|
| android_url | 更新下载地址 以`.apk`,`.wgt`结尾的 http 地址 | url |
|
||||||
|
|
||||||
|
下面这段`json`可以表达为:
|
||||||
|
|
||||||
|
1. 更新平台为 `全部平台`
|
||||||
|
2. `热更新`
|
||||||
|
3. `提示更新`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "2.2.1",
|
||||||
|
"title": "发现新版本,快来使用吧!",
|
||||||
|
"description": "1.增加了....\n 2.修复了... 3.杀了一个程序员祭天",
|
||||||
|
"platform": "both",
|
||||||
|
"type": "wgt",
|
||||||
|
"hotupdate_type": "tip",
|
||||||
|
"android_url": "http://cdn.femirror.com/H5FD926B1.wgt"
|
||||||
|
}
|
||||||
|
```
|
49
docs/hotfix/old/introduction.md
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
# 介绍
|
||||||
|
|
||||||
|
> `Hotfix`+`FEmirror 云更新` 让您的 H5+应用快速拥有热更新功能.
|
||||||
|
|
||||||
|
只需`几分钟`,让您的应用拥有更新能力!
|
||||||
|
|
||||||
|
| iphone 热更新 效果如下 | 安卓热更新效果如下 | 安卓安装更新如下 |
|
||||||
|
| ---------------------------------------------------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||||
|
| <img width="400" :src="$withBase('/IMG_0040.PNG')" alt="foo"> | <img width="400" :src="$withBase('/S80805-211149.jpg')" alt="foo"> | <img width="400" :src="$withBase('/S80806-112100.jpg')" alt="foo"> |
|
||||||
|
|
||||||
|
### Hotfix
|
||||||
|
|
||||||
|
`Hotfix` 是一个适用于 H5+应用的一个`拓展库`.可以自动完成热更新,和安装更新任务.
|
||||||
|
|
||||||
|
只要您的 app 是使用 Hbuilder 开发的,就可以使用 `Hotfix`.具体接入方式请[查看教程](hotfix.md)
|
||||||
|
|
||||||
|
### 云更新
|
||||||
|
|
||||||
|
`更新云` 是一个`app`版本更新的管理平台,提供版本更新服务.
|
||||||
|
|
||||||
|
单独的 `Hotfix` 还需要后端的协作,比如`版本管理`,`下载服务`.
|
||||||
|
|
||||||
|
`FEmirror 云更新`就是为您提供`版本管理`,`下载服务`的服务的.
|
||||||
|
|
||||||
|
### 如何 3 分钟接入云更新
|
||||||
|
|
||||||
|
#### 1.如果您是 MogoH5+ 开发者
|
||||||
|
|
||||||
|
如果您是`MogoH5+`的开发者,`1.3`后是内置了热更新,只要后端完成相关更新逻辑,就可以使用了.
|
||||||
|
|
||||||
|
如果想要更快的方式接入,可以使用`FEmirror 云更新`
|
||||||
|
|
||||||
|
#### 2.如果您是 Hbuilder 开发者
|
||||||
|
|
||||||
|
如果您的应用是使用`mui`开发,也没有使用`Mogoh5+`,您可以以`<script>`的方式引入`hotfix`获得更新能力.
|
||||||
|
|
||||||
|
同样,搭配`FEmirror 云更新`使用可以让您快速获得热更新能力.
|
||||||
|
|
||||||
|
### `FEmirror 云更新` 下一步计划
|
||||||
|
|
||||||
|
下一步会加入数据统计,比如安装设备的系统分布,版本分布等,您也可以提出宝贵意见
|
||||||
|
|
||||||
|
## 赞助
|
||||||
|
|
||||||
|
您的赞助会使`MogoH5+`发展的更好,所赞助的资金都将提升`FEmirror 云更新`服务.
|
||||||
|
|
||||||
|
| 微信 | 支付宝 |
|
||||||
|
| ---------------------------------------------------------- | ------------------------------------------------------------- |
|
||||||
|
| <img width="200" :src="$withBase('/wxpay.JPG')" alt="foo"> | <img width="200" :src="$withBase('/alipay.JPG')" alt="foo"> |
|
32
docs/hotfix/old/usage.md
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
# 接入方式
|
||||||
|
|
||||||
|
## 引入方式
|
||||||
|
|
||||||
|
可以在`main.js`中添加`checkUpdate(URL);`,打开 app 就会自动检测.还可以放在`检查更新`的按钮上触发.
|
||||||
|
|
||||||
|
### ES6 Module 引入
|
||||||
|
|
||||||
|
首先在`page.json`把用到`checkUpdate`的页面加上管道`|plusReady`.
|
||||||
|
|
||||||
|
然后加载使用.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { checkUpdate } from "./utils/update";
|
||||||
|
checkUpdate(URL); // 填入您检查api的url地址
|
||||||
|
```
|
||||||
|
|
||||||
|
### `<script>`方式引入
|
||||||
|
|
||||||
|
这种用于没有使用脚手架的开发者
|
||||||
|
|
||||||
|
```html
|
||||||
|
<title>APP</title>
|
||||||
|
<script src="html5plus://ready"></script> // 这段必须加载title底下
|
||||||
|
....
|
||||||
|
<script src="path/update.js"></script>
|
||||||
|
<script>
|
||||||
|
checkUpdate('https://api.hotfix.femirror.com/public/app/checkUpdate?bundleId=你的appId'); // 填入您检查api的url地址
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
如果您没有后端接入,可以使用`FEmirror云更新`
|
17
index.html
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" />
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<%= htmlWebpackPlugin.options.plusReady %>
|
||||||
|
<!-- 如果有使用mui,就不要注释下面的标签 -->
|
||||||
|
<%= htmlWebpackPlugin.options.muiCssString %>
|
||||||
|
<title>Mogo H5plus</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<%= htmlWebpackPlugin.options.muiScriptString %>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
302
manifest.json
Executable file
@ -0,0 +1,302 @@
|
|||||||
|
{
|
||||||
|
"@platforms" : [ "android", "iPhone" ],
|
||||||
|
"id" : "H514CC633", /*应用的标识,创建应用时自动生成,勿手动修改*/
|
||||||
|
"name" : "MogoH5+", /*应用名称,程序桌面图标名称*/
|
||||||
|
"version" : {
|
||||||
|
"name" : "1.6.0", /*应用版本名称*/
|
||||||
|
"code" : "141"
|
||||||
|
},
|
||||||
|
"description" : "MogoH5+", /*应用描述信息*/
|
||||||
|
"icons" : {
|
||||||
|
"72" : "icon.png"
|
||||||
|
},
|
||||||
|
"launch_path" : "http://192.168.0.101:8080", /*应用的入口页面,默认为根目录下的index.html;支持网络地址,必须以http://或https://开头*/
|
||||||
|
"developer" : {
|
||||||
|
"name" : "", /*开发者名称*/
|
||||||
|
"email" : "", /*开发者邮箱地址*/
|
||||||
|
"url" : "" /*开发者个人主页地址*/
|
||||||
|
},
|
||||||
|
"permissions" : {
|
||||||
|
"Cache" : {
|
||||||
|
"description" : "管理应用缓存"
|
||||||
|
},
|
||||||
|
"Console" : {
|
||||||
|
"description" : "跟踪调试输出日志"
|
||||||
|
},
|
||||||
|
"Contacts" : {
|
||||||
|
"description" : "访问系统联系人信息"
|
||||||
|
},
|
||||||
|
"Events" : {
|
||||||
|
"description" : "应用扩展事件"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"plus" : {
|
||||||
|
"statusbar" : {
|
||||||
|
"immersed" : true,
|
||||||
|
"style" : "dark"
|
||||||
|
},
|
||||||
|
"splashscreen" : {
|
||||||
|
"autoclose" : true, /*是否自动关闭程序启动界面,true表示应用加载应用入口页面后自动关闭;false则需调plus.navigator.closeSplashscreen()关闭*/
|
||||||
|
"waiting" : true /*是否在程序启动界面显示等待雪花,true表示显示,false表示不显示。*/
|
||||||
|
},
|
||||||
|
"popGesture" : "close", /*设置应用默认侧滑返回关闭Webview窗口,"none"为无侧滑返回功能,"hide"为侧滑隐藏Webview窗口。参考http://ask.dcloud.net.cn/article/102*/
|
||||||
|
"runmode" : "normal", /*应用的首次启动运行模式,可取liberate或normal,liberate模式在第一次启动时将解压应用资源(Android平台File API才可正常访问_www目录)*/
|
||||||
|
"signature" : "Sk9JTiBVUyBtYWlsdG86aHIyMDEzQGRjbG91ZC5pbw==", /*可选,保留给应用签名,暂不使用*/
|
||||||
|
"distribute" : {
|
||||||
|
"plugins" : {
|
||||||
|
"maps" : {}
|
||||||
|
},
|
||||||
|
"apple" : {
|
||||||
|
"appid" : "", /*iOS应用标识,苹果开发网站申请的appid,如io.dcloud.HelloH5*/
|
||||||
|
"mobileprovision" : "", /*iOS应用打包配置文件*/
|
||||||
|
"password" : "", /*iOS应用打包个人证书导入密码*/
|
||||||
|
"p12" : "", /*iOS应用打包个人证书,打包配置文件关联的个人证书*/
|
||||||
|
"devices" : "universal", /*iOS应用支持的设备类型,可取值iphone/ipad/universal*/
|
||||||
|
"frameworks" : [] /*调用Native.js调用原生Objective-c API需要引用的FrameWork,如需调用GameCenter,则添加"GameKit.framework"*/
|
||||||
|
},
|
||||||
|
"google" : {
|
||||||
|
"packagename" : "", /*Android应用包名,如io.dcloud.HelloH5*/
|
||||||
|
"keystore" : "", /*Android应用打包使用的密钥库文件*/
|
||||||
|
"password" : "", /*Android应用打包使用密钥库中证书的密码*/
|
||||||
|
"aliasname" : "", /*Android应用打包使用密钥库中证书的别名*/
|
||||||
|
"permissions" : [
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
|
||||||
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||||
|
"<uses-permission android:name=\"android.permission.CAMERA\"/>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
/*使用Native.js调用原生安卓API需要使用到的系统权限*/
|
||||||
|
"orientation" : [ "portrait-primary", "landscape-secondary" ], /*应用支持的方向,portrait-primary:竖屏正方向;portrait-secondary:竖屏反方向;landscape-primary:横屏正方向;landscape-secondary:横屏反方向*/
|
||||||
|
"icons" : {
|
||||||
|
"ios" : {
|
||||||
|
"prerendered" : true, /*应用图标是否已经高亮处理,在iOS6及以下设备上有效*/
|
||||||
|
|
||||||
|
/*应用图标,分辨率:512x512,用于自动生成各种尺寸程序图标*/
|
||||||
|
"iphone" : {
|
||||||
|
"normal" : "", /*iPhone3/3GS程序图标,分辨率:57x57*/
|
||||||
|
"retina" : "", /*iPhone4程序图标,分辨率:114x114*/
|
||||||
|
|
||||||
|
/*iPhone4S/5/6程序图标,分辨率:120x120*//*iPhone6 Plus程序图标,分辨率:180x180*/
|
||||||
|
"spotlight-normal" : "", /*iPhone3/3GS Spotlight搜索程序图标,分辨率:29x29*/
|
||||||
|
"spotlight-retina" : "", /*iPhone4 Spotlight搜索程序图标,分辨率:58x58*/
|
||||||
|
|
||||||
|
/*iPhone4S/5/6 Spotlight搜索程序图标,分辨率:80x80*/
|
||||||
|
"settings-normal" : "", /*iPhone4设置页面程序图标,分辨率:29x29*/
|
||||||
|
|
||||||
|
/*iPhone4S/5/6设置页面程序图标,分辨率:58x58*/
|
||||||
|
"app@2x" : "unpackage/res/icons/120x120.png",
|
||||||
|
"app@3x" : "unpackage/res/icons/180x180.png",
|
||||||
|
"settings@3x" : "unpackage/res/icons/87x87.png",
|
||||||
|
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||||
|
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||||
|
"spotlight@3x" : "unpackage/res/icons/120x120.png",
|
||||||
|
"notification@3x" : "unpackage/res/icons/60x60.png",
|
||||||
|
"notification@2x" : "unpackage/res/icons/40x40.png" /*iPhone6Plus设置页面程序图标,分辨率:87x87*/
|
||||||
|
},
|
||||||
|
"ipad" : {
|
||||||
|
"normal" : "", /*iPad普通屏幕程序图标,分辨率:72x72*/
|
||||||
|
"retina" : "", /*iPad高分屏程序图标,分辨率:144x144*/
|
||||||
|
|
||||||
|
/*iPad iOS7程序图标,分辨率:76x76*//*iPad iOS7高分屏程序图标,分辨率:152x152*/
|
||||||
|
"spotlight-normal" : "", /*iPad Spotlight搜索程序图标,分辨率:50x50*/
|
||||||
|
"spotlight-retina" : "", /*iPad高分屏Spotlight搜索程序图标,分辨率:100x100*/
|
||||||
|
|
||||||
|
/*iPad iOS7 Spotlight搜索程序图标,分辨率:40x40*//*iPad iOS7高分屏Spotlight搜索程序图标,分辨率:80x80*//*iPad设置页面程序图标,分辨率:29x29*/
|
||||||
|
"app" : "unpackage/res/icons/76x76.png",
|
||||||
|
"app@2x" : "unpackage/res/icons/152x152.png",
|
||||||
|
"settings" : "unpackage/res/icons/29x29.png",
|
||||||
|
"proapp@2x" : "unpackage/res/icons/167x167.png",
|
||||||
|
"spotlight" : "unpackage/res/icons/40x40.png",
|
||||||
|
"settings@2x" : "unpackage/res/icons/58x58.png",
|
||||||
|
"spotlight@2x" : "unpackage/res/icons/80x80.png",
|
||||||
|
"notification" : "unpackage/res/icons/20x20.png",
|
||||||
|
"notification@2x" : "unpackage/res/icons/40x40.png" /*iPad高分屏设置页面程序图标,分辨率:58x58*/
|
||||||
|
},
|
||||||
|
"appstore" : "unpackage/res/icons/1024x1024.png"
|
||||||
|
},
|
||||||
|
"android" : {
|
||||||
|
"mdpi" : "unpackage/res/icons/48x48.png", /*普通屏程序图标,分辨率:48x48*/
|
||||||
|
"ldpi" : "unpackage/res/icons/48x48.png", /*大屏程序图标,分辨率:48x48*/
|
||||||
|
"hdpi" : "unpackage/res/icons/72x72.png", /*高分屏程序图标,分辨率:72x72*/
|
||||||
|
"xhdpi" : "unpackage/res/icons/96x96.png", /*720P高分屏程序图标,分辨率:96x96*/
|
||||||
|
"xxhdpi" : "unpackage/res/icons/144x144.png",
|
||||||
|
"xxxhdpi" : "unpackage/res/icons/192x192.png" /*1080P 高分屏程序图标,分辨率:144x144*/
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"splashscreen" : {
|
||||||
|
"ios" : {
|
||||||
|
"iphone" : {
|
||||||
|
"default" : "", /*iPhone3启动图片选,分辨率:320x480*/
|
||||||
|
"retina35" : "", /*3.5英寸设备(iPhone4)启动图片,分辨率:640x960*/
|
||||||
|
"retina40" : "", /*4.0 英寸设备(iPhone5/iPhone5s)启动图片,分辨率:640x1136*/
|
||||||
|
"retina47" : "", /*4.7 英寸设备(iPhone6)启动图片,分辨率:750x1334*/
|
||||||
|
"retina55" : "", /*5.5 英寸设备(iPhone6 Plus)启动图片,分辨率:1242x2208*/
|
||||||
|
"retina55l" : "" /*5.5 英寸设备(iPhone6 Plus)横屏启动图片,分辨率:2208x1242*/
|
||||||
|
},
|
||||||
|
"ipad" : {
|
||||||
|
"portrait" : "", /*iPad竖屏启动图片,分辨率:768x1004*/
|
||||||
|
"portrait-retina" : "", /*iPad高分屏竖屏图片,分辨率:1536x2008*/
|
||||||
|
"landscape" : "", /*iPad横屏启动图片,分辨率:1024x748*/
|
||||||
|
"landscape-retina" : "", /*iPad高分屏横屏启动图片,分辨率:2048x1496*/
|
||||||
|
"portrait7" : "", /*iPad iOS7竖屏启动图片,分辨率:768x1024*/
|
||||||
|
"portrait-retina7" : "", /*iPad iOS7高分屏竖屏图片,分辨率:1536x2048*/
|
||||||
|
"landscape7" : "", /*iPad iOS7横屏启动图片,分辨率:1024x768*/
|
||||||
|
"landscape-retina7" : "" /*iPad iOS7高分屏横屏启动图片,分辨率:2048x1536*/
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"android" : {
|
||||||
|
"mdpi" : "", /*普通屏启动图片,分辨率:240x282*/
|
||||||
|
"ldpi" : "", /*大屏启动图片,分辨率:320x442*/
|
||||||
|
"hdpi" : "", /*高分屏启动图片,分辨率:480x762*/
|
||||||
|
"xhdpi" : "", /*720P高分屏启动图片,分辨率:720x1242*/
|
||||||
|
"xxhdpi" : "" /*1080P高分屏启动图片,分辨率:1080x1882*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies" : {
|
||||||
|
"idle" : {
|
||||||
|
"resources" : [
|
||||||
|
"src/assets/fonts/mui.ttf",
|
||||||
|
"test/unit/specs/HelloWorld.spec.js",
|
||||||
|
"src/page/goods/detail.js",
|
||||||
|
"dist/goods/detail.html",
|
||||||
|
"src/utils/webview.js",
|
||||||
|
"dist/assets/css/mui/index.56e5f56fc0bd813623b07c32aedb0e8c.css",
|
||||||
|
"src/assets/fonts/mui-icons-extra.ttf",
|
||||||
|
"src/assets/mui/mui.min.js",
|
||||||
|
"dist/map/map.js",
|
||||||
|
"dist/assets/img/logo.adf2bc3.png",
|
||||||
|
"build/mui-loader.js",
|
||||||
|
"package.json",
|
||||||
|
"src/page/mui/index.js",
|
||||||
|
"build/check-versions.js",
|
||||||
|
"config/dev.env.js",
|
||||||
|
"package-lock.json",
|
||||||
|
"README.md",
|
||||||
|
"test/unit/jest.conf.js",
|
||||||
|
"src/page.json",
|
||||||
|
"docs/README.md",
|
||||||
|
"build/webpack.dev.conf.js",
|
||||||
|
"src/page/map/map.vue",
|
||||||
|
"index.html",
|
||||||
|
"test/unit/setup.js",
|
||||||
|
"src/utils/envent.js",
|
||||||
|
"src/assets/mui/mui.css",
|
||||||
|
"src/assets/logo.png",
|
||||||
|
"build/multipage.js",
|
||||||
|
"config/test.env.js",
|
||||||
|
"dist/assets/css/map/map.2d75f521352cb21662b356ac39e8c9ce.css",
|
||||||
|
"src/main.js",
|
||||||
|
"src/page/map/map.js",
|
||||||
|
"src/components/content.vue",
|
||||||
|
"dist/map/map.html",
|
||||||
|
"dist/app.js",
|
||||||
|
"config/index.js",
|
||||||
|
"src/utils/request.js",
|
||||||
|
"src/utils/common.js",
|
||||||
|
"src/page/user/index.vue",
|
||||||
|
"src/components/HelloWorld.vue",
|
||||||
|
"dist/vux/index.js",
|
||||||
|
"dist/vux/index.html",
|
||||||
|
"dist/assets/css/user/index.67f3ac9443309c4cdb0fbfa855200001.css",
|
||||||
|
"build/utils.js",
|
||||||
|
"dist/mui/index.html",
|
||||||
|
"dist/assets/fonts/mui.8820b7f.ttf",
|
||||||
|
"build/logo.png",
|
||||||
|
"src/page/goods/detail.vue",
|
||||||
|
"build/vue-loader.conf.js",
|
||||||
|
"dist/mui/index.js",
|
||||||
|
"src/page/vux/index.vue",
|
||||||
|
"docs/deploy.sh",
|
||||||
|
"build/build.js",
|
||||||
|
"src/App.vue",
|
||||||
|
"config/prod.env.js",
|
||||||
|
"dist/user/index.js",
|
||||||
|
"build/webpack.base.conf.js",
|
||||||
|
"dist/assets/css/goods/detail.99776475e779987e734405cbb06f0dcd.css",
|
||||||
|
"src/page/user/index.js",
|
||||||
|
"dist/assets/css/app.e4cc5007c4501d913a3ad4364b16bf23.css",
|
||||||
|
"dist/goods/detail.js",
|
||||||
|
"src/components/logo.vue",
|
||||||
|
"src/page/vux/index.js",
|
||||||
|
"src/page/mui/index.vue",
|
||||||
|
"docs/guide.md",
|
||||||
|
"build/webpack.prod.conf.js",
|
||||||
|
"dist/assets/css/vux/index.e04574f3b1ee9b1e211545fbaea0a4b4.css"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pages" : {
|
||||||
|
"dist/index.html" : {
|
||||||
|
"resources" : [],
|
||||||
|
"refer" : [
|
||||||
|
"dist/user/index.html",
|
||||||
|
"dist/goods.detail.html",
|
||||||
|
"dist/mui.index.html",
|
||||||
|
"dist/vux.index.html",
|
||||||
|
"dist/goods.cart.html"
|
||||||
|
],
|
||||||
|
"priority" : 0
|
||||||
|
},
|
||||||
|
"dist/vux.index.html" : {
|
||||||
|
"resources" : [ "dist/assets/css/vux.index.css" ],
|
||||||
|
"refer" : [],
|
||||||
|
"priority" : 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"unpackage" : [
|
||||||
|
"src/page/user/index.js",
|
||||||
|
"src/page/user/index.vue",
|
||||||
|
"index.html",
|
||||||
|
"package-lock.json",
|
||||||
|
"package.json",
|
||||||
|
"build/build.js",
|
||||||
|
"build/check-versions.js",
|
||||||
|
"build/logo.png",
|
||||||
|
"build/mui-loader.js",
|
||||||
|
"build/multipage.js",
|
||||||
|
"build/utils.js",
|
||||||
|
"build/vue-loader.conf.js",
|
||||||
|
"build/webpack.base.conf.js",
|
||||||
|
"build/webpack.dev.conf.js",
|
||||||
|
"build/webpack.prod.conf.js",
|
||||||
|
"config/dev.env.js",
|
||||||
|
"config/index.js",
|
||||||
|
"config/prod.env.js",
|
||||||
|
"config/test.env.js",
|
||||||
|
"docs/README.md",
|
||||||
|
"docs/deploy.sh",
|
||||||
|
"docs/guide.md",
|
||||||
|
"src/assets/fonts/mui-icons-extra.ttf",
|
||||||
|
"src/assets/fonts/mui.ttf",
|
||||||
|
"src/assets/logo.png",
|
||||||
|
"src/assets/mui/mui.css",
|
||||||
|
"src/assets/mui/mui.min.js",
|
||||||
|
"src/components/HelloWorld.vue",
|
||||||
|
"src/components/content.vue",
|
||||||
|
"src/components/logo.vue",
|
||||||
|
"src/page/goods/detail.js",
|
||||||
|
"src/page/goods/detail.vue",
|
||||||
|
"src/page/map/map.js",
|
||||||
|
"src/page/map/map.vue",
|
||||||
|
"src/page/mui/index.js",
|
||||||
|
"src/page/mui/index.vue",
|
||||||
|
"src/page/vux/index.js",
|
||||||
|
"src/page/vux/index.vue",
|
||||||
|
"src/utils/common.js",
|
||||||
|
"src/utils/envent.js",
|
||||||
|
"src/utils/request.js",
|
||||||
|
"src/utils/webview.js",
|
||||||
|
"src/App.vue",
|
||||||
|
"src/main.js",
|
||||||
|
"src/page.json",
|
||||||
|
"test/unit/jest.conf.js",
|
||||||
|
"test/unit/setup.js",
|
||||||
|
"test/unit/specs/HelloWorld.spec.js",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"screenOrientation" : [ "portrait-primary", "landscape-secondary" ]
|
||||||
|
}
|
96
package.json
Executable file
@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"name": "mogo-h5plus",
|
||||||
|
"version": "1.3.0",
|
||||||
|
"description": "A Scaffolding To Develop H5+ App Fast.",
|
||||||
|
"author": "ArH <626019610@qq.com>",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nodemon -e json --exec \"webpack-dev-server --inline --progress --config build/webpack.dev.conf.js\"",
|
||||||
|
"start": "npm run dev",
|
||||||
|
"unit": "jest --config test/unit/jest.conf.js --coverage",
|
||||||
|
"test": "npm run unit",
|
||||||
|
"build": "node build/build.js",
|
||||||
|
"lint": "eslint --ext .js,.vue src test/unit",
|
||||||
|
"docs:dev": "cd docs && vuepress dev",
|
||||||
|
"docs:publish": "cd docs && ./deploy.sh"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.18.0",
|
||||||
|
"fastclick": "git+https://github.com/mogoclub/fastclick.git",
|
||||||
|
"h5plus-hotfix": "^1.0.1",
|
||||||
|
"vant": "^1.1.10",
|
||||||
|
"vconsole": "^3.2.0",
|
||||||
|
"vue": "^2.5.2",
|
||||||
|
"vux": "^2.9.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^7.1.2",
|
||||||
|
"babel-core": "^6.22.1",
|
||||||
|
"babel-eslint": "^8.2.1",
|
||||||
|
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||||
|
"babel-jest": "^21.0.2",
|
||||||
|
"babel-loader": "^7.1.1",
|
||||||
|
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||||
|
"babel-plugin-import": "^1.8.0",
|
||||||
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||||
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||||
|
"babel-plugin-transform-runtime": "^6.22.0",
|
||||||
|
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||||
|
"babel-preset-env": "^1.3.2",
|
||||||
|
"babel-preset-stage-2": "^6.22.0",
|
||||||
|
"chalk": "^2.0.1",
|
||||||
|
"copy-webpack-plugin": "^4.0.1",
|
||||||
|
"css-loader": "^0.28.0",
|
||||||
|
"eslint": "^4.15.0",
|
||||||
|
"eslint-config-standard": "^10.2.1",
|
||||||
|
"eslint-friendly-formatter": "^3.0.0",
|
||||||
|
"eslint-loader": "^1.7.1",
|
||||||
|
"eslint-plugin-import": "^2.7.0",
|
||||||
|
"eslint-plugin-node": "^5.2.0",
|
||||||
|
"eslint-plugin-promise": "^3.4.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
|
"eslint-plugin-vue": "^4.0.0",
|
||||||
|
"extract-text-webpack-plugin": "^3.0.0",
|
||||||
|
"file-loader": "^1.1.4",
|
||||||
|
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||||
|
"html-webpack-plugin": "^2.30.1",
|
||||||
|
"html-webpack-plugin-for-multihtml": "^2.30.2",
|
||||||
|
"jest": "^22.0.4",
|
||||||
|
"jest-serializer-vue": "^0.3.0",
|
||||||
|
"less": "^3.0.4",
|
||||||
|
"less-loader": "^4.1.0",
|
||||||
|
"node-notifier": "^5.1.2",
|
||||||
|
"nodemon": "^1.17.5",
|
||||||
|
"optimize-css-assets-webpack-plugin": "^3.2.0",
|
||||||
|
"ora": "^1.2.0",
|
||||||
|
"portfinder": "^1.0.13",
|
||||||
|
"postcss-import": "^11.0.0",
|
||||||
|
"postcss-loader": "^2.0.8",
|
||||||
|
"postcss-url": "^7.2.1",
|
||||||
|
"prettier": "^1.12.1",
|
||||||
|
"rimraf": "^2.6.0",
|
||||||
|
"semver": "^5.3.0",
|
||||||
|
"shelljs": "^0.7.6",
|
||||||
|
"uglifyjs-webpack-plugin": "^1.1.1",
|
||||||
|
"url-loader": "^0.5.8",
|
||||||
|
"vconsole-webpack-plugin": "^1.4.0",
|
||||||
|
"vue-jest": "^1.0.2",
|
||||||
|
"vue-loader": "^13.3.0",
|
||||||
|
"vue-style-loader": "^3.0.1",
|
||||||
|
"vue-template-compiler": "^2.5.2",
|
||||||
|
"vux-loader": "^1.2.9",
|
||||||
|
"webpack": "^3.6.0",
|
||||||
|
"webpack-bundle-analyzer": "^2.9.0",
|
||||||
|
"webpack-dev-server": "^2.9.1",
|
||||||
|
"webpack-merge": "^4.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0",
|
||||||
|
"npm": ">= 3.0.0"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"> 1%",
|
||||||
|
"last 2 versions",
|
||||||
|
"not ie <= 8"
|
||||||
|
]
|
||||||
|
}
|
280
src/App.vue
Executable file
@ -0,0 +1,280 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-pull-refresh class="content" v-model="isLoading" @refresh="onRefresh">
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<Logo></Logo>
|
||||||
|
<div style="padding:10px 15px;text-align:center">
|
||||||
|
<small>下拉Ajax请求试试😋</small>
|
||||||
|
</div>
|
||||||
|
<van-collapse v-model="activeName" accordion>
|
||||||
|
<van-collapse-item title="plus演示" name="1">
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell @click="openGoodsDetail()" title="预加载商品详情窗口" is-link />
|
||||||
|
<van-cell @click="openCart()" title="打开购物车窗口" is-link />
|
||||||
|
<van-cell @click="camera" title="拍照" is-link />
|
||||||
|
<van-cell @click="toast" title="原生Toast" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
</van-collapse-item>
|
||||||
|
<van-collapse-item title="Vant组件演示 " name="2">
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell @click="openAS" title="Actionsheet" is-link />
|
||||||
|
<van-cell @click="vantToast" title="Toast" is-link />
|
||||||
|
<van-cell @click="vantDialog" title="Dialog" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
</van-collapse-item>
|
||||||
|
<van-collapse-item title="Mui组件演示" name="3">
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell @click="openMui" title="Mui演示页" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
</van-collapse-item>
|
||||||
|
<van-collapse-item title="vux组件演示" name="4">
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell @click="openVux" title="vux演示页" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
</van-collapse-item>
|
||||||
|
|
||||||
|
</van-collapse>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</van-pull-refresh>
|
||||||
|
<van-actionsheet v-model="show" cancel-text="取消" :actions="actions" />
|
||||||
|
<van-tabbar v-model="active">
|
||||||
|
<van-tabbar-item icon="shop">标签</van-tabbar-item>
|
||||||
|
<van-tabbar-item icon="chat" dot>标签</van-tabbar-item>
|
||||||
|
<van-tabbar-item icon="records" info="5">标签</van-tabbar-item>
|
||||||
|
<van-tabbar-item icon="gold-coin" info="20">标签</van-tabbar-item>
|
||||||
|
</van-tabbar>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Vue from "vue";
|
||||||
|
import {
|
||||||
|
openWebview,
|
||||||
|
openWebviewFast,
|
||||||
|
preLoad,
|
||||||
|
showWebviewById
|
||||||
|
} from "@/utils/webview";
|
||||||
|
import { request } from "@/utils/request";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
CellGroup,
|
||||||
|
Toast,
|
||||||
|
PullRefresh,
|
||||||
|
Tabbar,
|
||||||
|
TabbarItem,
|
||||||
|
Cell,
|
||||||
|
List,
|
||||||
|
Actionsheet,
|
||||||
|
NavBar,
|
||||||
|
Tag,
|
||||||
|
Collapse,
|
||||||
|
CollapseItem
|
||||||
|
} from "vant";
|
||||||
|
import Logo from "./components/logo.vue";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Logo,
|
||||||
|
[Dialog.name]: Dialog,
|
||||||
|
[CellGroup.name]: CellGroup,
|
||||||
|
[Toast.name]: Toast,
|
||||||
|
[PullRefresh.name]: PullRefresh,
|
||||||
|
[Tabbar.name]: Tabbar,
|
||||||
|
[TabbarItem.name]: TabbarItem,
|
||||||
|
[Cell.name]: Cell,
|
||||||
|
[List.name]: List,
|
||||||
|
[Actionsheet.name]: Actionsheet,
|
||||||
|
[NavBar.name]: NavBar,
|
||||||
|
[Tag.name]: Tag,
|
||||||
|
[Collapse.name]: Collapse,
|
||||||
|
[CollapseItem.name]: CollapseItem
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
window.addEventListener("customEvent", function(event) {
|
||||||
|
//通过event.detail可获得传递过来的参数内容
|
||||||
|
plus.nativeUI.toast("我是首页,我很慌,我收到了信息");
|
||||||
|
console.log(event.detail);
|
||||||
|
});
|
||||||
|
function plusReady() {
|
||||||
|
let ws = plus.webview.currentWebview();
|
||||||
|
console.log(ws);
|
||||||
|
}
|
||||||
|
if (window.plus) {
|
||||||
|
plusReady();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("plusready", plusReady, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预加载一些窗口
|
||||||
|
preLoad([
|
||||||
|
{
|
||||||
|
url: "./vux.index.html",
|
||||||
|
id: "vux.index",
|
||||||
|
title: "vux演示页"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "./goods.detail.html",
|
||||||
|
id: "goods.detail",
|
||||||
|
title: "美国伽力果",
|
||||||
|
extras: {
|
||||||
|
id: 2018,
|
||||||
|
name: "超级红苹果"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "./goods.cart.html",
|
||||||
|
id: "goods.cart",
|
||||||
|
title: "购物车",
|
||||||
|
style: {
|
||||||
|
titleNView: {
|
||||||
|
backgroundColor: "#f7f7f7", // 导航栏背景色
|
||||||
|
titleText: "购物车", // 导航栏标题
|
||||||
|
titleColor: "#666", // 文字颜色
|
||||||
|
// type: "transparent", // 透明渐变样式
|
||||||
|
autoBackButton: true, // 自动绘制返回箭头
|
||||||
|
splitLine: {
|
||||||
|
// 底部分割线
|
||||||
|
color: "#cccccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
popGesture: "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
activeName: "1",
|
||||||
|
count: 0,
|
||||||
|
isLoading: false,
|
||||||
|
active: 0,
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
show: false,
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
name: "选项",
|
||||||
|
callback: this.onClick
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "选项",
|
||||||
|
subname: "描述信息"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "选项",
|
||||||
|
loading: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// 使用预加载速度会很快,但是没法再次传值,只能通过页面之间的通讯完成传值,参考goods.detail页面中的fire
|
||||||
|
openGoodsDetail() {
|
||||||
|
showWebviewById("goods.detail");
|
||||||
|
},
|
||||||
|
openVux() {
|
||||||
|
showWebviewById("vux.index");
|
||||||
|
},
|
||||||
|
openCart() {
|
||||||
|
showWebviewById("goods.cart");
|
||||||
|
},
|
||||||
|
openMui() {
|
||||||
|
// 重写了标题样式
|
||||||
|
openWebview(
|
||||||
|
{
|
||||||
|
url: "./mui.index.html",
|
||||||
|
id: "mui.index"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
titleNView: {
|
||||||
|
backgroundColor: "#f7f7f7", // 导航栏背景色
|
||||||
|
titleText: "MUI演示", // 导航栏标题
|
||||||
|
titleColor: "#666", // 文字颜色
|
||||||
|
// type: "transparent", // 透明渐变样式
|
||||||
|
autoBackButton: true, // 自动绘制返回箭头
|
||||||
|
splitLine: {
|
||||||
|
// 底部分割线
|
||||||
|
color: "#cccccc"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2018,
|
||||||
|
name: "超级红苹果"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// openWebview("./mui.index.html", "mui.index", "Mui演示");
|
||||||
|
},
|
||||||
|
camera() {
|
||||||
|
var cmr = plus.camera.getCamera();
|
||||||
|
cmr.captureImage(
|
||||||
|
function(p) {
|
||||||
|
plus.nativeUI.alert("成功:" + p);
|
||||||
|
plus.io.resolveLocalFileSystemURL(
|
||||||
|
p,
|
||||||
|
function(entry) {
|
||||||
|
// createItem(entry);
|
||||||
|
},
|
||||||
|
function(e) {
|
||||||
|
console.log("读取拍照文件错误:" + e.message);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
function(e) {
|
||||||
|
console.log("失败:" + e.message);
|
||||||
|
},
|
||||||
|
{ filename: "_doc/camera/", index: 1 }
|
||||||
|
);
|
||||||
|
},
|
||||||
|
vantDialog() {
|
||||||
|
Dialog.alert({
|
||||||
|
title: "标题",
|
||||||
|
message: "弹窗内容"
|
||||||
|
}).then(() => {
|
||||||
|
// on close
|
||||||
|
});
|
||||||
|
},
|
||||||
|
vantToast() {
|
||||||
|
Toast("我是提示文案,建议不超过十五字~");
|
||||||
|
},
|
||||||
|
toast() {
|
||||||
|
plus.nativeUI.toast("Hier");
|
||||||
|
},
|
||||||
|
|
||||||
|
onRefresh() {
|
||||||
|
this.isLoading = true;
|
||||||
|
request({
|
||||||
|
url: DOUBANAPI + "/v2/book/search?q=javascript&count=2"
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
this.isLoading = false;
|
||||||
|
plus.nativeUI.toast("Ajax请求成功");
|
||||||
|
console.log(res);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.isLoading = false;
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
openAS() {
|
||||||
|
this.show = !this.show;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
:global {
|
||||||
|
body {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
font-family: PingFang SC, Helvetica Neue, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
BIN
src/assets/logo.png
Executable file
After Width: | Height: | Size: 23 KiB |
5615
src/assets/mui/mui.css
Executable file
9
src/assets/mui/mui.min.js
vendored
Executable file
BIN
src/assets/mui/mui.ttf
Executable file
113
src/components/HelloWorld.vue
Executable file
@ -0,0 +1,113 @@
|
|||||||
|
<template>
|
||||||
|
<div class="hello">
|
||||||
|
<h1>{{ msg }}</h1>
|
||||||
|
<h2>Essential Links</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://vuejs.org"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Core Docs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://forum.vuejs.org"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Forum
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://chat.vuejs.org"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Community Chat
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://twitter.com/vuejs"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Twitter
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<br>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="http://vuejs-templates.github.io/webpack/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Docs for This Template
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Ecosystem</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="http://router.vuejs.org/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
vue-router
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="http://vuex.vuejs.org/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
vuex
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="http://vue-loader.vuejs.org/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
vue-loader
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="https://github.com/vuejs/awesome-vue"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
awesome-vue
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'HelloWorld',
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
msg: 'Welcome to Your Vue.js App'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
h1, h2 {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
22
src/components/content.vue
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div class="content">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from "vue";
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
created() {}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.content {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
</style>
|
31
src/components/logo.vue
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div style="text-align:center">
|
||||||
|
<img width="60%" src="@/assets/logo.png" alt="">
|
||||||
|
</div>
|
||||||
|
<van-tag mark type="success">{{info.version}}</van-tag>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Vue from "vue";
|
||||||
|
import { Tag } from "vant";
|
||||||
|
|
||||||
|
import { getProperty } from "../utils/plus/runtime.js";
|
||||||
|
Vue.use(Tag);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
info: "0"
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
getProperty().then(info => {
|
||||||
|
// console
|
||||||
|
this.info = info;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
51
src/main.js
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
// The Vue build version to load with the `import` command
|
||||||
|
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||||
|
import Vue from "vue";
|
||||||
|
// import hotfix from 'h5plus-hotfix';
|
||||||
|
import "./utils/common";
|
||||||
|
import App from "./App";
|
||||||
|
const appId = "com.femirror.mogoh5";
|
||||||
|
// const updateUrl = FemirrorAPI + `/public/app/checkUpdate?bundleId=${appId}`;
|
||||||
|
// hotfix({
|
||||||
|
// url: updateUrl,
|
||||||
|
// before(data) {
|
||||||
|
// // 确认安装
|
||||||
|
// return new Promise(resolve => {
|
||||||
|
// plus.nativeUI.confirm(data.description, (selected) => {
|
||||||
|
// if (selected.index === 0) {
|
||||||
|
// plus.nativeUI.showWaiting("下载更新文件...");
|
||||||
|
// resolve(data);
|
||||||
|
// }
|
||||||
|
// }, {
|
||||||
|
// title: data.title,
|
||||||
|
// buttons: ["确认更新", "取消"],
|
||||||
|
// verticalAlign: "bottom"
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// success() {
|
||||||
|
// console.log('安装成功')
|
||||||
|
// plus.runtime.restart(); // 重启app
|
||||||
|
// plus.nativeUI.closeWaiting();
|
||||||
|
// },
|
||||||
|
// error(e) {
|
||||||
|
// // 错误显示
|
||||||
|
// plus.nativeUI.closeWaiting();
|
||||||
|
// console.log("安装wgt文件失败[" + e.code + "]:" + e.message);
|
||||||
|
// plus.nativeUI.alert("安装wgt文件失败[" + e.code + "]:" + e.message);
|
||||||
|
// },
|
||||||
|
// onProgress(p) {
|
||||||
|
// console.log(p) // 下载进度
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
components: { App },
|
||||||
|
template: "<App/>"
|
||||||
|
});
|
8
src/page.json
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"index|plusReady": "./src/main.js",
|
||||||
|
"goods.detail": "./src/page/goods/detail.js",
|
||||||
|
"goods.cart|plusReady": "./src/page/goods/cart.js",
|
||||||
|
"mui.index|mui|plusReady": "./src/page/mui/index.js",
|
||||||
|
"user.index": "./src/page/user/index.js",
|
||||||
|
"vux.index|plusReady": "./src/page/vux/index.js"
|
||||||
|
}
|
8
src/page/goods/cart.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import "@/utils/common";
|
||||||
|
import App from "./cart.vue";
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
155
src/page/goods/cart.vue
Executable file
@ -0,0 +1,155 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-checkbox-group class="card-goods" v-model="checkedGoods">
|
||||||
|
<van-checkbox
|
||||||
|
class="card-goods__item"
|
||||||
|
v-for="item in goods"
|
||||||
|
:key="item.id"
|
||||||
|
:name="item.id"
|
||||||
|
>
|
||||||
|
<van-card
|
||||||
|
:title="item.title"
|
||||||
|
:desc="item.desc"
|
||||||
|
:num="item.num"
|
||||||
|
:price="formatPrice(item.price)"
|
||||||
|
:thumb="item.thumb"
|
||||||
|
/>
|
||||||
|
</van-checkbox>
|
||||||
|
</van-checkbox-group>
|
||||||
|
<van-submit-bar
|
||||||
|
:price="totalPrice"
|
||||||
|
:disabled="!checkedGoods.length"
|
||||||
|
:button-text="submitBarText"
|
||||||
|
@submit="onSubmit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Checkbox, CheckboxGroup, Card, SubmitBar, Toast } from "vant";
|
||||||
|
import { confirm } from "../../utils/plus/nativeUI";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
[Card.name]: Card,
|
||||||
|
[Checkbox.name]: Checkbox,
|
||||||
|
[SubmitBar.name]: SubmitBar,
|
||||||
|
[CheckboxGroup.name]: CheckboxGroup
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
plus.key.removeEventListener("backbutton", function() {
|
||||||
|
console.log(5555);
|
||||||
|
});
|
||||||
|
plus.key.addEventListener(
|
||||||
|
"backbutton",
|
||||||
|
function() {
|
||||||
|
// nativeUI.conf
|
||||||
|
// nativeUI.con
|
||||||
|
confirm("确认要离开么?").then(e => {
|
||||||
|
if (e.index === 0) {
|
||||||
|
plus.nativeUI.toast("离开了");
|
||||||
|
const ws = plus.webview.currentWebview();
|
||||||
|
ws.hide("auto");
|
||||||
|
} else {
|
||||||
|
plus.nativeUI.toast("留住了");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
window.addEventListener("addGoodsToCart", event => {
|
||||||
|
//通过event.detail可获得传递过来的参数内容
|
||||||
|
|
||||||
|
let goods = this.goods.find(ele => {
|
||||||
|
return ele.id == event.detail.goods_id;
|
||||||
|
});
|
||||||
|
goods.num++;
|
||||||
|
plus.nativeUI.toast(`我是购物车页面,当前苹果数量为${goods.num}`);
|
||||||
|
console.log(event.detail);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
checkedGoods: ["1", "2", "3"],
|
||||||
|
goods: [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
title: "进口香蕉",
|
||||||
|
desc: "约250g,2根",
|
||||||
|
price: 200,
|
||||||
|
num: 1,
|
||||||
|
thumb:
|
||||||
|
"https://img.yzcdn.cn/public_files/2017/10/24/2f9a36046449dafb8608e99990b3c205.jpeg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
title: "陕西蜜梨",
|
||||||
|
desc: "约600g",
|
||||||
|
price: 690,
|
||||||
|
num: 1,
|
||||||
|
thumb:
|
||||||
|
"https://img.yzcdn.cn/public_files/2017/10/24/f6aabd6ac5521195e01e8e89ee9fc63f.jpeg"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
title: "美国伽力果",
|
||||||
|
desc: "约680g/3个",
|
||||||
|
price: 2680,
|
||||||
|
num: 1,
|
||||||
|
thumb:
|
||||||
|
"https://img.yzcdn.cn/public_files/2017/10/24/320454216bbe9e25c7651e1fa51b31fd.jpeg"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
submitBarText() {
|
||||||
|
const count = this.checkedGoods.length;
|
||||||
|
return "结算" + (count ? `(${count})` : "");
|
||||||
|
},
|
||||||
|
totalPrice() {
|
||||||
|
return this.goods.reduce(
|
||||||
|
(total, item) =>
|
||||||
|
total + (this.checkedGoods.indexOf(item.id) !== -1 ? item.price : 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
formatPrice(price) {
|
||||||
|
return (price / 100).toFixed(2);
|
||||||
|
},
|
||||||
|
onSubmit() {
|
||||||
|
Toast("点击结算");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
body {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
.card-goods {
|
||||||
|
padding: 10px 0;
|
||||||
|
background-color: #fff;
|
||||||
|
&__item {
|
||||||
|
position: relative;
|
||||||
|
background-color: #fafafa;
|
||||||
|
.van-checkbox__label {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 10px 0 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.van-checkbox__icon {
|
||||||
|
top: 50%;
|
||||||
|
left: 10px;
|
||||||
|
z-index: 1;
|
||||||
|
position: absolute;
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
.van-card__price {
|
||||||
|
color: #f44;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
8
src/page/goods/detail.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import "@/utils/common";
|
||||||
|
import App from "./detail.vue";
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
159
src/page/goods/detail.vue
Executable file
@ -0,0 +1,159 @@
|
|||||||
|
<template>
|
||||||
|
<div class="goods">
|
||||||
|
<van-swipe class="goods-swipe" :autoplay="3000">
|
||||||
|
<van-swipe-item v-for="thumb in goods.thumb" :key="thumb">
|
||||||
|
<img :src="thumb">
|
||||||
|
</van-swipe-item>
|
||||||
|
</van-swipe>
|
||||||
|
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell>
|
||||||
|
<div class="goods-title">{{ goods.title }}</div>
|
||||||
|
<div class="goods-price">{{ formatPrice(goods.price) }}</div>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell class="goods-express">
|
||||||
|
<van-col span="10">运费:{{ goods.express }}</van-col>
|
||||||
|
<van-col span="14">剩余:{{ goods.remain }}</van-col>
|
||||||
|
</van-cell>
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group class="goods-cell-group">
|
||||||
|
<van-cell value="进入店铺" icon="shop" is-link @click="sorry">
|
||||||
|
<template slot="title">
|
||||||
|
<span class="van-cell-text">有赞的店</span>
|
||||||
|
<van-tag type="danger">官方</van-tag>
|
||||||
|
</template>
|
||||||
|
</van-cell>
|
||||||
|
<van-cell title="线下门店" icon="location" is-link @click="sorry" />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group class="goods-cell-group">
|
||||||
|
<van-cell title="查看商品详情" is-link @click="sorry" />
|
||||||
|
</van-cell-group>
|
||||||
|
<br><br><br><br><br>
|
||||||
|
|
||||||
|
<van-goods-action>
|
||||||
|
<van-goods-action-mini-btn icon="chat" @click="sorry">
|
||||||
|
客服
|
||||||
|
</van-goods-action-mini-btn>
|
||||||
|
<van-goods-action-mini-btn icon="cart" @click="onClickCart">
|
||||||
|
购物车
|
||||||
|
</van-goods-action-mini-btn>
|
||||||
|
<van-goods-action-big-btn @click="sendEvent">
|
||||||
|
触发首页事件
|
||||||
|
</van-goods-action-big-btn>
|
||||||
|
<van-goods-action-big-btn primary @click="sorry">
|
||||||
|
立即购买
|
||||||
|
</van-goods-action-big-btn>
|
||||||
|
</van-goods-action>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Tag,
|
||||||
|
Col,
|
||||||
|
Icon,
|
||||||
|
Cell,
|
||||||
|
CellGroup,
|
||||||
|
Swipe,
|
||||||
|
Toast,
|
||||||
|
SwipeItem,
|
||||||
|
GoodsAction,
|
||||||
|
GoodsActionBigBtn,
|
||||||
|
GoodsActionMiniBtn
|
||||||
|
} from "vant";
|
||||||
|
|
||||||
|
import { fire } from "../../utils/envent.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
[Tag.name]: Tag,
|
||||||
|
[Col.name]: Col,
|
||||||
|
[Icon.name]: Icon,
|
||||||
|
[Cell.name]: Cell,
|
||||||
|
[CellGroup.name]: CellGroup,
|
||||||
|
[Swipe.name]: Swipe,
|
||||||
|
[SwipeItem.name]: SwipeItem,
|
||||||
|
[GoodsAction.name]: GoodsAction,
|
||||||
|
[GoodsActionBigBtn.name]: GoodsActionBigBtn,
|
||||||
|
[GoodsActionMiniBtn.name]: GoodsActionMiniBtn
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
goods: {
|
||||||
|
title: "美国伽力果(约680g/3个)",
|
||||||
|
price: 2680,
|
||||||
|
express: "免运费",
|
||||||
|
remain: 19,
|
||||||
|
thumb: [
|
||||||
|
"https://img.yzcdn.cn/public_files/2017/10/24/e5a5a02309a41f9f5def56684808d9ae.jpeg",
|
||||||
|
"https://img.yzcdn.cn/public_files/2017/10/24/1791ba14088f9c2be8c610d0a6cc0f93.jpeg"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
function plusReady() {
|
||||||
|
let ws = plus.webview.currentWebview();
|
||||||
|
// 预载网络页面
|
||||||
|
plus.nativeUI.toast(
|
||||||
|
`我收到的信息是:{"id":"${ws.id}","name":"${ws.name}"}`
|
||||||
|
);
|
||||||
|
console.log(ws);
|
||||||
|
}
|
||||||
|
if (window.plus) {
|
||||||
|
plusReady();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("plusready", plusReady, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
sendEvent() {
|
||||||
|
const indexWebview = plus.webview.getLaunchWebview();
|
||||||
|
fire(indexWebview, "customEvent", { name: "ArH", project: "MogoH5+" });
|
||||||
|
},
|
||||||
|
formatPrice() {
|
||||||
|
return "¥" + (this.goods.price / 100).toFixed(2);
|
||||||
|
},
|
||||||
|
onClickCart() {
|
||||||
|
// this.$router.push("cart");
|
||||||
|
const cartWebview = plus.webview.getWebviewById("goods.cart");
|
||||||
|
fire(cartWebview, "addGoodsToCart", { goods_id: 3, num: 1 });
|
||||||
|
},
|
||||||
|
sorry() {
|
||||||
|
Toast("暂无后续逻辑~");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.goods {
|
||||||
|
padding-bottom: 50px;
|
||||||
|
&-swipe {
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
// height: 7.5rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
&-price {
|
||||||
|
color: #f44;
|
||||||
|
}
|
||||||
|
&-express {
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
}
|
||||||
|
&-cell-group {
|
||||||
|
margin: 15px 0;
|
||||||
|
.van-cell__value {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
8
src/page/mui/index.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import "@/utils/common";
|
||||||
|
import App from "./index.vue";
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
61
src/page/mui/index.vue
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<br><br>
|
||||||
|
<center>
|
||||||
|
<img width="60%" :src="img" alt="">
|
||||||
|
</center>
|
||||||
|
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<h4 style="text-align:center">Mui V2.0 </h4>
|
||||||
|
<p style="text-align:center;padding:10px 20px">这里主要演示MUI的一些样式和JS,我仍然推荐您使用其他vueUI(Vux,Vant,mint)来代替mui</p>
|
||||||
|
<br>
|
||||||
|
<button @click="alert" type="button" class="mui-btn">alert</button>
|
||||||
|
<button @click="toast" type="button" class="mui-btn mui-btn-primary">toast</button>
|
||||||
|
<br><br>
|
||||||
|
<form class="mui-input-group">
|
||||||
|
<div class="mui-input-row">
|
||||||
|
<label>用户名</label>
|
||||||
|
<input type="text" class="mui-input-clear" placeholder="请输入用户名">
|
||||||
|
</div>
|
||||||
|
<div class="mui-input-row">
|
||||||
|
<label>密码</label>
|
||||||
|
<input type="password" class="mui-input-password" placeholder="请输入密码">
|
||||||
|
</div>
|
||||||
|
<div class="mui-button-row">
|
||||||
|
<button type="button" class="mui-btn mui-btn-primary">确认</button>
|
||||||
|
<button type="button" class="mui-btn mui-btn-danger">取消</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<br><br>
|
||||||
|
<ul class="mui-table-view">
|
||||||
|
<li class="mui-table-view-cell mui-collapse">
|
||||||
|
<a class="mui-navigate-right" href="#">面板1</a>
|
||||||
|
<div class="mui-collapse-content">
|
||||||
|
<p>面板1子内容</p>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
img: require("@/assets/logo.png")
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
alert() {
|
||||||
|
mui.alert("Mogo H5+");
|
||||||
|
},
|
||||||
|
toast() {
|
||||||
|
mui.toast("嘿嘿,有问题issue哦");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
</style>
|
8
src/page/user/index.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import "@/utils/common";
|
||||||
|
import App from "./index.vue";
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#root",
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
65
src/page/user/index.vue
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<img class="user-poster" src="https://img.yzcdn.cn/public_files/2017/10/23/8690bb321356070e0b8c4404d087f8fd.png">
|
||||||
|
<van-row class="user-links">
|
||||||
|
<van-col span="6">
|
||||||
|
<van-icon name="pending-payment" /> 待付款
|
||||||
|
</van-col>
|
||||||
|
<van-col span="6">
|
||||||
|
<van-icon name="pending-orders" /> 待接单
|
||||||
|
</van-col>
|
||||||
|
<van-col span="6">
|
||||||
|
<van-icon name="pending-deliver" /> 待发货
|
||||||
|
</van-col>
|
||||||
|
<van-col span="6">
|
||||||
|
<van-icon name="logistics" /> 待发货
|
||||||
|
</van-col>
|
||||||
|
</van-row>
|
||||||
|
|
||||||
|
<van-cell-group class="user-group">
|
||||||
|
<van-cell icon="records" title="全部订单" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell icon="exchange" title="我的积分" is-link />
|
||||||
|
<van-cell icon="gold-coin" title="我的优惠券" is-link />
|
||||||
|
<van-cell icon="gift" title="我收到的礼物" is-link />
|
||||||
|
</van-cell-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Row, Col, Icon, Cell, CellGroup } from 'vant';
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
[Row.name]: Row,
|
||||||
|
[Col.name]: Col,
|
||||||
|
[Icon.name]: Icon,
|
||||||
|
[Cell.name]: Cell,
|
||||||
|
[CellGroup.name]: CellGroup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.user {
|
||||||
|
&-poster {
|
||||||
|
width: 100%;
|
||||||
|
// height: 4rem;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
&-group {
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
}
|
||||||
|
&-links {
|
||||||
|
padding: 15px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #fff;
|
||||||
|
.van-icon {
|
||||||
|
display: block;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
8
src/page/vux/index.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
import Vue from "vue";
|
||||||
|
import "@/utils/common";
|
||||||
|
import App from "./index.vue";
|
||||||
|
|
||||||
|
new Vue({
|
||||||
|
el: "#app",
|
||||||
|
render: h => h(App)
|
||||||
|
});
|
173
src/page/vux/index.vue
Executable file
@ -0,0 +1,173 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<group-title>THX to: https://github.com/wechatui/swiper</group-title>
|
||||||
|
<group-title>list模式下,默认高度为180px, 如果设置aspect-ratio会根据宽度自动计算高度</group-title>
|
||||||
|
<swiper :list="demo01_list" v-model="demo01_index" @on-index-change="demo01_onIndexChange"></swiper>
|
||||||
|
<p class="copyright">Image Source: http://www.gratisography.com/</p>
|
||||||
|
<p>current index: {{demo01_index}}</p>
|
||||||
|
<x-button @click.native="demo01_index = 0">go to 0</x-button>
|
||||||
|
<x-button @click.native="demo01_index = 1">go to 1</x-button>
|
||||||
|
<x-button @click.native="demo01_index = 2">go to 2</x-button>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { Swiper, GroupTitle, SwiperItem, XButton, Divider } from "vux";
|
||||||
|
|
||||||
|
const baseList = [
|
||||||
|
{
|
||||||
|
url: "javascript:",
|
||||||
|
img: "https://ww1.sinaimg.cn/large/663d3650gy1fq66vvsr72j20p00gogo2.jpg",
|
||||||
|
title: "送你一朵fua"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "javascript:",
|
||||||
|
img: "https://ww1.sinaimg.cn/large/663d3650gy1fq66vw1k2wj20p00goq7n.jpg",
|
||||||
|
title: "送你一辆车"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: "javascript:",
|
||||||
|
img: "https://static.vux.li/demo/5.jpg", // 404
|
||||||
|
title: "送你一次旅行",
|
||||||
|
fallbackImg:
|
||||||
|
"https://ww1.sinaimg.cn/large/663d3650gy1fq66vw50iwj20ff0aaaci.jpg"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const imgList = [
|
||||||
|
"http://placeholder.qiniudn.com/800x300/FF3B3B/ffffff",
|
||||||
|
"http://placeholder.qiniudn.com/800x300/FFEF7D/ffffff",
|
||||||
|
"http://placeholder.qiniudn.com/800x300/8AEEB1/ffffff"
|
||||||
|
];
|
||||||
|
|
||||||
|
const urlList = baseList.map((item, index) => ({
|
||||||
|
url: "http://m.baidu.com",
|
||||||
|
img: item.img,
|
||||||
|
fallbackImg: item.fallbackImg,
|
||||||
|
title: `(可点击)${item.title}`
|
||||||
|
}));
|
||||||
|
|
||||||
|
const demoList = imgList.map((one, index) => ({
|
||||||
|
url: "javascript:",
|
||||||
|
img: one
|
||||||
|
}));
|
||||||
|
|
||||||
|
const only2ClickList = baseList.slice(0, 2).map(item => {
|
||||||
|
item.url = "http://m.baidu.com";
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
function b() {
|
||||||
|
return {
|
||||||
|
a: 1,
|
||||||
|
c: 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解构
|
||||||
|
let s = { ...b() };
|
||||||
|
console.log("解构测试");
|
||||||
|
console.log(s);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Swiper,
|
||||||
|
SwiperItem,
|
||||||
|
GroupTitle,
|
||||||
|
XButton,
|
||||||
|
Divider
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
console.log(plus.webview.currentWebview());
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSwiperItemIndexChange(index) {
|
||||||
|
console.log("demo item change", index);
|
||||||
|
},
|
||||||
|
demo01_onIndexChange(index) {
|
||||||
|
this.demo01_index = index;
|
||||||
|
},
|
||||||
|
demo05_onIndexChange(index) {
|
||||||
|
this.demo05_index = index;
|
||||||
|
},
|
||||||
|
demo05_onLoad(id) {
|
||||||
|
this.demo05_list = id === 1 ? baseList : demoList;
|
||||||
|
},
|
||||||
|
demo06_onIndexChange(index) {
|
||||||
|
this.demo06_index = index;
|
||||||
|
},
|
||||||
|
demo07_onIndexChange(index) {
|
||||||
|
this.demo07_index = index;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
demo01_list: baseList,
|
||||||
|
demo01_index: 1,
|
||||||
|
swiperItemIndex: 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.copyright {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #ccc;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.text-scroll {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
.text-scroll p {
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
.black {
|
||||||
|
background-color: #000;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
line-height: 100px;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.animated {
|
||||||
|
animation-duration: 1s;
|
||||||
|
animation-fill-mode: both;
|
||||||
|
}
|
||||||
|
.vux-indicator.custom-bottom {
|
||||||
|
bottom: 30px;
|
||||||
|
}
|
||||||
|
@-webkit-keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(0, 100%, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate3d(0, 100%, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fadeInUp {
|
||||||
|
animation-name: fadeInUp;
|
||||||
|
}
|
||||||
|
.swiper-demo-img img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
5
src/utils/README.md
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
# 建议
|
||||||
|
|
||||||
|
我们建议您将自己的常用函数库放在其他的文件夹.
|
||||||
|
|
||||||
|
因为我们会时而更新此文件夹中的函数
|
95
src/utils/common.js
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
/**
|
||||||
|
* 该js为所有页面都必须加载的js
|
||||||
|
* 可以用于全局添加某功能
|
||||||
|
*/
|
||||||
|
import FastClick from "fastclick";
|
||||||
|
// 去除300ms延迟
|
||||||
|
document.addEventListener(
|
||||||
|
"DOMContentLoaded",
|
||||||
|
function() {
|
||||||
|
FastClick.attach(document.body);
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
// 自动关闭窗口 可根据具体逻辑自定义
|
||||||
|
function plusReady() {
|
||||||
|
plus.key.addEventListener(
|
||||||
|
"backbutton",
|
||||||
|
function () {
|
||||||
|
var ws = plus.webview.currentWebview();
|
||||||
|
if (ws.webviewPreload == true) {
|
||||||
|
plus.webview.hide(ws, 'auto');
|
||||||
|
} else {
|
||||||
|
plus.webview.close(ws, 'auto');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (window.plus) {
|
||||||
|
plusReady();
|
||||||
|
} else {
|
||||||
|
document.addEventListener("plusready", plusReady, false);
|
||||||
|
}
|
||||||
|
// 页面调试工具
|
||||||
|
var print = function (json, options) {
|
||||||
|
var reg = null,
|
||||||
|
formatted = "",
|
||||||
|
pad = 0,
|
||||||
|
PADDING = " ";
|
||||||
|
options = options || {};
|
||||||
|
options.newlineAfterColonIfBeforeBraceOrBracket =
|
||||||
|
options.newlineAfterColonIfBeforeBraceOrBracket === true ? true : false;
|
||||||
|
options.spaceAfterColon = options.spaceAfterColon === false ? false : true;
|
||||||
|
if (typeof json !== "string") {
|
||||||
|
json = JSON.stringify(json);
|
||||||
|
} else {
|
||||||
|
json = JSON.parse(json);
|
||||||
|
json = JSON.stringify(json);
|
||||||
|
}
|
||||||
|
reg = /([\{\}])/g;
|
||||||
|
json = json.replace(reg, "\r\n$1\r\n");
|
||||||
|
reg = /([\[\]])/g;
|
||||||
|
json = json.replace(reg, "\r\n$1\r\n");
|
||||||
|
reg = /(\,)/g;
|
||||||
|
json = json.replace(reg, "$1\r\n");
|
||||||
|
reg = /(\r\n\r\n)/g;
|
||||||
|
json = json.replace(reg, "\r\n");
|
||||||
|
reg = /\r\n\,/g;
|
||||||
|
json = json.replace(reg, ",");
|
||||||
|
if (!options.newlineAfterColonIfBeforeBraceOrBracket) {
|
||||||
|
reg = /\:\r\n\{/g;
|
||||||
|
json = json.replace(reg, ":{");
|
||||||
|
reg = /\:\r\n\[/g;
|
||||||
|
json = json.replace(reg, ":[");
|
||||||
|
}
|
||||||
|
if (options.spaceAfterColon) {
|
||||||
|
reg = /\:/g;
|
||||||
|
json = json.replace(reg, ":");
|
||||||
|
}
|
||||||
|
json.split("\r\n").forEach(function (node, index) {
|
||||||
|
//console.log(node);
|
||||||
|
var i = 0,
|
||||||
|
indent = 0,
|
||||||
|
padding = "";
|
||||||
|
|
||||||
|
if (node.match(/\{$/) || node.match(/\[$/)) {
|
||||||
|
indent = 1;
|
||||||
|
} else if (node.match(/\}/) || node.match(/\]/)) {
|
||||||
|
if (pad !== 0) {
|
||||||
|
pad -= 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
indent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < pad; i++) {
|
||||||
|
padding += PADDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatted += padding + node + "\r\n";
|
||||||
|
pad += indent;
|
||||||
|
});
|
||||||
|
console.log(formatted);
|
||||||
|
};
|
17
src/utils/envent.js
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* 发送自定义事件
|
||||||
|
* @param {*} webview
|
||||||
|
* @param {*} eventType
|
||||||
|
* @param {*} data
|
||||||
|
*/
|
||||||
|
export const fire = function(webview, eventType, data) {
|
||||||
|
console.log(data);
|
||||||
|
webview &&
|
||||||
|
webview.evalJS(`
|
||||||
|
document.dispatchEvent(new CustomEvent("${eventType}", {
|
||||||
|
detail:${JSON.stringify(data)},
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true
|
||||||
|
}));
|
||||||
|
`);
|
||||||
|
};
|
6
src/utils/plus/nativeUI.js
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
//http://www.html5plus.org/doc/zh_cn/nativeui.html#plus.nativeUI.confirm
|
||||||
|
export function confirm(message, title = "确认") {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
plus.nativeUI.confirm(message, resolve, title);
|
||||||
|
});
|
||||||
|
}
|
7
src/utils/plus/runtime.js
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
export function getProperty() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
|
||||||
|
resolve(inf);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
14
src/utils/request.js
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* http请求模块
|
||||||
|
*/
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export async function request (data) {
|
||||||
|
const conf = {
|
||||||
|
headers: {
|
||||||
|
// Authorization: "token"
|
||||||
|
},
|
||||||
|
...data
|
||||||
|
}
|
||||||
|
return await axios(conf)
|
||||||
|
}
|
13
src/utils/tools.js
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
export function isAndroid() {
|
||||||
|
const ua = navigator.userAgent;
|
||||||
|
return ua.match(/(Android);?[\s\/]+([\d.]+)?/);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isIos() {
|
||||||
|
const ua = navigator.userAgent;
|
||||||
|
return ua.match(/(iPhone\sOS)\s([\d_]+)/);
|
||||||
|
}
|
||||||
|
|
||||||
|
// var iphone = ua.match(/(iPhone\sOS)\s([\d_]+)/);
|
||||||
|
// var ipad = ua.match(/(iPad).*OS\s([\d_]+)/);
|
||||||
|
// var wechat = ua.match(/(MicroMessenger)\/([\d\.]+)/i);
|
108
src/utils/webview.js
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* 打开一个webview窗口
|
||||||
|
*/
|
||||||
|
export function openWebview(config, style = {}, extras = {}) {
|
||||||
|
var wv = plus.webview.create(
|
||||||
|
config.url,
|
||||||
|
config.id,
|
||||||
|
{
|
||||||
|
top: 0, // 新页面顶部位置
|
||||||
|
bottom: 0, // 新页面底部位置
|
||||||
|
render: "always",
|
||||||
|
popGesture: "hide",
|
||||||
|
bounce: "vertical",
|
||||||
|
bounceBackground: "#efeff4",
|
||||||
|
titleNView: {
|
||||||
|
// 详情页原生导航配置
|
||||||
|
backgroundColor: "#f7f7f7", // 导航栏背景色
|
||||||
|
titleText: config.title, // 导航栏标题
|
||||||
|
titleColor: "#000000", // 文字颜色
|
||||||
|
type: "transparent", // 透明渐变样式
|
||||||
|
autoBackButton: true, // 自动绘制返回箭头
|
||||||
|
splitLine: {
|
||||||
|
// 底部分割线
|
||||||
|
color: "#cccccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...style
|
||||||
|
},
|
||||||
|
extras
|
||||||
|
);
|
||||||
|
var w = plus.nativeUI.showWaiting();
|
||||||
|
// 监听窗口加载成功
|
||||||
|
wv.addEventListener(
|
||||||
|
"loaded",
|
||||||
|
function () {
|
||||||
|
wv.show("slide-in-right"); // 显示窗口
|
||||||
|
w.close();
|
||||||
|
w = null;
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// webview.open 打开得很快 但是不能传参
|
||||||
|
export function openWebviewFast(url, id, title) {
|
||||||
|
plus.nativeUI.showWaiting("加载中");
|
||||||
|
plus.webview.open(
|
||||||
|
url,
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
titleNView: {
|
||||||
|
backgroundColor: "#f7f7f7", // 导航栏背景色
|
||||||
|
titleText: title, // 导航栏标题
|
||||||
|
titleColor: "#666", // 文字颜色
|
||||||
|
// type: "transparent", // 透明渐变样式
|
||||||
|
autoBackButton: true, // 自动绘制返回箭头
|
||||||
|
splitLine: {
|
||||||
|
// 底部分割线
|
||||||
|
color: "#cccccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"slide-in-right",
|
||||||
|
420,
|
||||||
|
function () {
|
||||||
|
plus.nativeUI.closeWaiting();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 预加载页面 速度很快,但是不要加载超过10个
|
||||||
|
export function preLoad(webviews = []) {
|
||||||
|
webviews.map(webview => {
|
||||||
|
const fullExtras = {
|
||||||
|
webviewPreload: true,
|
||||||
|
...webview.extras
|
||||||
|
};
|
||||||
|
plus.webview.create(
|
||||||
|
webview.url,
|
||||||
|
webview.id,
|
||||||
|
{
|
||||||
|
top: 0, // 新页面顶部位置
|
||||||
|
bottom: 0, // 新页面底部位置
|
||||||
|
render: "always",
|
||||||
|
popGesture: "hide",
|
||||||
|
bounce: "vertical",
|
||||||
|
bounceBackground: "#efeff4",
|
||||||
|
titleNView: {
|
||||||
|
// 详情页原生导航配置
|
||||||
|
backgroundColor: "#f7f7f7", // 导航栏背景色
|
||||||
|
titleText: webview.title, // 导航栏标题
|
||||||
|
titleColor: "#000000", // 文字颜色
|
||||||
|
type: "transparent", // 透明渐变样式
|
||||||
|
autoBackButton: true, // 自动绘制返回箭头
|
||||||
|
splitLine: {
|
||||||
|
// 底部分割线
|
||||||
|
color: "#cccccc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...webview.style
|
||||||
|
},
|
||||||
|
fullExtras
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showWebviewById(id) {
|
||||||
|
plus.webview.show(id, "slide-in-right", 200);
|
||||||
|
}
|
0
static/.gitkeep
Executable file
7
test/unit/.eslintrc
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"jest": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
}
|
||||||
|
}
|
26
test/unit/jest.conf.js
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
rootDir: path.resolve(__dirname, '../../'),
|
||||||
|
moduleFileExtensions: [
|
||||||
|
'js',
|
||||||
|
'json',
|
||||||
|
'vue'
|
||||||
|
],
|
||||||
|
moduleNameMapper: {
|
||||||
|
'^@/(.*)$': '<rootDir>/src/$1'
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
|
||||||
|
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
|
||||||
|
},
|
||||||
|
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
||||||
|
setupFiles: ['<rootDir>/test/unit/setup'],
|
||||||
|
mapCoverage: true,
|
||||||
|
coverageDirectory: '<rootDir>/test/unit/coverage',
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.{js,vue}',
|
||||||
|
'!src/main.js',
|
||||||
|
'!**/node_modules/**'
|
||||||
|
]
|
||||||
|
}
|
3
test/unit/setup.js
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
Vue.config.productionTip = false
|
11
test/unit/specs/HelloWorld.spec.js
Executable file
@ -0,0 +1,11 @@
|
|||||||
|
import Vue from 'vue'
|
||||||
|
import HelloWorld from '@/components/HelloWorld'
|
||||||
|
|
||||||
|
describe('HelloWorld.vue', () => {
|
||||||
|
it('should render correct contents', () => {
|
||||||
|
const Constructor = Vue.extend(HelloWorld)
|
||||||
|
const vm = new Constructor().$mount()
|
||||||
|
expect(vm.$el.querySelector('.hello h1').textContent)
|
||||||
|
.toEqual('Welcome to Your Vue.js App')
|
||||||
|
})
|
||||||
|
})
|
35
unpackage/.confirmed_dependencies
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"dist/index.html": {
|
||||||
|
"refer": [
|
||||||
|
"dist/goods.detail.html",
|
||||||
|
"dist/mui.index.html",
|
||||||
|
"dist/vux.index.html",
|
||||||
|
"dist/goods.cart.html"
|
||||||
|
],
|
||||||
|
"resources": [
|
||||||
|
"dist/assets/css/vue.css",
|
||||||
|
"dist/assets/css/index.css",
|
||||||
|
"dist/assets/img/logo.png"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dist/vux.index.html": {
|
||||||
|
"resources": [
|
||||||
|
"dist/assets/css/vux.index.css",
|
||||||
|
"dist/assets/css/vue.css"
|
||||||
|
],
|
||||||
|
"refer": []
|
||||||
|
},
|
||||||
|
"dist/goods.detail.html": {
|
||||||
|
"resources": [
|
||||||
|
"dist/assets/css/goods.detail.css"
|
||||||
|
],
|
||||||
|
"refer": []
|
||||||
|
},
|
||||||
|
"dist/goods.cart.html": {
|
||||||
|
"resources": [
|
||||||
|
"dist/assets/css/goods.cart.css",
|
||||||
|
"dist/assets/css/vue.css"
|
||||||
|
],
|
||||||
|
"refer": []
|
||||||
|
}
|
||||||
|
}
|
1
unpackage/.dependencies
Executable file
@ -0,0 +1 @@
|
|||||||
|
null
|
BIN
unpackage/res/icons/1024x1024.png
Executable file
After Width: | Height: | Size: 82 KiB |
BIN
unpackage/res/icons/120x120.png
Executable file
After Width: | Height: | Size: 6.8 KiB |