Compare commits

...

21 Commits

Author SHA1 Message Date
xuxiaoyan b30b01e9b5 Merge branch 'weapp' of https://github.com/didi/mand-mobile into weapp 2018-09-18 14:19:15 +08:00
xuxiaoyan f5a873234a feat(switch): fit for weapp 2018-09-18 14:19:04 +08:00
supergaojian 129b0230d3 Merge branch 'weapp' of https://github.com/didi/mand-mobile into weapp 2018-09-18 10:38:37 +08:00
xuxiaoyan 6d7671320c feat(action-bar): fit for weapp 2018-09-17 15:45:58 +08:00
xuxiaoyan f25fc9ae42 Merge branch 'weapp' of https://github.com/didi/mand-mobile into weapp 2018-09-17 10:31:32 +08:00
supergaojian feea93039f Merge branch 'weapp' of https://github.com/didi/mand-mobile into weapp 2018-09-17 09:53:25 +08:00
supergaojian 126546c709 feat: add loader for weapp demo 2018-09-17 09:53:14 +08:00
xuxiaoyan 3741183838 resolve conflicts 2018-09-16 22:45:54 +08:00
xuxiaoyan 60de1c7360 resolve conflicts 2018-09-16 22:45:15 +08:00
xuxiaoyan ccdf350295 feat: weapp development entry & plantform 2018-09-16 17:13:14 +08:00
supergaojian 68dfb01ed2 feat: rebuild examples/build env for weapp 2018-09-16 17:13:14 +08:00
supergaojian 84ab47752d feat(build): mand mobile 2.0 for weapp build env 2018-09-16 17:12:38 +08:00
supergaojian 22aa10e4c3 feat(build): mand mobile 2.0 for mpvue/weapp add app.json 2018-09-16 17:12:38 +08:00
supergaojian 56b8b5c2ce feat(build): mand-mobile 2.0 for mpvue/weapp 2018-09-16 17:12:38 +08:00
xuxiaoyan f1eb365c42 feat(button): weapp demo 2018-09-14 18:58:23 +08:00
xuxiaoyan a573115739 feat: weapp development entry & plantform 2018-09-14 18:09:23 +08:00
supergaojian 5423449632 feat: rebuild examples/build env for weapp 2018-09-13 19:12:44 +08:00
supergaojian d4c9ec1d30 Merge remote-tracking branch 'remotes/origin/2.0' into weapp 2018-09-07 10:44:40 +08:00
supergaojian 8e6fff84b4 feat(build): mand mobile 2.0 for weapp build env 2018-09-07 10:44:29 +08:00
supergaojian a9f30f9e37 feat(build): mand mobile 2.0 for mpvue/weapp add app.json 2018-09-05 15:52:04 +08:00
supergaojian b4640b8bb5 feat(build): mand-mobile 2.0 for mpvue/weapp 2018-09-05 10:18:00 +08:00
59 changed files with 1464 additions and 1012 deletions

View File

@ -10,7 +10,11 @@
"plugins": [
"transform-object-rest-spread",
"syntax-dynamic-import",
"transform-vue-jsx"
"transform-vue-jsx",
["import", {
"libraryName": "mand-mobile",
"libraryDirectory": "components"
}]
],
"env": {
"test": {

View File

@ -1,6 +1,7 @@
build/*.js
config/*.js
lib/*
dist/*
output/*
examples/*
site/*

View File

@ -12,8 +12,7 @@ const fs = bluebird.promisifyAll(require('fs'))
const CWD = process.cwd()
const COMPONENTS_PATH = path.resolve(CWD, './components')
const EXPECT_SHELL = path.resolve(CWD, './build/template.exp')
const DEMO_INDEX_PATH = path.resolve(CWD, './examples/demo-index.js')
const DEMO_INDEX_PATH_INDEMAND = path.resolve(CWD, './examples/demo-index.indemand.js')
const DEMO_INDEX_PATH = path.resolve(CWD, './examples/web/demo-index.js')
const COMPONENT_INDEX = path.resolve(CWD, './components/index.js')
const COMPONENT_JSON = path.resolve(CWD, './examples/components.json')
@ -47,7 +46,7 @@ function changeKebabToCamel(str) {
}
function sync(answers) {
return Promise.all([syncToComponentJson(answers), syncToExample(answers), syncToIndex(answers), syncToExampleIndemand(answers)]).then(() =>answers)
return Promise.all([syncToComponentJson(answers), syncToExample(answers), syncToIndex(answers)]).then(() =>answers)
}
function syncToExample(answers) {
@ -58,14 +57,6 @@ function syncToExample(answers) {
.then(str => fs.writeFileAsync(DEMO_INDEX_PATH, str, 'utf8'))
.then(() => answers)
}
function syncToExampleIndemand(answers) {
fs.readFileAsync(DEMO_INDEX_PATH_INDEMAND, 'utf8')
.then(str => {
return compile(answers, str)
})
.then(str => fs.writeFileAsync(DEMO_INDEX_PATH_INDEMAND, str, 'utf8'))
.then(() => answers)
}
function syncToIndex(answers) {
/* 同步components/index文件 */
@ -164,7 +155,7 @@ function launch() {
type: 'input',
name: 'componentCnName',
message: '请输入要创建的组件中文名称(中文):',
},
},
{
type: 'list',
choices: [

View File

@ -3,7 +3,7 @@ const rollup = require('rollup')
const path = require('path')
const inputOptions = {
input: path.resolve(PROJECT_DIR, 'examples/main.indemand.js'),
input: path.resolve(PROJECT_DIR, 'examples/web/main.js'),
plugins: rollupPlugin,
}
@ -25,4 +25,4 @@ function build() {
})
}
build()
build()

View File

@ -11,7 +11,7 @@ const history = require('connect-history-api-fallback')
const port = 4000
const inputOptions = {
input: path.resolve(PROJECT_DIR, 'examples/main.indemand.js'),
input: path.resolve(PROJECT_DIR, 'examples/web/main.js'),
plugins: rollupPlugin,
}
@ -44,7 +44,7 @@ function serve(path) {
function runServer() {
// rollup buildwatch
watch()
// livereload
const lrserver = livereload.createServer()
lrserver.watch(path.join(process.cwd(), 'output'))
@ -61,4 +61,4 @@ function runServer() {
}
runServer()
runServer()

View File

@ -11,7 +11,16 @@ const path = require('path')
const express = require('express')
const webpack = require('webpack')
const proxyMiddleware = require('http-proxy-middleware')
let webpackConfig = require('./webpack.dev.conf')
let webpackConfig
// 这需要判断是否构建小程序
let isWeapp = process.env.NODE_ENV === 'weapp'
if (isWeapp) {
webpackConfig = require('./webpack.dev.weapp.conf')
} else {
webpackConfig = require('./webpack.dev.conf')
}
// default port where dev server listens for incoming traffic
const port = process.env.PORT || config.dev.port
// automatically open browser, if not set will be false
@ -23,20 +32,33 @@ const proxyTable = config.dev.proxyTable
const app = express()
const compiler = webpack(webpackConfig)
const resolve = file => path.resolve(__dirname, file)
const devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
})
const hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: false,
heartbeat: 2000
})
let devMiddleware
// 小程序需要引入webpack-dev-middleware-hard-disk
if (isWeapp) {
devMiddleware = require('webpack-dev-middleware-hard-disk')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true
})
} else {
devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
})
app.use(devMiddleware)
const hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: false,
heartbeat: 2000
})
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
}
const serve = function (path) {
return express.static(resolve(path), {})
}
// force page reload when html-webpack-plugin template changes
// currently disabled until this is resolved:
// https://github.com/jantimon/html-webpack-plugin/issues/680
@ -47,10 +69,6 @@ const serve = function (path) {
// })
// })
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
let options = proxyTable[context]
@ -64,7 +82,6 @@ Object.keys(proxyTable).forEach(function (context) {
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
app.use('/static', serve(path.join(__dirname, '../../static')))
// serve pure static assets
// const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)

View File

@ -4,6 +4,7 @@ const config = require('../../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const resolve = file => path.resolve(__dirname, file)
const isProd = process.env.NODE_ENV === 'production'
const isWeapp = process.env.NODE_ENV === 'weapp'
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
@ -23,9 +24,28 @@ exports.cssLoaders = function (options) {
}
}
var postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: true
}
}
var px2rpxLoader = {
loader: 'px2rpx-loader',
options: {
baseDpr: 1,
rpxUnit: 0.5
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = [cssLoader]
if (isWeapp) {
loaders.push(px2rpxLoader)
loaders.push(postcssLoader)
}
if (loader) {
loaders.push({
loader: loader + '-loader',
@ -63,6 +83,7 @@ exports.cssLoaders = function (options) {
return {
css: generateLoaders(),
wxss: generateLoaders(),
postcss: generateLoaders(),
stylus: generateLoaders('stylus', {
import: stylusMixins

View File

@ -1,7 +1,10 @@
'use strict'
const utils = require('./utils')
const config = require('../../config')
const isProduction = process.env.NODE_ENV === 'production'
let isProduction = process.env.NODE_ENV === 'production'
if (process.env.NODE_ENV === 'weapp') {
isProduction = true
}
module.exports = {
loaders: utils.cssLoaders({

View File

@ -17,12 +17,12 @@ const pxtoremConfig = pxtorem({ rootValue: 100, propWhiteList: [], minPixelValue
const argv = require('yargs').argv
let entry = {
'index': ['./build/webpack/dev-client', './examples/main.js']
'index': ['./build/webpack/dev-client', './examples/web/main.js']
}
if (argv.component) {
entry = {
'index': ['./build/webpack/dev-client', './examples/single-component-main.js']
'index': ['./build/webpack/dev-client', './examples/web/single-component-main.js']
}
}
@ -61,7 +61,7 @@ module.exports = merge(baseWebpackConfig, {
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.dev.index,
template: './examples/index.html',
template: './examples/web/index.html',
inject: true
}),
new FriendlyErrorsPlugin()

View File

@ -0,0 +1,160 @@
const utils = require('./utils')
const webpack = require('webpack')
const glob = require('glob')
const config = require('../../config')
const merge = require('webpack-merge')
let baseWebpackConfig = require('./webpack.base.conf')
let vueLoaderConfig = require('./vue-loader.conf')
const path = require('path')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const DashBoardPlugin = require('webpack-dashboard/plugin')
const MpvuePlugin = require('webpack-mpvue-asset-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const pkg = require('../../package.json')
const argv = require('yargs').argv
function resolve (dir) {
return path.join(__dirname, '../..', dir)
}
function getEntry (rootSrc, pattern) {
let files = glob.sync(path.resolve(rootSrc, pattern))
return files.reduce((res, file) => {
let info = path.parse(file)
let key = info.dir.slice(rootSrc.length + 1) + '/' + info.name
res[key] = path.resolve(file)
return res
}, {})
}
const appEntry = {
app: resolve('./examples/weapp/main.js')
}
const homePagesEntry = getEntry(resolve('./examples/weapp/pages'), '**/**/page.js')
const demoPagesEntry = getEntry(resolve('./components'), '**/**/page.js')
const pagesEntry = Object.assign(homePagesEntry, demoPagesEntry)
const entry = Object.assign({}, appEntry, pagesEntry)
// 微信小程序解析.vue文件使用mpvue-loader解析
// 所以将webpack.base.conf中的vue-loader切换至mpvue-loader
baseWebpackConfig = merge.smart(baseWebpackConfig, {
resolve: {
symlinks: false,
aliasFields: ['mpvue', 'weapp', 'browser'],
mainFields: ['browser', 'module', 'main']
},
module: {
rules: [
{
test: /\.vue$/,
use: [
{
loader: 'mpvue-loader',
options: vueLoaderConfig
},
{
loader: path.resolve('platforms/weapp/loader.js')
}
]
},
{
test: /\.js$/,
include: [resolve('components'), resolve('examples'), resolve('test')],
use: [
'babel-loader',
{
loader: 'mpvue-loader',
options: {
checkMPEntry: true
}
},
]
}
]
}
})
baseWebpackConfig.resolve.alias = {
'vue': 'mpvue',
'@examples': resolve('examples'),
'mand-mobile/lib': resolve('components'),
'mand-mobile/components': resolve('components'),
'mand-mobile': resolve('components'),
}
module.exports = merge(baseWebpackConfig, {
entry,
target: require('mpvue-webpack-target'),
module: {
rules: utils.styleLoaders({
sourceMap: config.devWeapp.cssSourceMap,
extract: true
})
},
devtool: '#source-map',
output: {
path: config.devWeapp.assetsRoot,
filename: path.posix.join('', '[name].js'),
chunkFilename: path.posix.join('', '[id].js'),
publicPath: config.devWeapp.assetsPublicPath
},
plugins: [
new DashBoardPlugin(),
new MpvuePlugin(),
new webpack.DefinePlugin({
'process.env': config.devWeapp.env,
'COMPONENT_NAME': `'${argv.component}'`,
'MAN_VERSION': `'${pkg.version}'`
}),
// copy from ./webpack.prod.conf.js
// extract css into its own f ile
new ExtractTextPlugin({
filename: path.posix.join('', '[name].wxss')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: {
safe: true
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common/vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf('node_modules') >= 0
) || count > 1
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common/manifest',
chunks: ['common/vendor']
}),
// copy custom static assets
// new CopyWebpackPlugin([
// {
// from: path.resolve(__dirname, '../../static'),
// to: config.devWeapp.assetsRoot,
// ignore: ['.*']
// }
// ]),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../../examples/weapp/*.json'),
to: path.resolve(__dirname, '../../dist'),
ignore: ['.*'],
flatten: true
}
]),
new webpack.NoEmitOnErrorsPlugin(),
new FriendlyErrorsPlugin()
]
})

View File

@ -17,7 +17,7 @@ const env = config.example.env
const webpackConfig = merge(baseWebpackConfig, {
entry: {
'index': './examples/main.js',
'index': './examples/web/main.js',
},
module: {
rules: utils.styleLoaders({

View File

@ -4,7 +4,7 @@
</div>
</template>
<script> import {ActionBar, Toast} from 'mand-mobile'
<script> import {ActionBar} from 'mand-mobile'
export default {
name: 'action-bar-demo',
@ -27,7 +27,7 @@ export default {
},
methods: {
handleClick() {
Toast.succeed('Click')
// Toast.succeed('Click')
},
},
}

View File

@ -1,9 +1,9 @@
<template>
<div class="md-example-child md-example-child-action-bar md-example-child-3">
<md-action-bar :actions="data" @click="onBtnClick">
<span class="price">
&yen;128.00<small></small>
</span>
<p class="price">
&yen;128.00<span></span>
</p>
</md-action-bar>
</div>
</template>
@ -45,7 +45,7 @@ export default {
font-weight 500
font-size 48px
color #FF823A
small
span
margin-left 10px
font-size 32px
color #858B9C

View File

@ -1,22 +1,40 @@
<template>
<div class="md-example action-bar">
<section class="md-example-section" v-for="(demo, index) in demos" :key="index">
<div class="md-example-title" v-html="demo.title || '基础'"></div>
<section class="md-example-section">
<div class="md-example-content">
<component :is="demo"></component>
<demo0></demo0>
</div>
</section>
<section class="md-example-section">
<div class="md-example-content">
<demo1></demo1>
</div>
</section>
<section class="md-example-section">
<div class="md-example-content">
<demo2></demo2>
</div>
</section>
<section class="md-example-section">
<div class="md-example-content">
<demo3></demo3>
</div>
</section>
</div>
</template>
<script> import createDemoModule from '../../../examples/create-demo-module'
import Demo0 from './cases/demo0'
<script> import Demo0 from './cases/demo0'
import Demo1 from './cases/demo1'
import Demo2 from './cases/demo2'
import Demo3 from './cases/demo3'
export default {
...createDemoModule('action-bar', [Demo0, Demo1, Demo2, Demo3]),
components: {
Demo0,
Demo1,
Demo2,
Demo3,
},
}
</script>

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()

View File

@ -4,17 +4,14 @@
<slot></slot>
</div>
<div class="md-action-bar-group">
<template v-for="(item, index) in coerceActions">
<md-button
class="md-action-bar-button"
:type="!!item.disabled ? 'disabled' : 'primary'"
:plain="index !== coerceActions.length - 1"
:key="index"
@click="$_onBtnClick($event, item)"
>
{{ item.text }}
</md-button>
</template>
<md-button
v-for="(item, index) in coerceActions"
:type="!!item.disabled ? 'disabled' : 'primary'"
:plain="index !== coerceActions.length - 1"
:content="item.text"
:key="index"
@click="$_onBtnClick($event, item)"
></md-button>
</div>
</div>
</template>
@ -83,13 +80,12 @@ export default {
display flex
flex 1
height 100%
.md-action-bar-button
display flex
float right
align-items center
justify-content center
flex 1
&:nth-of-type(2)
margin-left action-bar-button-gap
.md-button
display flex
float right
align-items center
justify-content center
flex 1
&:nth-of-type(2)
margin-left action-bar-button-gap
</style>

View File

@ -6,7 +6,7 @@
<md-button type="primary" inactive>Primary Inactive</md-button>
<md-button type="warning">Warning</md-button>
<md-button type="warning" inactive>Warning Inactive</md-button>
<md-button type="disabled">Disabled</md-button>
<md-button type="disabled">Disabled</md-button>
</div>
</template>

View File

@ -1,33 +1,53 @@
<template>
<div class="md-example button">
<section class="md-example-section" v-for="(demo, index) in demos" :key="index">
<div class="md-example-title" v-html="demo.title || '基础'"></div>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-content">
<component :is="demo"></component>
<demo0></demo0>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-content">
<demo1></demo1>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-content">
<demo2></demo2>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-content">
<demo3></demo3>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-content">
<demo4></demo4>
</div>
</section>
</div>
</template>
<script> import createDemoModule from '../../../examples/create-demo-module'
import Demo0 from './cases/demo0'
<script> import Demo0 from './cases/demo0'
import Demo1 from './cases/demo1'
import Demo2 from './cases/demo2'
import Demo3 from './cases/demo3'
import Demo4 from './cases/demo4'
export default {
...createDemoModule('button', [Demo0, Demo1, Demo2, Demo3, Demo4]),
components: {
Demo0,
Demo1,
Demo2,
Demo3,
Demo4,
},
}
// export default {
// name: `button-demo`,
// data() {
// return {
// demos: [Demo0, Demo1, Demo2, Demo3],
// }
// },
// }
</script>
<style lang="stylus">

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()

View File

@ -15,7 +15,10 @@
<template v-if="icon">
<md-icon :name="icon"></md-icon>
</template>
<p class="md-button-content">
<p class="md-button-content" v-if="content">
{{ content }}
</p>
<p class="md-button-content" v-else>
<slot></slot>
</p>
</div>
@ -59,6 +62,9 @@ export default {
type: Boolean,
default: false,
},
content: {
type: String,
},
},
methods: {

View File

@ -1,5 +1,6 @@
<template>
<svg
<div></div>
<!-- <svg
v-if="name"
class="md-icon"
:class="[`md-icon-${name}`, size]"
@ -7,7 +8,7 @@
@click="$emit('click', $event)"
>
<use :xlink:href="`#${name}`"/>
</svg>
</svg> -->
</template>
<script> import loadSprite from './load-spirte'

View File

@ -80,16 +80,6 @@ export default {
}
},
},
preventScroll: {
type: Boolean,
default: false,
},
preventScrollExclude: {
type: [String, HTMLElement],
default() {
return ''
},
},
},
data() {
@ -118,13 +108,6 @@ export default {
this.$_hidePopupBox()
}
},
preventScrollExclude(val, oldVal) {
// remove old listener before add
/* istanbul ignore next */
this.$_preventScrollExclude(false, oldVal)
/* istanbul ignore next */
this.$_preventScrollExclude(true, val)
},
},
mounted() {
@ -144,44 +127,16 @@ export default {
this.$_onPopupTransitionEnd()
}
})
this.preventScroll && this.$_preventScroll(true)
},
$_hidePopupBox() {
this.isAnimation = true
this.isPopupBoxShow = false
this.preventScroll && this.$_preventScroll(false)
this.$emit('input', false)
/* istanbul ignore if */
if (process.env.NODE_ENV === 'testing') {
this.$_onPopupTransitionEnd()
}
},
$_preventScroll(isBind) {
const handler = isBind ? 'addEventListener' : 'removeEventListener'
const masker = this.$el.querySelector('.md-popup-mask')
const boxer = this.$el.querySelector('.md-popup-box')
masker && masker[handler]('touchmove', this.$_preventDefault, false)
boxer && boxer[handler]('touchmove', this.$_preventDefault, false)
this.$_preventScrollExclude(isBind)
},
$_preventScrollExclude(isBind, preventScrollExclude) {
const handler = isBind ? 'addEventListener' : 'removeEventListener'
preventScrollExclude = preventScrollExclude || this.preventScrollExclude
const excluder =
preventScrollExclude && typeof preventScrollExclude === 'string'
? this.$el.querySelector(preventScrollExclude)
: preventScrollExclude
excluder && excluder[handler]('touchmove', this.$_stopImmediatePropagation, false)
},
$_preventDefault(event) {
event.preventDefault()
},
$_stopImmediatePropagation(event) {
/* istanbul ignore next */
event.stopImmediatePropagation()
},
// MARK: event handler
$_onPopupTransitionStart() {

View File

@ -1,22 +1,49 @@
<template>
<div class="md-example switch">
<section class="md-example-section" v-for="(demo, index) in demos" :key="index">
<div class="md-example-title" v-html="demo.title || '基础'"></div>
<div class="md-example-describe" v-html="demo.describe"></div>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-describe"></div>
<div class="md-example-content">
<component :is="demo"></component>
<demo0></demo0>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-describe"></div>
<div class="md-example-content">
<demo1></demo1>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-describe"></div>
<div class="md-example-content">
<demo2></demo2>
</div>
</section>
<section class="md-example-section">
<div class="md-example-title"></div>
<div class="md-example-describe"></div>
<div class="md-example-content">
<demo3></demo3>
</div>
</section>
</div>
</template>
<script> import createDemoModule from '../../../examples/create-demo-module'
import Demo0 from './cases/demo0'
<script> import Demo0 from './cases/demo0'
import Demo1 from './cases/demo1'
import Demo2 from './cases/demo2'
import Demo3 from './cases/demo3'
export default {...createDemoModule('switch', [Demo0, Demo1, Demo2, Demo3])}
export default {
components: {
Demo0,
Demo1,
Demo2,
Demo3,
},
}
</script>
<style lang="stylus" scoped>

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()

View File

@ -11,28 +11,28 @@
}"
>
<ul
v-for="i in (repeatY ? 50 : 1)"
v-for="(i, lineIndex) in (repeatY ? 50 : 1)"
class="water-mark-line"
:style="{
marginBottom: spacing,
}"
:key="`line-${i}`"
:key="`line-${lineIndex}`"
>
<li
v-for="j in (repeatX ? 50 : 1)"
v-for="(j, itemIndex) in (repeatX ? 50 : 1)"
class="water-mark-item"
:style="i % 2 === 0 ? {
marginLeft: repeatX ? spacing : 0,
} : {
marginRight: repeatX ? spacing : 0,
}"
:key="`item-${j}`"
:key="`item-${itemIndex}`"
>
<p v-if="content">{{ content }}</p>
<slot
v-else-if="!!$scopedSlots.watermark"
name="watermark"
@index="index"
@index="{ i: lineIndex, j: itemIndex }"
></slot>
</li>
</ul>

View File

@ -57,5 +57,19 @@ module.exports = {
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
},
devWeapp: {
env: require('./dev.env'),
port: process.env.PORT || 4000,
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: '',
assetsPublicPath: '/example',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

View File

@ -1,148 +0,0 @@
<template>
<div class="mand">
<template v-if="isHome">
<router-view></router-view>
</template>
<template v-else>
<div class="md-nav">
<p class="home" @click="goToCategory"><i></i><i></i><i></i></p>
<p class="name" v-text="navTitle"></p>
<p class="name-zh" v-text="navSubTitle"></p>
</div>
<div class="md-example-wrapper">
<router-view></router-view>
</div>
</template>
</div>
</template>
<script>
import './assets/responsive'
export default {
name: 'app',
computed: {
navTitle() {
return this.$route.name
},
navSubTitle() {
return this.$route.meta.description
},
isHome() {
const path = this.$route.path
return path === '/' || path === '/home' || path === '/category'
},
},
methods: {
goToCategory() {
this.$router.push('/category')
},
},
}
</script>
<style lang="stylus">
block()
float left
width 100%
.mand
position relative
min-height 100%
max-width 750px
font-size 28px
font-size-adjust none
-webkit-text-size-adjust 100%
-webkit-overflow-scrolling touch
font-family -apple-system,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","Microsoft JhengHei","Source Han Sans SC","Noto Sans CJK SC","Source Han Sans CN","Noto Sans SC","Source Han Sans TC","Noto Sans CJK TC","WenQuanYi Micro Hei",SimSun,sans-serif !important
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
background color-primary-background
.md-nav
position relative
display flex
padding 32px 20px
p
position relative
display inline-block
line-height 1
&.home
top 5px
width 36px
height 32px
i
position absolute
left 0
width 100%
height .04rem
background color-bg-mask
border-radius 2px
&:nth-of-type(1)
top 0
&:nth-of-type(2)
top 50%
width 70%
margin-top -.02rem
&:nth-of-type(3)
bottom 0
&.name
margin-left h-gap-lg
font-size font-heading-large
font-weight font-weight-medium
color color-text-base
&.name-zh
top 9px
margin-left h-gap-sm
font-size font-body-large
font-weight font-weight-normal
color color-text-minor
.md-example-wrapper
position relative
z-index 3
padding 20px
clearfix()
.md-example
.md-example-section
clearfix()
margin-bottom 30px
color color-text-base
.md-example-title
block()
font-size font-body-normal
font-weight font-weight-medium
a
margin-right 5px
background color-primary-tap
color #fff
padding 5px 10px
border-radius radius-normal
font-size font-minor-large
font-weight 300
line-height 28px
text-decoration none
.md-example-describe
block()
margin-top 15px
font-size font-minor-large
font-weight 300
color color-text-minor
.md-example-content
block()
position relative
margin-top 20px
box-sizing border-box
.md-dialog pre
width 100%
padding 20px 10px
box-sizing border-box
white-space pre-wrap
word-wrap break-word
font-size font-minor-normal
background color-primary-background
border-radius radius-normal
@media screen and (min-width: 749px)
.mand
margin-left -360px
left 50%
</style>

View File

@ -1,189 +0,0 @@
<template>
<div class="md-cg">
<h1 class="md-cg-title">Mand Mobile</h1>
<h1 class="md-cg-subtitle">面向金融场景的移动端Vue组件库</h1>
<section
v-for="(category, i) in components" :key="i"
class="cg-category"
:class="{'active': category.show}">
<div
class="cg-category-title"
:class="{'active': category.show}"
@click="toggleCategory(i, category)">
{{ category.name }}&nbsp;&nbsp;<span>{{ category.text }}</span>
<md-icon name="arrow-right" size="lg"></md-icon>
</div>
<transition name="slide-fade">
<div class="cg-category-list" v-show="category.show">
<div class="cg-category-item"
v-for="(item, j) in category.list"
:key="j"
@click="goToComponent(item.path)">
<div class="cg-category-item-inner">
{{ item.name }} - {{ item.text }}
<md-icon name="arrow-right" size="md"></md-icon>
</div>
</div>
<div class="cg-category-item" @click="toggleCategory(i, category)">
<div class="cg-category-item-inner close">收起</div>
</div>
</div>
</transition>
</section>
<h1 class="md-cg-copyright">Produced By DiDi - FDC &times; MFE</h1>
</div>
</template>
<script>
import components from './components.json'
import Icon from '../components/icon'
export default {
name: 'category',
components: {
[Icon.name]: Icon,
},
data() {
return {
components,
}
},
methods: {
toggleCategory(index, category) {
category.show = !category.show
this.$set(this.components, index, category)
},
goToComponent(path) {
this.$router.push(path)
},
},
}
</script>
<style lang="stylus" scoped>
block()
float left
width 100%
.md-cg
padding 20px 20px 50px
clearfix()
.md-cg-title
block()
margin 20px 0
font-size font-heading-large
font-weight font-weight-normal
color color-text-minor
span
color color-text-base
.md-cg-subtitle
block()
margin-bottom 30px
font-size font-body-normal
font-weight 300
color color-text-minor
.cg-category
block()
position relative
z-index 3
height 120px
margin-bottom 20px
border-radius border-width-base
transform translate(0, 0)
&.active
height auto
// box-shadow shadow-bottom
.cg-category-title
position relative
z-index 2
block()
height 120px
padding 0 h-gap-lg
line-height 120px
font-size font-heading-normal
// font-weight font-weight-medium
color color-text-base
box-sizing border-box
box-shadow shadow-bottom
background color-bg-base
overflow hidden
span
font-size font-body-large
color color-text-minor
.md-icon
position absolute
right h-gap-lg
top 50%
transform translateY(-50%)
transition transform .3s ease-in-out-quint
&.active .md-icon
transform translateY(-50%) rotate(90deg)
&:before
content ""
position absolute
left 0
top 0
width 4px
height 100%
border-radius border-width-base
// display none
&:nth-of-type(1) .cg-category-title:before
background #5E83DD
&:nth-of-type(2) .cg-category-title:before
background #83D23A
&:nth-of-type(3) .cg-category-title:before
background #FF7A2E
&:nth-of-type(4) .cg-category-title:before
background #FFC013
&:nth-of-type(5) .cg-category-title:before
background #FF525D
.cg-category-list
block()
background #FCFCFC
box-shadow shadow-bottom
.cg-category-item
block()
padding 0 h-gap-lg
box-sizing border-box
-webkit-tap-highlight-color transparent
.cg-category-item-inner
position relative
block()
height 100px
line-height 100px
font-size font-body-normal
color color-text-minor
hairline(bottom, color-border-base)
.md-icon
position absolute
right 0
top 50%
transform translateY(-50%)
&.close
text-align center
color color-text-link
&:before
display none
.md-cg-copyright
position fixed
left 0
bottom 20px
width 100%
text-align center
font-size font-minor-normal
font-weight 300
color color-text-caption
.slide-fade-enter-active
transition all .3s ease
.slide-fade-leave-active
transition all .3s ease
.slide-fade-enter
/* .slide-fade-leave-active below version 2.1.8 */
transform translate3d(0, -10px, 0)
opacity 0
.slide-fade-leave-to
opacity 0
</style>

View File

@ -1,46 +0,0 @@
export {default as Home} from './home.indemand.vue'
export {default as Category} from './category'
export {default as Button} from '../components/button/demo'
export {default as Icon} from '../components/icon/demo'
export {default as Popup} from '../components/popup/demo'
export {default as ActionBar} from '../components/action-bar/demo'
export {default as DropMenu} from '../components/drop-menu/demo'
export {default as Picker} from '../components/picker/demo'
export {default as TabBar} from '../components/tab-bar/demo'
export {default as Swiper} from '../components/swiper/demo'
export {default as Toast} from '../components/toast/demo'
export {default as Dialog} from '../components/dialog/demo'
export {default as Tip} from '../components/tip/demo'
export {default as Tabs} from '../components/tabs/demo'
export {default as Tag} from '../components/tag/demo'
export {default as InputItem} from '../components/input-item/demo'
export {default as NumberKeyboard} from '../components/number-keyboard/demo'
export {default as Stepper} from '../components/stepper/demo'
export {default as Steps} from '../components/steps/demo'
export {default as NoticeBar} from '../components/notice-bar/demo'
export {default as ResultPage} from '../components/result-page/demo'
export {default as ActionSheet} from '../components/action-sheet/demo'
export {default as Selector} from '../components/selector/demo'
export {default as Landscape} from '../components/landscape/demo'
export {default as ImageViewer} from '../components/image-viewer/demo'
export {default as ImageReader} from '../components/image-reader/demo'
export {default as TabPicker} from '../components/tab-picker/demo'
export {default as Field} from '../components/field/demo'
export {default as Switch} from '../components/switch/demo'
export {default as Agree} from '../components/agree/demo'
export {default as Radio} from '../components/radio/demo'
export {default as DatePicker} from '../components/date-picker/demo'
export {default as Captcha} from '../components/captcha/demo'
export {default as Codebox} from '../components/codebox/demo'
export {default as Cashier} from '../components/cashier/demo'
export {default as Chart} from '../components/chart/demo'
export {default as Amount} from '../components/amount/demo'
export {default as ActivityIndicator} from '../components/activity-indicator/demo'
export {default as CheckGroup} from '../components/check-group/demo'
export {default as CheckList} from '../components/check-list/demo'
export {default as CheckBox} from '../components/check-box/demo'
export {default as ScrollView} from '../components/scroll-view/demo'
export {default as Bill} from '../components/bill/demo'
export {default as WaterMark} from '../components/water-mark/demo'
export {default as Transition} from '../components/transition/demo' /* @init<%export {default as ${componentNameUpper}} from '../components/${componentName}/demo'%> */

View File

@ -1,94 +0,0 @@
<template>
<div class="md-home">
<div class="md-home-logo">
<img src="//manhattan.didistatic.com/static/manhattan/mand/docs/mand-logo-black.svg" alt="">
</div>
<div class="md-home-name" data-in-effect="fadeInLeftBig">
Mand Mobile
</div>
<div class="md-home-time">0%</div>
<h1 class="md-home-copyright">Produced By DiDi - FDC &times; MFE</h1>
</div>
</template>
<script>
export default {
data() {
return {
percent: 0,
}
},
mounted() {
$('.md-home-name')
.textillate()
.on('end.tlt')
this.timeCount(() => {
this.$router.replace('/category')
})
},
methods: {
timeCount(fn) {
const duration = 2000
const tick = 100
const per = 100 / (duration / tick)
let percent = 0
const time = setInterval(() => {
if (percent < 100) {
percent += per
$('.md-home-time').text(`${parseInt(percent)}%`)
} else {
clearInterval(time)
fn()
}
}, tick)
},
},
}
</script>
<style lang="stylus">
.md-home
position fixed
absolute-pos()
background color-bg-base
.md-home-logo
position absolute
top 30%
left 50%
transform translateX(-50%)
.md-home-name
position absolute
width 100%
top 45%
left 0
font-size font-heading-medium
font-weight 300
color color-text-minor
text-align center
span.word5
.char1, .char2, .char3
color color-text-base
span.word6 .char1
color color-text-base
span.word7 .char1
color color-text-base
.md-home-time
position absolute
width 100%
top 50%
left 0
font-size font-minor-normal
color color-text-minor
text-align center
.md-home-copyright
position fixed
left 0
bottom 20px
width 100%
text-align center
font-size font-minor-normal
font-weight 300
color color-text-caption
</style>

View File

@ -1,95 +0,0 @@
<template>
<div class="md-home">
<div class="md-home-logo">
<img src="//manhattan.didistatic.com/static/manhattan/mand/docs/mand-logo-black.svg" alt="">
</div>
<div class="md-home-name" data-in-effect="fadeInLeftBig">
Mand Mobile
</div>
<div class="md-home-time">0%</div>
<h1 class="md-home-copyright">Produced By DiDi - FDC &times; MFE</h1>
</div>
</template>
<script>
export default {
data() {
return {
percent: 0,
}
},
mounted() {
require.ensure(['./category'], () => {}, 'category')
$('.md-home-name')
.textillate()
.on('end.tlt')
this.timeCount(() => {
this.$router.replace('/category')
})
},
methods: {
timeCount(fn) {
const duration = 2000
const tick = 100
const per = 100 / (duration / tick)
let percent = 0
const time = setInterval(() => {
if (percent < 100) {
percent += per
$('.md-home-time').text(`${parseInt(percent)}%`)
} else {
clearInterval(time)
fn()
}
}, tick)
},
},
}
</script>
<style lang="stylus">
.md-home
position fixed
absolute-pos()
background color-bg-base
.md-home-logo
position absolute
top 30%
left 50%
transform translateX(-50%)
.md-home-name
position absolute
width 100%
top 45%
left 0
font-size font-heading-medium
font-weight 300
color color-text-minor
text-align center
span.word5
.char1, .char2, .char3
color color-text-base
span.word6 .char1
color color-text-base
span.word7 .char1
color color-text-base
.md-home-time
position absolute
width 100%
top 50%
left 0
font-size font-minor-normal
color color-text-minor
text-align center
.md-home-copyright
position fixed
left 0
bottom 20px
width 100%
text-align center
font-size font-minor-normal
font-weight 300
color color-text-caption
</style>

View File

@ -1,27 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Mand Mobile</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="format-detection" content="telephone=no,email=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<link rel="icon" href="//static.galileo.xiaojukeji.com/static/tms/other/mand-mobile-logo.png" type="image/x-icon">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/pace.css">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/fade-in-left-big.css">
<style>
*{margin:0;padding:0;list-style:0;-webkit-touch-callout:none;}
html{touch-action: manipulation;background:#f3f4f5;}
</style>
</head>
<body>
<div id="app"></div>
<script src="//img6.didistatic.com/static/tms/cdn/z/zepto/zepto/1.0.1/zepto.min.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/pace.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.lettering.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.textillate.js"></script>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,31 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Mand Mobile</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="format-detection" content="telephone=no,email=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<link rel="icon" href="//static.galileo.xiaojukeji.com/static/tms/other/mand-mobile-logo.png" type="image/x-icon">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/pace.css">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/fade-in-left-big.css">
<style>
*{margin:0;padding:0;list-style:0;-webkit-touch-callout:none;}
html{touch-action: manipulation;background:#f3f4f5;}
</style>
</head>
<body>
<div id="app"></div>
<script>
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
':35729/livereload.js?snipver=1"></' + 'script>')
</script>
<script src="//img6.didistatic.com/static/tms/cdn/z/zepto/zepto/1.0.1/zepto.min.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/pace.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.lettering.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.textillate.js"></script>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,39 +0,0 @@
// 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 VueRouter from 'vue-router'
import routes from './route.indemand'
import App from './App'
import '../components/_style/global.styl'
import './theme.custom.styl'
import {FastClick} from 'fastclick'
if ('ontouchstart' in window) {
FastClick.attach(document.body)
}
Vue.config.productionTip = false
Vue.use(VueRouter)
const isProd = process.env.NODE_ENV === 'production'
const router = new VueRouter({
mode: 'hash',
base: isProd ? '/mand-mobile/examples' : '',
routes,
})
router.afterEach(route => {
document.title = route.name ? `${route.name}-Mand Mobile` : 'Mand Mobile'
})
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App),
router,
})

View File

@ -1,46 +0,0 @@
import components from './components.json'
import * as demo from './demo-index.indemand'
const traverseComponents = (data, fn) => {
data.map(item =>
item.list && item.list.map(subItem =>
fn(subItem)
)
)
}
const registerRoute = (components) => {
const routes = []
traverseComponents(components, (component) => {
routes.push({
name: component.name,
path: component.path,
// require(`../components${component.path}/demo`).default
component: demo[component.name] || {},
meta: {
title: component.name || '',
description: component.text || ''
}
})
})
return routes
}
const routes = registerRoute(components)
routes.push({
path: '/home',
component: demo['Home']
})
routes.push({
path: '/category',
component: demo['Category']
})
routes.push({
path: '/',
redirect: '/home'
})
export default routes

View File

@ -1,126 +0,0 @@
<template>
<div class="mand">
<div class="md-example-wrapper">
<demo></demo>
</div>
</div>
</template>
<script>
import './assets/responsive'
import demo from '../components/radio/demo/'
export default {
name: 'app',
components: {
demo: () => import(`../components/${COMPONENT_NAME}/demo`),
},
}
</script>
<style lang="stylus">
block()
float left
width 100%
.mand
position relative
min-height 100%
max-width 750px
font-size-adjust none
-webkit-text-size-adjust 100%
-webkit-overflow-scrolling touch
font-family -apple-system,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","Microsoft JhengHei","Source Han Sans SC","Noto Sans CJK SC","Source Han Sans CN","Noto Sans SC","Source Han Sans TC","Noto Sans CJK TC","WenQuanYi Micro Hei",SimSun,sans-serif !important
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
background color-primary-background
.md-nav
position relative
display flex
padding 32px 20px
p
position relative
display inline-block
line-height 1
&.home
top 5px
width 36px
height 32px
i
position absolute
left 0
width 100%
height .04rem
background color-bg-mask
border-radius 2px
&:nth-of-type(1)
top 0
&:nth-of-type(2)
top 50%
width 70%
margin-top -.02rem
&:nth-of-type(3)
bottom 0
&.name
margin-left h-gap-lg
font-size font-heading-large
font-weight font-weight-medium
color color-text-base
&.name-zh
top 9px
margin-left h-gap-sm
font-size font-body-large
font-weight font-weight-normal
color color-text-minor
.md-example-wrapper
position relative
z-index 3
padding 20px
clearfix()
.md-example
.md-example-section
clearfix()
margin-bottom 30px
color color-text-base
.md-example-title
block()
font-size font-body-normal
font-weight font-weight-medium
a
margin-right 5px
background color-primary-tap
color #fff
padding 5px 10px
border-radius radius-normal
font-size font-minor-large
font-weight 300
line-height 28px
text-decoration none
.md-example-describe
block()
margin-top 15px
font-size font-minor-large
font-weight 300
color color-text-minor
.md-example-content
block()
position relative
margin-top 20px
box-sizing border-box
.md-dialog pre
width 100%
padding 20px 10px
box-sizing border-box
white-space pre-wrap
word-wrap break-word
font-size font-minor-normal
background color-primary-background
border-radius radius-normal
@media screen and (min-width: 749px)
.mand
margin-left -360px
left 50%
</style>

11
examples/weapp/App.vue Normal file
View File

@ -0,0 +1,11 @@
<script>
export default {
created () {}
}
</script>
<style lang="stylus">
page
padding 20px
box-sizing border-box
background #f3f4f5
</style>

15
examples/weapp/app.json Normal file
View File

@ -0,0 +1,15 @@
{
"pages": [
"category/page",
"button/demo/page",
"action-bar/demo/page",
"field/demo/page",
"switch/demo/page"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "black"
}
}

22
examples/weapp/main.js Normal file
View File

@ -0,0 +1,22 @@
import Vue from 'vue'
import App from './App.vue'
import Weapp from '../../platforms/weapp'
import Button from '../../components/button'
import ActionBar from '../../components/action-bar'
import Field from '../../components/field'
import FieldItem from '../../components/field/item'
import Switch from '../../components/switch'
Vue.config.productionTip = false
App.mpType = 'app'
Vue.use(Weapp)
Vue.component('mdButton', Button)
Vue.component('mdActionBar', ActionBar)
Vue.component('mdField', Field)
Vue.component('mdFieldItem', FieldItem)
Vue.component('mdSwitch', Switch)
const app = new Vue(App)
app.$mount()

View File

@ -0,0 +1,53 @@
<template>
<div class="md-cg">
<div
v-for="(category, i) in categoryData" :key="i"
class="cg-category"
:class="{'active': category.show}">
<div
class="cg-category-title"
:class="{'active': category.show}"
>
{{ category.name }}&nbsp;&nbsp;<span>{{ category.text }}</span>
</div>
<div class="cg-category-list">
<div
class="cg-category-item"
v-for="(item, j) in category.list"
:key="j"
@click="goToComponent(item.path)"
>
<div class="cg-category-item-inner">
{{ item.name }} - {{ item.text }}
</div>
</div>
<!-- <div class="cg-category-item" @click="toggleCategory(i, category)">
<div class="cg-category-item-inner close">收起</div>
</div> -->
</div>
</div>
</div>
</template>
<script>
import components from '../../../components.json'
export default {
data () {
return {
categoryData: components
}
},
mounted () {
},
methods: {
goToComponent (name) {
wx.navigateTo({ url: `..${name}/demo/page` })
}
}
}
</script>
<style lang="stylus">
</style>

View File

@ -0,0 +1,5 @@
import Vue from 'vue'
import App from './index'
const app = new Vue(App)
app.$mount()

148
examples/web/App.vue Normal file
View File

@ -0,0 +1,148 @@
<template>
<div class="mand">
<template v-if="isHome">
<router-view></router-view>
</template>
<template v-else>
<div class="md-nav">
<p class="home" @click="goToCategory"><i></i><i></i><i></i></p>
<p class="name" v-text="navTitle"></p>
<p class="name-zh" v-text="navSubTitle"></p>
</div>
<div class="md-example-wrapper">
<router-view></router-view>
</div>
</template>
</div>
</template>
<script>
import '../assets/responsive'
export default {
name: 'app',
computed: {
navTitle() {
return this.$route.name
},
navSubTitle() {
return this.$route.meta.description
},
isHome() {
const path = this.$route.path
return path === '/' || path === '/home' || path === '/category'
},
},
methods: {
goToCategory() {
this.$router.push('/category')
},
},
}
</script>
<style lang="stylus">
block()
float left
width 100%
.mand
position relative
min-height 100%
max-width 750px
font-size 28px
font-size-adjust none
-webkit-text-size-adjust 100%
-webkit-overflow-scrolling touch
font-family -apple-system,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","Microsoft JhengHei","Source Han Sans SC","Noto Sans CJK SC","Source Han Sans CN","Noto Sans SC","Source Han Sans TC","Noto Sans CJK TC","WenQuanYi Micro Hei",SimSun,sans-serif !important
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
background color-primary-background
.md-nav
position relative
display flex
padding 32px 20px
p
position relative
display inline-block
line-height 1
&.home
top 5px
width 36px
height 32px
i
position absolute
left 0
width 100%
height .04rem
background color-bg-mask
border-radius 2px
&:nth-of-type(1)
top 0
&:nth-of-type(2)
top 50%
width 70%
margin-top -.02rem
&:nth-of-type(3)
bottom 0
&.name
margin-left h-gap-lg
font-size font-heading-large
font-weight font-weight-medium
color color-text-base
&.name-zh
top 9px
margin-left h-gap-sm
font-size font-body-large
font-weight font-weight-normal
color color-text-minor
.md-example-wrapper
position relative
z-index 3
padding 20px
clearfix()
.md-example
.md-example-section
clearfix()
margin-bottom 30px
color color-text-base
.md-example-title
block()
font-size font-body-normal
font-weight font-weight-medium
a
margin-right 5px
background color-primary-tap
color #fff
padding 5px 10px
border-radius radius-normal
font-size font-minor-large
font-weight 300
line-height 28px
text-decoration none
.md-example-describe
block()
margin-top 15px
font-size font-minor-large
font-weight 300
color color-text-minor
.md-example-content
block()
position relative
margin-top 20px
box-sizing border-box
.md-dialog pre
width 100%
padding 20px 10px
box-sizing border-box
white-space pre-wrap
word-wrap break-word
font-size font-minor-normal
background color-primary-background
border-radius radius-normal
@media screen and (min-width: 749px)
.mand
margin-left -360px
left 50%
</style>

189
examples/web/category.vue Normal file
View File

@ -0,0 +1,189 @@
<template>
<div class="md-cg">
<h1 class="md-cg-title">Mand Mobile</h1>
<h1 class="md-cg-subtitle">面向金融场景的移动端Vue组件库</h1>
<section
v-for="(category, i) in components" :key="i"
class="cg-category"
:class="{'active': category.show}">
<div
class="cg-category-title"
:class="{'active': category.show}"
@click="toggleCategory(i, category)">
{{ category.name }}&nbsp;&nbsp;<span>{{ category.text }}</span>
<md-icon name="arrow-right" size="lg"></md-icon>
</div>
<transition name="slide-fade">
<div class="cg-category-list" v-show="category.show">
<div class="cg-category-item"
v-for="(item, j) in category.list"
:key="j"
@click="goToComponent(item.path)">
<div class="cg-category-item-inner">
{{ item.name }} - {{ item.text }}
<md-icon name="arrow-right" size="md"></md-icon>
</div>
</div>
<div class="cg-category-item" @click="toggleCategory(i, category)">
<div class="cg-category-item-inner close">收起</div>
</div>
</div>
</transition>
</section>
<h1 class="md-cg-copyright">Produced By DiDi - FDC &times; MFE</h1>
</div>
</template>
<script>
import components from '../components.json'
import Icon from '../../components/icon'
export default {
name: 'category',
components: {
[Icon.name]: Icon,
},
data() {
return {
components,
}
},
methods: {
toggleCategory(index, category) {
category.show = !category.show
this.$set(this.components, index, category)
},
goToComponent(path) {
this.$router.push(path)
},
},
}
</script>
<style lang="stylus" scoped>
block()
float left
width 100%
.md-cg
padding 20px 20px 50px
clearfix()
.md-cg-title
block()
margin 20px 0
font-size font-heading-large
font-weight font-weight-normal
color color-text-minor
span
color color-text-base
.md-cg-subtitle
block()
margin-bottom 30px
font-size font-body-normal
font-weight 300
color color-text-minor
.cg-category
block()
position relative
z-index 3
height 120px
margin-bottom 20px
border-radius border-width-base
transform translate(0, 0)
&.active
height auto
// box-shadow shadow-bottom
.cg-category-title
position relative
z-index 2
block()
height 120px
padding 0 h-gap-lg
line-height 120px
font-size font-heading-normal
// font-weight font-weight-medium
color color-text-base
box-sizing border-box
box-shadow shadow-bottom
background color-bg-base
overflow hidden
span
font-size font-body-large
color color-text-minor
.md-icon
position absolute
right h-gap-lg
top 50%
transform translateY(-50%)
transition transform .3s ease-in-out-quint
&.active .md-icon
transform translateY(-50%) rotate(90deg)
&:before
content ""
position absolute
left 0
top 0
width 4px
height 100%
border-radius border-width-base
// display none
&:nth-of-type(1) .cg-category-title:before
background #5E83DD
&:nth-of-type(2) .cg-category-title:before
background #83D23A
&:nth-of-type(3) .cg-category-title:before
background #FF7A2E
&:nth-of-type(4) .cg-category-title:before
background #FFC013
&:nth-of-type(5) .cg-category-title:before
background #FF525D
.cg-category-list
block()
background #FCFCFC
box-shadow shadow-bottom
.cg-category-item
block()
padding 0 h-gap-lg
box-sizing border-box
-webkit-tap-highlight-color transparent
.cg-category-item-inner
position relative
block()
height 100px
line-height 100px
font-size font-body-normal
color color-text-minor
hairline(bottom, color-border-base)
.md-icon
position absolute
right 0
top 50%
transform translateY(-50%)
&.close
text-align center
color color-text-link
&:before
display none
.md-cg-copyright
position fixed
left 0
bottom 20px
width 100%
text-align center
font-size font-minor-normal
font-weight 300
color color-text-caption
.slide-fade-enter-active
transition all .3s ease
.slide-fade-leave-active
transition all .3s ease
.slide-fade-enter
/* .slide-fade-leave-active below version 2.1.8 */
transform translate3d(0, -10px, 0)
opacity 0
.slide-fade-leave-to
opacity 0
</style>

View File

@ -1,20 +1,20 @@
export {default as Home} from './home.vue'
export const Category = r => require.ensure([], () => r(require('./category')), 'category')
export const Button = r => require.ensure([], () => r(require('../components/button/demo')), 'button')
export const Icon = r => require.ensure([], () => r(require('../components/icon/demo')), 'icon')
export const Popup = r => require.ensure([], () => r(require('../components/popup/demo')), 'popup')
export const ActionBar = r => require.ensure([], () => r(require('../components/action-bar/demo')), 'action-bar')
export const DropMenu = r => require.ensure([], () => r(require('../components/drop-menu/demo')), 'drop-menu')
export const Picker = r => require.ensure([], () => r(require('../components/picker/demo')), 'picker')
export const TabBar = r => require.ensure([], () => r(require('../components/tab-bar/demo')), 'tab-bar')
export const Swiper = r => require.ensure([], () => r(require('../components/swiper/demo')), 'swiper')
export const Toast = r => require.ensure([], () => r(require('../components/toast/demo')), 'toast')
export const Dialog = r => require.ensure([], () => r(require('../components/dialog/demo')), 'dialog')
export const Tip = r => require.ensure([], () => r(require('../components/tip/demo')), 'tip')
export const Tabs = r => require.ensure([], () => r(require('../components/tabs/demo')), 'tabs')
export const Tag = r => require.ensure([], () => r(require('../components/tag/demo')), 'tag')
export const InputItem = r => require.ensure([], () => r(require('../components/input-item/demo')), 'input-item')
export const Button = r => require.ensure([], () => r(require('../../components/button/demo')), 'button')
export const Icon = r => require.ensure([], () => r(require('../../components/icon/demo')), 'icon')
export const Popup = r => require.ensure([], () => r(require('../../components/popup/demo')), 'popup')
export const ActionBar = r => require.ensure([], () => r(require('../../components/action-bar/demo')), 'action-bar')
export const DropMenu = r => require.ensure([], () => r(require('../../components/drop-menu/demo')), 'drop-menu')
export const Picker = r => require.ensure([], () => r(require('../../components/picker/demo')), 'picker')
export const TabBar = r => require.ensure([], () => r(require('../../components/tab-bar/demo')), 'tab-bar')
export const Swiper = r => require.ensure([], () => r(require('../../components/swiper/demo')), 'swiper')
export const Toast = r => require.ensure([], () => r(require('../../components/toast/demo')), 'toast')
export const Dialog = r => require.ensure([], () => r(require('../../components/dialog/demo')), 'dialog')
export const Tip = r => require.ensure([], () => r(require('../../components/tip/demo')), 'tip')
export const Tabs = r => require.ensure([], () => r(require('../../components/tabs/demo')), 'tabs')
export const Tag = r => require.ensure([], () => r(require('../../components/tag/demo')), 'tag')
export const InputItem = r => require.ensure([], () => r(require('../../components/input-item/demo')), 'input-item')
export const NumberKeyboard = r =>
require.ensure([], () => r(require('../components/number-keyboard/demo')), 'number-keyboard')
export const Stepper = r => require.ensure([], () => r(require('../components/stepper/demo')), 'stepper')
@ -44,4 +44,5 @@ export const CheckBox = r => require.ensure([], () => r(require('../components/
export const ScrollView = r => require.ensure([], () => r(require('../components/scroll-view/demo')), 'scroll-view')
export const Bill = r => require.ensure([], () => r(require('../components/bill/demo')), 'bill')
export const WaterMark = r => require.ensure([], () => r(require('../components/water-mark/demo')), 'water-mark')
export const Transition = r => require.ensure([], () => r(require('../components/transition/demo')), 'transition') /* @init<%export const ${componentNameUpper} = r => require.ensure([], () => r(require('../components/${componentName}/demo')), '${componentName}')%> */
export const Transition = r => require.ensure([], () => r(require('../components/transition/demo')), 'transition')
/* @init<%export const ${componentNameUpper} = r => require.ensure([], () => r(require('../components/${componentName}/demo')), '${componentName}')%> */

95
examples/web/home.vue Normal file
View File

@ -0,0 +1,95 @@
<template>
<div class="md-home">
<div class="md-home-logo">
<img src="//manhattan.didistatic.com/static/manhattan/mand/docs/mand-logo-black.svg" alt="">
</div>
<div class="md-home-name" data-in-effect="fadeInLeftBig">
Mand Mobile
</div>
<div class="md-home-time">0%</div>
<h1 class="md-home-copyright">Produced By DiDi - FDC &times; MFE</h1>
</div>
</template>
<script>
export default {
data() {
return {
percent: 0,
}
},
mounted() {
require.ensure(['./category'], () => {}, 'category')
$('.md-home-name')
.textillate()
.on('end.tlt')
this.timeCount(() => {
this.$router.replace('/category')
})
},
methods: {
timeCount(fn) {
const duration = 2000
const tick = 100
const per = 100 / (duration / tick)
let percent = 0
const time = setInterval(() => {
if (percent < 100) {
percent += per
$('.md-home-time').text(`${parseInt(percent)}%`)
} else {
clearInterval(time)
fn()
}
}, tick)
},
},
}
</script>
<style lang="stylus">
.md-home
position fixed
absolute-pos()
background color-bg-base
.md-home-logo
position absolute
top 30%
left 50%
transform translateX(-50%)
.md-home-name
position absolute
width 100%
top 45%
left 0
font-size font-heading-medium
font-weight 300
color color-text-minor
text-align center
span.word5
.char1, .char2, .char3
color color-text-base
span.word6 .char1
color color-text-base
span.word7 .char1
color color-text-base
.md-home-time
position absolute
width 100%
top 50%
left 0
font-size font-minor-normal
color color-text-minor
text-align center
.md-home-copyright
position fixed
left 0
bottom 20px
width 100%
text-align center
font-size font-minor-normal
font-weight 300
color color-text-caption
</style>

27
examples/web/index.html Normal file
View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Mand Mobile</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<meta name="format-detection" content="telephone=no,email=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-touch-fullscreen" content="yes">
<link rel="icon" href="//static.galileo.xiaojukeji.com/static/tms/other/mand-mobile-logo.png" type="image/x-icon">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/pace.css">
<link rel="stylesheet" href="//manhattan.didistatic.com/static/manhattan/mand/fade-in-left-big.css">
<style>
*{margin:0;padding:0;list-style:0;-webkit-touch-callout:none;}
html{touch-action: manipulation;background:#f3f4f5;}
</style>
</head>
<body>
<div id="app"></div>
<script src="//img6.didistatic.com/static/tms/cdn/z/zepto/zepto/1.0.1/zepto.min.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/pace.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.lettering.js"></script>
<script src="//manhattan.didistatic.com/static/manhattan/mand/jquery.textillate.js"></script>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -5,8 +5,8 @@ import VueRouter from 'vue-router'
import routes from './route'
import App from './App'
import FastClick from 'fastclick'
import '../components/_style/global.styl'
import './theme.custom.styl'
import '../../components/_style/global.styl'
import '../theme.custom.styl'
if ('ontouchstart' in window) {
FastClick.attach(document.body)

View File

@ -1,4 +1,4 @@
import components from './components.json'
import components from '../components.json'
import * as demo from './demo-index'
const traverseComponents = (data, fn) => {

View File

@ -0,0 +1,126 @@
<template>
<div class="mand">
<div class="md-example-wrapper">
<demo></demo>
</div>
</div>
</template>
<script>
import '../assets/responsive'
import demo from '../../components/radio/demo/'
export default {
name: 'app',
components: {
demo: () => import(`../../components/${COMPONENT_NAME}/demo`),
},
}
</script>
<style lang="stylus">
block()
float left
width 100%
.mand
position relative
min-height 100%
max-width 750px
font-size-adjust none
-webkit-text-size-adjust 100%
-webkit-overflow-scrolling touch
font-family -apple-system,"Helvetica Neue",Arial,"PingFang SC","Hiragino Sans GB",STHeiti,"Microsoft YaHei","Microsoft JhengHei","Source Han Sans SC","Noto Sans CJK SC","Source Han Sans CN","Noto Sans SC","Source Han Sans TC","Noto Sans CJK TC","WenQuanYi Micro Hei",SimSun,sans-serif !important
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
background color-primary-background
.md-nav
position relative
display flex
padding 32px 20px
p
position relative
display inline-block
line-height 1
&.home
top 5px
width 36px
height 32px
i
position absolute
left 0
width 100%
height .04rem
background color-bg-mask
border-radius 2px
&:nth-of-type(1)
top 0
&:nth-of-type(2)
top 50%
width 70%
margin-top -.02rem
&:nth-of-type(3)
bottom 0
&.name
margin-left h-gap-lg
font-size font-heading-large
font-weight font-weight-medium
color color-text-base
&.name-zh
top 9px
margin-left h-gap-sm
font-size font-body-large
font-weight font-weight-normal
color color-text-minor
.md-example-wrapper
position relative
z-index 3
padding 20px
clearfix()
.md-example
.md-example-section
clearfix()
margin-bottom 30px
color color-text-base
.md-example-title
block()
font-size font-body-normal
font-weight font-weight-medium
a
margin-right 5px
background color-primary-tap
color #fff
padding 5px 10px
border-radius radius-normal
font-size font-minor-large
font-weight 300
line-height 28px
text-decoration none
.md-example-describe
block()
margin-top 15px
font-size font-minor-large
font-weight 300
color color-text-minor
.md-example-content
block()
position relative
margin-top 20px
box-sizing border-box
.md-dialog pre
width 100%
padding 20px 10px
box-sizing border-box
white-space pre-wrap
word-wrap break-word
font-size font-minor-normal
background color-primary-background
border-radius radius-normal
@media screen and (min-width: 749px)
.mand
margin-left -360px
left 50%
</style>

View File

@ -3,7 +3,7 @@
import Vue from 'vue'
import FastClick from 'fastclick'
import App from './single-component-app'
import '../components/_style/global.styl'
import '../../components/_style/global.styl'
if ('ontouchstart' in window) {
FastClick.attach(document.body)

View File

@ -23,15 +23,14 @@
],
"scripts": {
"dev": "webpack-dashboard -m -- node build/webpack/dev-server",
"dev:rollup": "node build/rollup/dev-server.rollup",
"dev:site": "cd site && npm start",
"dev:weapp": "rm -rf dist/* && cross-env NODE_ENV=weapp webpack-dashboard -m -- node build/webpack/dev-server",
"create": "node build/component-init.js",
"cz": "git-cz",
"clean": "rm -rf ./lib && rm -rf ./lib-vw && rm -rf ./docs/examples",
"build": "npm run clean && npm run build:components && npm run build:mand-mobile && npm run build:mand-mobile-special && node build/rollup/build-vw-responsive",
"build:site": "cd site && npm run generate && npm run build",
"prebuild:example": "npm run build",
"build:example": "cross-env NODE_ENV=production BUILD_TYPE=example node build/rollup/build-example.rollup",
"build:mand-mobile": "cross-env NODE_ENV=production node build/rollup/build-mand-mobile.rollup",
"build:mand-mobile-special": "cross-env NODE_ENV=production BUILD_TYPE=special node build/rollup/build-mand-mobile.rollup",
"build:components": "cross-env NODE_ENV=production && node build/rollup/build-component.rollup",
@ -96,7 +95,7 @@
"commander": "^2.12.2",
"commitizen": "^2.9.6",
"connect-history-api-fallback": "^1.3.0",
"copy-webpack-plugin": "^4.0.1",
"copy-webpack-plugin": "^4.5.1",
"cross-env": "^5.0.1",
"cross-spawn": "^5.0.1",
"css-loader": "^0.28.0",
@ -118,7 +117,7 @@
"eslint-plugin-standard": "^3.0.1",
"eventsource-polyfill": "^0.9.6",
"express": "^4.14.1",
"extract-text-webpack-plugin": "^3.0.0",
"extract-text-webpack-plugin": "^3.0.2",
"fastclick": "^1.0.6",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
@ -154,6 +153,10 @@
"mime-types": "^2.1.17",
"mocha": "^3.2.0",
"moment": "^2.19.1",
"mpvue": "^1.0.13",
"mpvue-loader": "^1.1.2",
"mpvue-template-compiler": "^1.0.13",
"mpvue-webpack-target": "^1.0.0",
"needle": "^2.0.1",
"nib": "^1.1.2",
"nightwatch": "^0.9.12",
@ -163,12 +166,14 @@
"phantomjs-prebuilt": "^2.1.16",
"portfinder": "^1.0.13",
"postcss-loader": "^2.0.8",
"postcss-mpvue-wxss": "^1.0.0",
"postcss-pixel-to-viewport": "^1.0.2",
"postcss-pxtorem": "^4.0.1",
"postcss-url": "^7.3.1",
"poststylus": "^1.0.0",
"prettier": "^1.5.3",
"prettier": "~1.12.1",
"progress-bar-webpack-plugin": "^1.10.0",
"px2rpx-loader": "^0.1.10",
"recursive-copy": "^2.0.8",
"rimraf": "^2.6.0",
"rollup": "^0.54.0",
@ -210,12 +215,14 @@
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.4.2",
"vueify": "^9.4.1",
"webpack": "^3.6.0",
"webpack": "^3.11.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dashboard": "^1.0.2",
"webpack-dev-middleware": "^1.12.0",
"webpack-dev-middleware-hard-disk": "^1.12.1",
"webpack-hot-middleware": "^2.18.2",
"webpack-merge": "^4.1.0",
"webpack-mpvue-asset-plugin": "^0.1.1",
"word-wrap": "^1.2.3",
"yargs": "^11.0.0"
},

View File

@ -0,0 +1,73 @@
<template>
<div class="md-scroll-view-private">
<scroll-view
class="scroll-view-wrapper"
:scroll-x="scrollingX"
:scroll-y="scrollingY"
:scroll-top="scrollTop"
:scroll-left="scrollLeft"
:scroll-with-animation="scrollWithAnimation"
:lower-threshold="endReachedThreshold"
@scroll="$_onScroll"
@scrolltolower="$_onScrollEnd"
>
<div class="scroll-view-container">
<slot></slot>
</div>
</scroll-view>
</div>
</template>
<script>
export default {
name: 'md-scroll-view-private',
props: {
scrollingX: {
type: Boolean,
default: true,
},
scrollingY: {
type: Boolean,
default: true,
},
endReachedThreshold: {
type: Number,
default: 0,
},
},
data () {
return {
scrollTop: 0,
scrollLeft: 0,
scrollWithAnimation: false
}
},
methods: {
$_onScroll (e) {
this.$emit('scroll', e.mp.detail)
},
$_onScrollEnd () {
console.log('xxxxx')
this.$emit('endReached')
},
scrollTo (left = 0, top = 0, animate = false) {
this.scrollWithAnimation = animate
this.$nextTick(() => {
this.scrollLeft = left
this.scrollTop = top
})
}
}
}
</script>
<style lang="stylus">
.md-scroll-view-private .scroll-view-wrapper
width 100%
height 100%
::-webkit-scrollbar
width 0
height 0
color transparent
</style>

View File

@ -0,0 +1,150 @@
<template>
<div
class="md-transition-private"
:class="transitionClass"
@animationend="$_onTransitionendEnd"
@transitionend="$_onTransitionendEnd"
>
<template v-if="keepAlive">
<div class="transition-content" v-show="contentShow">
<slot></slot>
</div>
</template>
<template v-else>
<div class="transition-content" v-if="contentShow">
<slot :show="value"></slot>
</div>
</template>
</div>
</template>
<script>
export default {
name: 'md-transition-private',
props: {
value: {
type: Boolean,
default: false
},
name: {
type: String,
default: ''
},
keepAlive: {
type: Boolean,
default: false
},
},
data () {
return {
transitionClass: [],
contentShow: false,
whenTransitionEnds: null
}
},
computed: {
isMiniProgram () {
return !!(this.$root && this.$root.$mp)
},
createAnimation () {
return wx && wx.createAnimation
}
},
watch: {
value (val) {
if (val) {
this.$_enterTransition()
} else {
this.$_leaveTransition()
}
}
},
mounted () {
if (this.value) {
this.contentShow = true
}
},
methods: {
$_enterTransition () {
if (!this.isMiniProgram || !this.name) {
return
}
const animationClass = this.$_getTransitionClass(this.name)
const startClass = animationClass.enterClass
const activeClass = animationClass.enterActiveClass
const toClass = animationClass.enterToClass
this.$emit('beforeEnter')
this.$_addTransitionClass(startClass)
setTimeout(() => {
this.$_addTransitionClass(activeClass)
this.$nextTick(() => {
this.$_removeTransitionClass(startClass)
this.$_addTransitionClass(toClass)
this.whenTransitionEnds = () => {
this.$_removeTransitionClass(toClass)
this.$_removeTransitionClass(activeClass)
this.$emit('afterEnter')
this.whenTransitionEnds = null
}
})
}, 50)
this.contentShow = true
this.$emit('enter')
},
$_leaveTransition () {
if (!this.isMiniProgram || !this.name) {
return
}
const animationClass = this.$_getTransitionClass(this.name)
const startClass = animationClass.leaveClass
const activeClass = animationClass.leaveActiveClass
const toClass = animationClass.leaveToClass
this.$emit('beforeLeave')
this.$_addTransitionClass(startClass)
this.$_addTransitionClass(activeClass)
this.$nextTick(() => {
this.$_removeTransitionClass(startClass)
this.$_addTransitionClass(toClass)
this.whenTransitionEnds = () => {
this.$_removeTransitionClass(toClass)
this.$_removeTransitionClass(activeClass)
this.$emit('afterLeave')
this.contentShow = false
this.whenTransitionEnds = null
}
})
this.$emit('leave')
},
$_getTransitionClass (name) {
return {
enterClass: `${name}-enter`,
enterToClass: `${name}-enter-to`,
enterActiveClass: `${name}-enter-active`,
leaveClass: `${name}-leave`,
leaveToClass: `${name}-leave-to`,
leaveActiveClass: `${name}-leave-active`
}
},
$_addTransitionClass (className) {
const index = this.transitionClass.indexOf(className)
if (!~index) {
this.transitionClass.push(className)
}
},
$_removeTransitionClass (className) {
const index = this.transitionClass.indexOf(className)
if (~index) {
this.transitionClass.splice(index, 1)
}
},
$_onTransitionendEnd () {
this.whenTransitionEnds && this.whenTransitionEnds()
}
}
}
</script>

19
platforms/weapp/index.js Normal file
View File

@ -0,0 +1,19 @@
import transition from './components/transition'
import scrollView from './components/scroll-view'
import dom from './modules/document'
const install = function (Vue) {
if (!Vue || install.installed) {
return
}
Vue.component('mdTransitionPrivate', transition)
Vue.component('mdScrollViewPrivate', scrollView)
Vue.prototype.$document = dom
Vue.prototype.$element = dom
}
export default {
install
}

60
platforms/weapp/loader.js Normal file
View File

@ -0,0 +1,60 @@
const fs = require('fs')
/**
* 为mand-mobile支持mpvue增加一个loader
* 作用
* 1通过特定注释格式化template
* 2将createDemoModule格式化为mpvue支持代码
*
* @param source
* @return {*}
*/
module.exports = function (source) {
// 判断是否有注入
let matches = source.match(/\.\.\.createDemoModule\(.*\)/)
if (!matches) {
return source
}
// 匹配demo个数
let demos = matches[0]
demos = demos.match(/\[(.*)\]/)
if (!demos) {
return source
}
demos = demos[1].split(',').map(demo => demo.trim())
let template_str = ''
let components_str = 'components: {'
demos.forEach((demo, index) => {
// 获取demo的title和describe
let demo_url = this.resource.replace('index.vue', `cases/demo${index}.vue`)
const file = fs.readFileSync(demo_url, 'utf8')
let title = '基础'
let describe = ''
if (typeof file === 'string') {
// 匹配demo文件中的title和describe
let title_match = file.match(/title:[\s']*(.*)'/)
title_match && (title = title_match[1])
let describe_match = file.match(/describe:[\s']*(.*)'/)
describe_match && (describe = describe_match[1])
}
// 拼接template字符串
template_str +=
`
<section class="md-example-section">
<div class="md-example-title">${title}</div>
<div class="md-example-describe">${describe}</div>
<div class="md-example-content">
<demo${index}></demo${index}>
</div>
</section>
`
// 拼接componets字符串
components_str += `Demo${index},`
})
// 通过指定字符串替换template
let res = source.replace('<!-- weapp inject -->', template_str)
// 替换createDemoModule
components_str += '},'
res = res.replace(/\.\.\.createDemoModule\(.*\)/, components_str)
return res
}

View File

@ -0,0 +1,40 @@
/**
* 小程序中不存在Dom
*/
class Dom {
constructor () {
this.documentElement = {}
this.readyState = 'complete / 完成\n'
}
querySelector () {
return new Dom()
}
getElementById () {
return new Dom()
}
createElement () {
return new Dom()
}
getElementsByTagName () {
return [new Dom()]
}
addEventListener () {}
removeEventListener () {}
}
class Document extends Dom {
constructor () {
super()
this.body = {}
}
}
export const dom = new Dom()
export default new Document()

View File

@ -0,0 +1 @@
export default document

1
platforms/web/index.js Normal file
View File

@ -0,0 +1 @@
export { default as mdDocument } from './Document'

View File

@ -7,6 +7,7 @@ module.exports = (ctx) => ({
'postcss-url': {url: 'inline'},
'cssnano': { zindex: false, mergeIdents: false, discardUnused: false, autoprefixer: false, reduceIdents: false
},
'autoprefixer': { browsers: browserslist }
'autoprefixer': { browsers: browserslist },
'postcss-mpvue-wxss': {}
}
})