vant components

This commit is contained in:
cookfront 2017-04-19 17:33:44 +08:00
commit 63c549d651
346 changed files with 25710 additions and 0 deletions

9
.babelrc Normal file
View File

@ -0,0 +1,9 @@
{
"presets": [
"es2015"
],
"plugins": [
"transform-runtime",
"transform-vue-jsx"
]
}

23
.editorconfig Normal file
View File

@ -0,0 +1,23 @@
root = true
[*]
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.js]
indent_size = 2
[*.vue]
indent_size = 2
[*.css]
indent_size = 2
[Makefile]
indent_style = tab

4
.eslintignore Normal file
View File

@ -0,0 +1,4 @@
lib/
dist/
node_modules/
build/**/*.js

148
.eslintrc.js Normal file
View File

@ -0,0 +1,148 @@
module.exports = {
parserOptions: {
ecmaVersion: 6,
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true
},
sourceType: 'module'
},
env: {
es6: true,
node: true,
mocha: true
},
plugins: ['vue'],
globals: {
expect: true,
sinon: true,
zanui: true,
document: false,
navigator: false,
window: false,
require: true,
FileReader: true,
File: true
},
rules: {
'accessor-pairs': 2,
'arrow-spacing': [2, { 'before': true, 'after': true }],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', { 'allowSingleLine': true }],
'camelcase': [2, { 'properties': 'always' }],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, { 'before': false, 'after': true }],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': [2, 'allow-null'],
'generator-star-spacing': [2, { 'before': true, 'after': true }],
'handle-callback-err': [2, '^(err|error)$' ],
'indent': [2, 2, { 'SwitchCase': 1 }],
'jsx-quotes': [2, 'prefer-double'],
'key-spacing': [2, { 'beforeColon': false, 'afterColon': true }],
'keyword-spacing': [2, { 'before': true, 'after': true }],
'new-cap': [2, { 'newIsCap': true, 'capIsNew': false }],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 2,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, { 'allowLoop': false, 'allowSwitch': false }],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, { 'max': 1 }],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, { 'defaultAssignment': false }],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, { 'vars': 'all', 'args': 'none' }],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, { 'initialized': 'never' }],
'operator-linebreak': [2, 'after', { 'overrides': { '?': 'before', ':': 'before' } }],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', { 'avoidEscape': true, 'allowTemplateLiterals': true }],
'semi': [2, 'always'],
'semi-spacing': [2, { 'before': false, 'after': true }],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, { 'words': true, 'nonwords': false }],
'spaced-comment': [2, 'always', { 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] }],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', { objectsInObjects: false }],
'array-bracket-spacing': [2, 'never'],
'vue/jsx-uses-vars': 2
}
}

0
CHANGELOG.md Normal file
View File

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
.PHONY: test
usage = "\
Usage: make <option> \n\n\
init componentname makefile \n\n\
\n"
default:
@echo $(usage)
init:
node build/bin/init.js $(filter-out $@,$(MAKECMDGOALS))
dev:
npm run dev
test:
npm run test

61
README.md Normal file
View File

@ -0,0 +1,61 @@
<p>
<a href="https://github.com/youzan/"><img alt="有赞logo" width="36px" src="https://img.yzcdn.cn/public_files/2017/02/09/e84aa8cbbf7852688c86218c1f3bbf17.png" alt="youzan">
</p></a>
<p align="center">
<img alt="项目logo" src="https://img.yzcdn.cn/public_files/2017/02/06/ee0ebced79a80457d77ce71c7d414c74.png">
</p>
<p align="center">Vue Mobile UI at YouZan</p>
## 一、安装
```shell
ynpm install @youzan/zanui-vue
```
## 二、使用
### 1. 导入所有组件
```javascript
import Vue from 'vue';
import ZanUI from '@youzan/zanui-vue';
// 你也可以使用自己的主题
import '@youzan/zanui-vue/lib/zanui-css/index.css';
Vue.use(ZanUI);
```
### 2. 按需导入组件
```javascript
import Vue from 'vue';
import { Button, Cell } from '@youzan/zanui-vue';
import '@youzan/zanui-vue/lib/zanui-css/button.css';
import '@youzan/zanui-vue/lib/zanui-css/cell.css';
Vue.component(Button.name, Button);
Vue.component(Cell.name, Cell);
```
## 三、开发
### 1. 新建一个组件
```shell
make init componentName
```
### 2. 示例预览
`docs/nav.config.json`文件里合适的地方写入组件声明根据组件类型JS组件CSS组件Form等进行区分 在`docs/examples-docs`目录里新建同名的md文件`waterfall.md`在项目的根目录下执行以下命令启动server
```shell
make dev
```
浏览器访问[http://localhost:8080](http://localhost:8080)就可以看到所有组件的示例了。
## 四、开源协议
本项目基于 [MIT](https://zh.wikipedia.org/wiki/MIT%E8%A8%B1%E5%8F%AF%E8%AD%89) 协议,请自由地享受和参与开源。

25
build/bin/build-all.js Normal file
View File

@ -0,0 +1,25 @@
'use strict';
const components = require('../../components.json');
const execSync = require('child_process').execSync;
const existsSync = require('fs').existsSync;
const path = require('path');
const componentPaths = [];
delete components.font;
Object.keys(components).forEach(key => {
const filePath = path.join(__dirname, `../../packages/${key}/webpack.conf.js`);
if (existsSync(filePath)) {
componentPaths.push(`packages/${key}/webpack.conf.js`);
}
});
const paths = componentPaths.join(',');
const cli = `node_modules/.bin/webpack build -c ${paths} -p`;
execSync(cli, {
stdio: 'inherit'
});

75
build/bin/build-entry.js Normal file
View File

@ -0,0 +1,75 @@
var Components = require('../../components.json');
var fs = require('fs');
var render = require('json-templater/string');
var uppercamelcase = require('uppercamelcase');
var path = require('path');
var chalk = require('chalk');
var OUTPUT_PATH = path.join(__dirname, '../../src/index.js');
var IMPORT_TEMPLATE = 'import {{name}} from \'../packages/{{package}}/index.js\';';
var ISNTALL_COMPONENT_TEMPLATE = ' Vue.component({{name}}.name, {{name}});';
var MAIN_TEMPLATE = `{{include}}
const install = function(Vue) {
if (install.installed) return;
{{install}}
};
// auto install
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
module.exports = {
install,
version: '{{version}}',
{{list}}
};
`;
delete Components.font;
var ComponentNames = Object.keys(Components);
var includeComponentTemplate = [];
var installTemplate = [];
var listTemplate = [];
ComponentNames.forEach(name => {
var componentName = uppercamelcase(name);
includeComponentTemplate.push(render(IMPORT_TEMPLATE, {
name: componentName,
package: name
}));
if ([
// directives
'Lazyload',
'Waterfall',
// services
'Dialog',
'Toast',
'ImagePreview'
].indexOf(componentName) === -1) {
installTemplate.push(render(ISNTALL_COMPONENT_TEMPLATE, {
name: componentName,
component: name
}));
}
listTemplate.push(` ${componentName}`);
});
var template = render(MAIN_TEMPLATE, {
include: includeComponentTemplate.join('\n'),
install: installTemplate.join('\n'),
version: process.env.VERSION || require('../../package.json').version,
list: listTemplate.join(',\n')
});
fs.writeFileSync(OUTPUT_PATH, template);
console.log(chalk.green('[build entry] DONE:' + OUTPUT_PATH));

48
build/bin/init.js Normal file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env node
const ch = require('child_process');
const gulp = require('gulp');
const runSequence = require('run-sequence');
const gutil = require('gulp-util');
const fileSave = require('file-save');
const path = require('path');
const exec = ch.exec;
if (!process.argv[2]) {
console.error('[组件名]必填.');
process.exit(1);
}
const name = process.argv[2];
// 项目规范文件拷贝
gulp.task('copy', function(callback) {
gutil.log(gutil.colors.yellow('-------> 开始初始化'));
exec('cd packages && git clone git@gitlab.qima-inc.com:fe/vue-seed.git ' + name, function(err, stdout, stderr) {
gutil.log('-------> 拉取 vue-seed');
exec('rm -rf ./packages/' + name + '/.git', function(err, stdout, stderr) {
gutil.log('-------> ' + name + '组件初始化成功');
callback();
});
});
});
// 添加到 components.json
gulp.task('addComponents', function(callback) {
const componentsFile = require('../../components.json');
if (componentsFile[name]) {
console.error(`${name} 已存在.`);
process.exit(1);
}
componentsFile[name] = `./packages/${name}/index.js`;
fileSave(path.join(__dirname, '../../components.json'))
.write(JSON.stringify(componentsFile, null, ' '), 'utf8')
.end('\n');
gutil.log('-------> components.json文件更新成功');
gutil.log(gutil.colors.yellow('-------> 请无视下面的make报错'));
});
runSequence('copy', 'addComponents');

114
build/genExamples.js Normal file
View File

@ -0,0 +1,114 @@
var markdownIt = require('markdown-it');
var markdownItContainer = require('markdown-it-container');
var fs = require('fs');
var path = require('path');
var cheerio = require('cheerio');
var chalk = require('chalk');
var decamelize = require('decamelize');
var striptags = require('./strip-tags');
var navs = require('../docs/src/nav.config.js');
navs = navs['zh-CN'];
var parser = markdownIt('default', {
html: true
});
var renderVueTemplate = function(html, componentTitle) {
var $ = cheerio.load(html, {
decodeEntities: false,
lowerCaseAttributeNames: false,
lowerCaseTags: false
});
var output = {
style: $.html('style'),
script: $.html('script'),
'example-block': $.html('example-block')
};
var result;
$('style').remove();
$('script').remove();
var script = '';
if (output.script) {
script = output.script.replace('<script>', '<script>\nimport Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);');
} else {
script = '<script>\nimport Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>';
}
var componentName = componentTitle.split(' ')[0];
componentName = decamelize(componentName, '-');
result = `<template><section class="demo-${componentName}"><h1 class="demo-title">${componentTitle}</h1>` + output['example-block'] + '</section></template>\n' +
output.style + '\n' +
script;
return result;
};
function convert(str) {
str = str.replace(/(&#x)(\w{4});/gi, function($0) {
return String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16));
});
return str;
}
parser.use(markdownItContainer, 'demo', {
validate: function(params) {
return params.trim().match(/^demo\s*(.*)$/);
},
render: function(tokens, idx) {
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
if (tokens[idx].nesting === 1) {
var description = (m && m.length > 1) ? m[1] : '';
var content = tokens[idx + 1].content;
var html = convert(striptags.strip(content, ['script', 'style']));
return `<example-block title="${description}">
${html}
</example-block>\n`;
}
return '';
}
});
var docsDir = path.resolve(__dirname, '../docs');
var components = [];
for (var i = 0; i < navs.length; i++) {
var navItem = navs[i];
if (!navItem.showInMobile) continue;
if (!navItem.groups) {
components.push(navs[i]);
} else {
for (var j = 0; j < navItem.groups.length; j++) {
components = components.concat(navItem.groups[j].list);
}
}
}
for (var i = 0; i < components.length; i++) {
var item = components[i];
var itemMdFile = `${docsDir}/examples-docs${item.path}.md`;
if (!fs.existsSync(itemMdFile)) {
continue;
}
var itemMd = fs.readFileSync(`${docsDir}/examples-docs${item.path}.md`).toString();
var content = parser.render(itemMd);
var result = renderVueTemplate(content, item.title);
var exampleVueName = `${docsDir}/examples-dist/${item.path}.vue`;
// 新建一个文件
if (!fs.existsSync(exampleVueName)) {
fs.closeSync(fs.openSync(exampleVueName, 'w'));
}
fs.writeFileSync(exampleVueName, result, {
encoding: 'utf8'
});
}
console.log(chalk.green('generate examples success!'));

35
build/release.sh Normal file
View File

@ -0,0 +1,35 @@
git checkout master
git merge dev
#!/usr/bin/env sh
set -e
echo "Enter release version: "
read VERSION
read -p "Releasing $VERSION - are you sure? (y/n)" -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
echo "Releasing $VERSION ..."
# build
VERSION=$VERSION npm run dist
# publish zanui-css
echo "Releasing zanui-css $VERSION ..."
cd packages/zanui-css
npm version $VERSION --message "[release] $VERSION"
npm publish --registry=http://registry.npm.qima-inc.com
cd ../..
# commit
git add -A
git commit -m "[build] $VERSION"
npm version $VERSION --message "[release] $VERSION"
# publish
git push origin master
git push origin refs/tags/v$VERSION
npm publish --registry=http://registry.npm.qima-inc.com
fi

34
build/strip-tags.js Normal file
View File

@ -0,0 +1,34 @@
/*!
* strip-tags <https://github.com/jonschlinkert/strip-tags>
*
* Copyright (c) 2015 Jon Schlinkert, contributors.
* Licensed under the MIT license.
*/
'use strict';
var cheerio = require('cheerio');
exports.strip = function(str, tags) {
var $ = cheerio.load(str, {decodeEntities: false});
if (!tags || tags.length === 0) {
return str;
}
tags = !Array.isArray(tags) ? [tags] : tags;
var len = tags.length;
while (len--) {
$(tags[len]).remove();
}
return $.html();
};
exports.fetch = function(str, tag) {
var $ = cheerio.load(str, {decodeEntities: false});
if (!tag) return str;
return $(tag).html();
};

View File

@ -0,0 +1,28 @@
var config = {
'bem': {
'shortcuts': {'component': 'b', 'modifier': 'm', 'descendent': 'e'},
'separators': {'descendent': '__', 'modifier': '--'}
}
};
// https://github.com/trysound/postcss-easy-import
var partialImport = require("postcss-easy-import")();
// 这不是bem虽然名字叫bem其实它是suit
// https://github.com/saladcss/saladcss-bem
var bem = require("saladcss-bem")(config.bem);
// https://github.com/jonathantneal/precss
var precss = require("precss")();
// https://github.com/postcss/autoprefixer
var autoprefixer = require("autoprefixer")();
module.exports = function (webpack) {
// 顺序很重要
return [
partialImport,
bem,
precss,
autoprefixer
];
};

43
build/webpack.build.js Normal file
View File

@ -0,0 +1,43 @@
var webpack = require('webpack');
var getPostcssPlugin = require('./utils/postcss_pipe');
var config = require('./webpack.config.js');
config.entry = {
'vant': './src/index.js'
};
config.output = {
filename: './lib/[name].js',
library: 'vant',
libraryTarget: 'umd'
};
config.externals = {
vue: 'vue'
};
config.plugins = [
new webpack.DefinePlugin({
'process.env.NODE_ENV': '"production"'
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false,
options: {
postcss: getPostcssPlugin,
babel: {
presets: ['es2015'],
plugins: ['transform-runtime', 'transform-vue-jsx']
},
vue: {
autoprefixer: false,
preserveWhitespace: false,
postcss: getPostcssPlugin
}
}
})
];
delete config.devtool;
module.exports = config;

18
build/webpack.build.min.js vendored Normal file
View File

@ -0,0 +1,18 @@
var webpack = require('webpack');
var config = require('./webpack.config.js');
config.output.filename = config.output.filename.replace(/\.js$/, '.min.js');
config.plugins = config.plugins.concat([
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
},
sourceMap: false
})
]);
module.exports = config;

View File

@ -0,0 +1,19 @@
var path = require('path');
var Components = require('../components.json');
var config = require('./webpack.build.js');
delete config.devtool;
config.entry = Components;
config.externals = {
vue: 'vue'
};
config.output = {
path: path.join(__dirname, '../lib'),
filename: '[name].js',
libraryTarget: 'umd'
};
module.exports = config;

195
build/webpack.config.js Normal file
View File

@ -0,0 +1,195 @@
var webpack = require('webpack');
var path = require('path');
var slugify = require('transliteration').slugify;
var striptags = require('./strip-tags');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var getPoastcssPlugin = require('./utils/postcss_pipe');
var ProgressBarPlugin = require('progress-bar-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
var StyleExtractPlugin;
if (process.env.NODE_ENV === 'production') {
StyleExtractPlugin = new ExtractTextPlugin('[name].[hash:8].css');
} else {
StyleExtractPlugin = new ExtractTextPlugin('[name].css');
}
function convert(str) {
str = str.replace(/(&#x)(\w{4});/gi, function($0) {
return String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16));
});
return str;
}
function wrap(render) {
return function() {
return render.apply(this, arguments)
.replace('<code class="', '<code class="hljs ')
.replace('<code>', '<code class="hljs">');
};
};
module.exports = {
entry: {
'vendor': ['vue', 'vue-router'],
'vant-docs': './docs/src/index.js',
'vant-examples': './docs/src/examples.js'
},
output: {
path: path.join(__dirname, '../docs/dist'),
publicPath: '/',
filename: '[name].js'
},
resolve: {
modules: [
path.join(__dirname, '../node_modules'),
'node_modules'
],
extensions: ['.js', '.vue', '.css'],
alias: {
'vue$': 'vue/dist/vue.runtime.common.js',
'vant': path.join(__dirname, '..'),
'src': path.join(__dirname, '../src'),
'packages': path.join(__dirname, '../packages'),
'lib': path.join(__dirname, '../lib'),
'components': path.join(__dirname, '../docs/src/components')
}
},
module: {
loaders: [
{
test: /\.vue$/,
use: [{
loader: 'vue-loader',
options: {
loaders: {
css: ExtractTextPlugin.extract({
use: 'css-loader!postcss-loader',
fallback: 'vue-style-loader'
})
}
}
}]
},
{
test: /\.js$/,
exclude: /node_modules|vue-router\/|vue-loader\/|vue-hot-reload-api\//,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader!postcss-loader'
})
},
{
test: /\.md/,
loader: 'vue-markdown-loader'
},
{
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url-loader'
}
]
},
devtool: 'source-map',
plugins: [
new ProgressBarPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
options: {
postcss: getPoastcssPlugin,
babel: {
presets: ['es2015'],
plugins: ['transform-runtime', 'transform-vue-jsx']
},
vue: {
autoprefixer: false,
postcss: getPoastcssPlugin
},
vueMarkdown: {
use: [
[require('markdown-it-anchor'), {
level: 2,
slugify: slugify,
permalink: true,
permalinkBefore: true
}],
[require('markdown-it-container'), 'demo', {
validate: function(params) {
return params.trim().match(/^demo\s*(.*)$/);
},
render: function(tokens, idx) {
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
if (tokens[idx].nesting === 1) {
var description = (m && m.length > 1) ? m[1] : '';
var content = tokens[idx + 1].content;
var html = convert(striptags.strip(content, ['script', 'style']));
return `<demo-block class="demo-box" description="${description}">
<div class="examples" slot="examples">${html}</div>
<div class="highlight" slot="highlight">`;
}
return '</div></demo-block>\n';
}
}]
],
preprocess: function(MarkdownIt, source) {
MarkdownIt.renderer.rules.table_open = function() {
return '<table class="table">';
};
MarkdownIt.renderer.rules.fence = wrap(MarkdownIt.renderer.rules.fence);
return source;
}
}
}
}),
new HtmlWebpackPlugin({
chunks: ['vendor', 'vant-docs'],
template: 'docs/src/index.tpl',
filename: 'index.html',
inject: true
}),
new HtmlWebpackPlugin({
chunks: ['vendor', 'vant-examples'],
template: 'docs/src/index.tpl',
filename: 'examples.html',
inject: true
}),
new OptimizeCssAssetsPlugin(),
StyleExtractPlugin
]
};
if (process.env.NODE_ENV === 'production') {
delete module.exports.devtool;
module.exports.output = {
path: path.join(__dirname, '../docs/dist'),
publicPath: '/zanui/vue',
filename: '[name].[hash:8].js'
};
module.exports.plugins = module.exports.plugins.concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV)
}
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true
},
output: {
comments: false
},
sourceMap: false
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity
})
]);
}

39
components.json Normal file
View File

@ -0,0 +1,39 @@
{
"button": "./packages/button/index.js",
"switch": "./packages/switch/index.js",
"field": "./packages/field/index.js",
"radio": "./packages/radio/index.js",
"cell": "./packages/cell/index.js",
"icon": "./packages/icon/index.js",
"cell-group": "./packages/cell-group/index.js",
"popup": "./packages/popup/index.js",
"dialog": "./packages/dialog/index.js",
"picker": "./packages/picker/index.js",
"radio-group": "./packages/radio-group/index.js",
"waterfall": "./packages/waterfall/index.js",
"loading": "./packages/loading/index.js",
"panel": "./packages/panel/index.js",
"card": "./packages/card/index.js",
"steps": "./packages/steps/index.js",
"tag": "./packages/tag/index.js",
"checkbox": "./packages/checkbox/index.js",
"checkbox-group": "./packages/checkbox-group/index.js",
"badge-group": "./packages/badge-group/index.js",
"badge": "./packages/badge/index.js",
"search": "./packages/search/index.js",
"step": "./packages/step/index.js",
"tabs": "./packages/tabs/index.js",
"tab": "./packages/tab/index.js",
"lazyload": "./packages/lazyload/index.js",
"image-preview": "./packages/image-preview/index.js",
"col": "./packages/col/index.js",
"row": "./packages/row/index.js",
"actionsheet": "./packages/actionsheet/index.js",
"quantity": "./packages/quantity/index.js",
"progress": "./packages/progress/index.js",
"toast": "./packages/toast/index.js",
"uploader": "./packages/uploader/index.js",
"swipe": "./packages/swipe/index.js",
"swipe-item": "./packages/swipe-item/index.js",
"datetime-picker": "./packages/datetime-picker/index.js"
}

210
docs/assets/docs.css Normal file
View File

@ -0,0 +1,210 @@
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
vertical-align: baseline;
}
body {
font-family: 'Helvetica Neue',Helvetica,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',SimSun,sans-serif;
font-weight: 400;
-webkit-font-smoothing: antialiased;
background-color: #f8f8f8;
}
a {
color: #4078c0;
text-decoration: none;
}
button, input, select, textarea {
font-family: inherit;
font-size: inherit;
line-height: inherit;
color: inherit;
}
ul, ol {
list-style: none;
}
code.hljs {
line-height: 1.5;
font-family: Menlo, Monaco, Consolas, Courier, monospace;
font-size: 12px;
padding: 20px;
background-color: #f8f8f8;
border: solid 1px #E5E5E5;
margin-bottom: 25px;
border-radius: 4px;
-webkit-font-smoothing: auto;
}
.clearfix {
&::before {
display: table;
content: "";
}
&::after {
display: table;
content: "";
clear: both;
}
}
.main-content {
margin: 110px 20px 40px;
padding-top: 20px;
}
.page-container {
background-color: #fff;
position: relative;
display: flex;
width: 100%;
overflow: hidden;
}
.page-content {
box-sizing: border-box;
flex: 1;
section {
padding: 0 40px;
> h1,
> h2,
> h3,
> h4,
> h5,
> h6 {
color: #333;
line-height: 1.5;
margin: 20px 0;
font-weight: normal;
&:hover a {
opacity: .4;
}
a {
float: left;
margin-left: -20px;
opacity: 0;
cursor: pointer;
&:hover {
opacity: .4;
}
}
}
> h1 {
font-size: 40px;
}
> h2 {
font-size: 36px;
}
> h3 {
font-size: 30px;
}
> h4 {
font-size: 24px;
}
> h5 {
font-size: 14px
}
> h6 {
font-size: 14px;
color: #666;
}
> p {
font-size: 14px;
line-height: 20px;
color: #666;
margin: 14px 0;
}
> ul li,
> ol li {
color: #666;
font-size: 14px;
line-height: 20px;
margin: 10px 0 10px 20px;
padding-left: 20px;
position: relative;
&::before {
content: '';
position: absolute;
width: 8px;
height: 8px;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 50%;
top: 6px;
left: 0;
}
li {
margin-left: 0;
}
}
}
p > code,
.table code,
li > code {
background-color: #F2F2F2;
display: inline-block;
border: 1px solid #E5E5E5;
padding: 2px 4px;
color: #333;
margin: 0 3px;
}
}
.table {
border-collapse: collapse;
width: 100%;
background-color: #fff;
color: #333;
font-size: 14px;
margin-bottom: 45px;
th {
text-align: left;
border: 1px solid #E5E5E5;
background-color: #F2F2F2;
padding: 10px;
&:first-child {
padding-left: 10px;
}
}
td {
border: 1px solid #E5E5E5;
padding: 10px;
}
}

View File

@ -0,0 +1,81 @@
<template><section class="demo-actionsheet"><h1 class="demo-title">Actionsheet 行动按钮</h1><example-block title="基础用法">
<van-button @click="show1 = true">弹出actionsheet</van-button>
<van-actionsheet v-model="show1" :actions="actions1">
</van-actionsheet>
</example-block><example-block title="带取消按钮的ActionSheet">
<van-button @click="show2 = true">弹出带取消按钮的actionsheet</van-button>
<van-actionsheet v-model="show2" :actions="actions1" cancel-text="取消">
</van-actionsheet>
</example-block><example-block title="带标题的ActionSheet">
<van-button @click="show3 = true">弹出带标题的actionsheet</van-button>
<van-actionsheet v-model="show3" title="支持以下配送方式" class="title-actionsheet">
<p>一些内容</p>
</van-actionsheet>
</example-block></section></template>
<style>
@component-namespace demo {
@b actionsheet {
.actionsheet-wx {
color: #06BF04;
}
.van-button {
margin-left: 15px;
}
.title-actionsheet p {
padding: 20px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
data() {
return {
show1: false,
show2: false,
show3: false,
actions1: [
{
name: '微信安全支付',
className: 'actionsheet-wx',
callback: this.handleActionClick
},
{
name: '支付宝支付',
loading: true
},
{
name: '有赞E卡',
subname: '剩余260.50元)'
},
{
name: '信用卡支付'
},
{
name: '其他支付方式'
}
]
};
},
methods: {
handleActionClick(item) {
console.log(item);
}
}
}
</script>

View File

@ -0,0 +1,50 @@
<template><section class="demo-badge"><h1 class="demo-title">Badge 徽章</h1><example-block title="基础用法">
<div class="badge-group-wrapper">
<van-badge-group>
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
</example-block><example-block title="选中某个badge">
<div class="badge-group-wrapper">
<van-badge-group :active-key="2">
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
</example-block></section></template>
<style>
@component-namespace demo {
@b badge {
.badge-group-wrapper {
padding: 30px 20px;
background-color: #fff;
}
.van-badge-group {
margin: 0 auto;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
activeKey: '2'
};
},
methods: {
onItemClick(e, data) {
this.activeKey = data.mark;
}
}
};
</script>

View File

@ -0,0 +1,89 @@
<template><section class="demo-button"><h1 class="demo-title">Button 按钮</h1><example-block title="按钮功能">
<van-row>
<van-col span="24">
<van-button block="">default</van-button>
</van-col>
<van-col span="24">
<van-button type="primary" block="">primary</van-button>
</van-col>
<van-col span="24">
<van-button type="danger" block="">danger</van-button>
</van-col>
</van-row>
</example-block><example-block title="禁用状态">
<van-row>
<van-col span="24">
<van-button disabled block="">diabled</van-button>
</van-col>
</van-row>
</example-block><example-block title="按钮尺寸">
<van-row>
<van-col span="24">
<van-button size="large">large</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="normal">normal</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="small">small</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="mini">mini</van-button>
</van-col>
</van-row>
</example-block><example-block title="自定义按钮标签">
<van-row>
<van-col span="24">
<van-button tag="a" type="primary" href="https://www.youzan.com" target="_blank">a标签按钮</van-button>
</van-col>
</van-row>
</example-block><example-block title="loading按钮">
<van-row>
<van-col span="24">
<van-button type="primary" loading="" block="">loading</van-button>
</van-col>
<van-col span="24">
<van-button loading="" block=""></van-button>
</van-col>
</van-row>
</example-block><example-block title="">
<van-row>
<van-col span="24">
<van-button type="primary" bottom-action="">立即购买</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="12">
<van-button bottom-action="">加入购物车</van-button>
</van-col>
<van-col span="12">
<van-button type="primary" bottom-action="">立即购买</van-button>
</van-col>
</van-row>
</example-block></section></template>
<style>
@component-namespace demo {
@b button {
.van-row {
padding: 0 15px;
}
.van-col {
margin-bottom: 10px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,23 @@
<template><section class="demo-card"><h1 class="demo-title">Card 图文组件</h1><example-block title="基础用法">
<van-card title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余" desc="描述" thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
</van-card>
</example-block><example-block title="高级用法">
<van-card thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
<span class="van-card__num">x 2</span>
</div>
<div class="van-card__footer" slot="footer">
<van-button size="mini">按钮一</van-button>
<van-button size="mini">按钮二</van-button>
</div>
</van-card>
</example-block></section></template>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,47 @@
<template><section class="demo-cell"><h1 class="demo-title">Cell 单元格</h1><example-block title="基础用法">
<van-cell-group>
<van-cell title="单元格1" value="单元格1内容"></van-cell>
<van-cell title="单元格2" value="单元格2内容"></van-cell>
</van-cell-group>
</example-block><example-block title="标题带描述信息">
<van-cell-group>
<van-cell title="单元格1" label="描述信息" is-link="" url="javascript:void(0)" @click="handleClick"></van-cell>
<van-cell title="单元格2" label="描述信息"></van-cell>
</van-cell-group>
</example-block><example-block title="带图标">
<van-cell-group>
<van-cell title="起码运动馆" icon="home"></van-cell>
<van-cell title="线下门店" icon="location"></van-cell>
</van-cell-group>
</example-block><example-block title="可点击的链接">
<van-cell-group>
<van-cell title="起码运动馆" value="进入店铺" icon="home" url="http://youzan.com" is-link=""></van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link=""></van-cell>
</van-cell-group>
</example-block><example-block title="高级用法">
<van-cell-group>
<van-cell value="进入店铺" icon="home" url="http://youzan.com" is-link="">
<template slot="title">
<span class="van-cell-text">起码运动馆</span>
<van-tag type="danger">官方</van-tag>
</template>
</van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link=""></van-cell>
</van-cell-group>
</example-block></section></template>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
methods: {
handleClick() {
console.log('cell click');
}
}
};
</script>

View File

@ -0,0 +1,80 @@
<template><section class="demo-checkbox"><h1 class="demo-title">Checkbox 复选框</h1><example-block title="基础用法">
<div class="van-checkbox-wrapper">
<van-checkbox v-model="checkbox1">复选框1</van-checkbox>
</div>
</example-block><example-block title="禁用状态">
<div class="van-checkbox-wrapper">
<van-checkbox v-model="checkbox2">复选框2</van-checkbox>
</div>
</example-block><example-block title="Checkbox组">
<div class="van-checkbox-wrapper">
<van-checkbox-group v-model="result">
<van-checkbox v-for="item in list" :name="item">复选框{{item}}</van-checkbox>
</van-checkbox-group>
</div>
</example-block><example-block title="禁用Checkbox组">
<div class="van-checkbox-wrapper">
<van-checkbox-group v-model="result" disabled>
<van-checkbox v-for="item in list" :name="item">复选框{{item}}</van-checkbox>
</van-checkbox-group>
</div>
</example-block><example-block title="与Cell组件一起使用">
<van-checkbox-group v-model="result">
<van-cell-group>
<van-cell v-for="item in list">
<van-checkbox :name="item">复选框{{item}}</van-checkbox>
</van-cell>
</van-cell-group>
</van-checkbox-group>
</example-block></section></template>
<style>
@component-namespace demo {
@b checkbox {
.van-checkbox-wrapper {
padding: 0 20px;
.van-checkbox {
margin: 10px 0;
}
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
checkbox1: true,
checkbox2: true,
list: [
'a',
'b',
'c'
],
result: ['a', 'b']
};
},
watch: {
result(val) {
console.log(val);
}
}
};
</script>

View File

@ -0,0 +1,34 @@
<template><section class="demo-datetime"><h1 class="demo-title">Datetime Picker 时间选择</h1><example-block title="基础用法">
<zan-datetime-picker v-model="currentDate" type="datetime" format="yyyy.mm.dd hh时 mm分" :min-hour="minHour" :max-hour="maxHour" :min-date="minDate" @change="handlePickerChange">
</zan-datetime-picker>
</example-block></section></template>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
minHour: 10,
maxHour: 20,
minDate: new Date(),
currentDate: null
};
},
methods: {
handlePickerChange(picker, values) {
// picker.setColumnValues(1, citys[values[0]]);
console.log(values);
},
handlePickerCancel() {
alert('picker cancel');
},
handlePickerConfirm() {
alert('picker confirm');
}
}
};
</script>

View File

@ -0,0 +1,60 @@
<template><section class="demo-dialog"><h1 class="demo-title">Dialog 弹出框</h1><example-block title="消息提示">
<van-button @click="handleAlertClick">alert</van-button>
<van-button @click="handleAlert2Click">无标题alert</van-button>
</example-block><example-block title="消息确认">
<van-button @click="handleConfirmClick">confirm</van-button>
</example-block></section></template>
<style>
@component-namespace demo {
@b dialog {
.van-button {
margin: 15px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import { Dialog } from 'src/index';
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
methods: {
handleAlertClick() {
Dialog.alert({
title: 'alert标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
});
},
handleAlert2Click() {
Dialog.alert({
message: '无标题alert'
}).then((action) => {
console.log(action);
});
},
handleConfirmClick() {
Dialog.confirm({
title: 'confirm标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
}, (error) => {
console.log(error);
});
}
}
};
</script>

View File

@ -0,0 +1,52 @@
<template><section class="demo-field"><h1 class="demo-title">Field 输入框</h1><example-block title="基础用法">
<van-cell-group>
<van-field type="text" label="用户名:" placeholder="请输入用户名" v-model="username" required></van-field>
<van-field type="password" label="密码:" placeholder="请输入密码" required></van-field>
<van-field type="textarea" label="个人介绍:" placeholder="请输入个人介绍" required></van-field>
</van-cell-group>
</example-block><example-block title="无label的输入框">
<van-cell-group>
<van-field type="text" placeholder="请输入用户名"></van-field>
</van-cell-group>
</example-block><example-block title="带border的输入框">
<div class="van-field-wrapper">
<van-field type="text" placeholder="请输入用户名" border=""></van-field>
</div>
</example-block><example-block title="禁用的输入框">
<van-cell-group>
<van-field label="用户名:" type="text" placeholder="请输入用户名" v-model="username" disabled></van-field>
</van-cell-group>
</example-block><example-block title="错误的输入框">
<van-cell-group>
<van-field label="用户名:" type="text" placeholder="请输入用户名" error=""></van-field>
</van-cell-group>
</example-block><example-block title="错误的输入框">
<van-cell-group>
<van-field label="留言:" type="textarea" placeholder="请输入留言" rows="1" autosize=""></van-field>
</van-cell-group>
</example-block></section></template>
<style>
@component-namespace demo {
@b field {
.van-field-wrapper {
padding: 0 10px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
username: 'zhangmin'
};
}
};
</script>

156
docs/examples-dist/icon.vue Normal file
View File

@ -0,0 +1,156 @@
<template><section class="demo-icon"><h1 class="demo-title">Icon 图标</h1><example-block title="所有Icon">
<van-row>
<van-col span="8">
<van-icon name="qr-invalid"></van-icon>
<span>qr-invalid</span>
</van-col>
<van-col span="8">
<van-icon name="qr"></van-icon>
<span>qr</span>
</van-col>
<van-col span="8">
<van-icon name="exchange"></van-icon>
<span>exchange</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="close"></van-icon>
<span>close</span>
</van-col>
<van-col span="8">
<van-icon name="location"></van-icon>
<span>location</span>
</van-col>
<van-col span="8">
<van-icon name="upgrade"></van-icon>
<span>upgrade</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="check"></van-icon>
<span>check</span>
</van-col>
<van-col span="8">
<van-icon name="checked"></van-icon>
<span>checked</span>
</van-col>
<van-col span="8">
<van-icon name="like-o"></van-icon>
<span>like-o</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="like" style="color: red;"></van-icon>
<span>like</span>
</van-col>
<van-col span="8">
<van-icon name="chat"></van-icon>
<span>chat</span>
</van-col>
<van-col span="8">
<van-icon name="shop"></van-icon>
<span>shop</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="photograph"></van-icon>
<span>photograph</span>
</van-col>
<van-col span="8">
<van-icon name="add"></van-icon>
<span>add</span>
</van-col>
<van-col span="8">
<van-icon name="add2"></van-icon>
<span>add2</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="photo"></van-icon>
<span>photo</span>
</van-col>
<van-col span="8">
<van-icon name="logistics"></van-icon>
<span>logistics</span>
</van-col>
<van-col span="8">
<van-icon name="edit"></van-icon>
<span>edit</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="passed"></van-icon>
<span>passed</span>
</van-col>
<van-col span="8">
<van-icon name="cart"></van-icon>
<span>cart</span>
</van-col>
<van-col span="8">
<van-icon name="arrow"></van-icon>
<span>arrow</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="gift"></van-icon>
<span>gift</span>
</van-col>
<van-col span="8">
<van-icon name="search"></van-icon>
<span>search</span>
</van-col>
<van-col span="8">
<van-icon name="clear"></van-icon>
<span>clear</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="success"></van-icon>
<span>success</span>
</van-col>
<van-col span="8">
<van-icon name="fail"></van-icon>
<span>fail</span>
</van-col>
<van-col span="8">
<van-icon name="contact"></van-icon>
<span>contact</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="wechat"></van-icon>
<span>wechat</span>
</van-col>
<van-col span="8">
<van-icon name="alipay"></van-icon>
<span>alipay</span>
</van-col>
</van-row>
</example-block></section></template>
<style>
@component-namespace demo {
@b icon {
.van-col {
text-align: center;
}
.van-icon {
font-size: 45px;
display: block;
margin: 15px 0;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,34 @@
<template><section class="demo-image-preview"><h1 class="demo-title">ImagePreview 图片预览</h1><example-block title="基础用法">
<van-button @click="handleImagePreview">预览图片</van-button>
</example-block></section></template>
<style>
@component-namespace demo {
@b image-preview {
.van-button {
margin-left: 15px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import { ImagePreview } from 'src/index';
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
methods: {
handleImagePreview() {
ImagePreview([
'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]);
}
}
};
</script>

View File

@ -0,0 +1,71 @@
<template><section class="demo-layout"><h1 class="demo-title">Layout 布局</h1><example-block title="常规用法">
<van-row>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="white">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
</van-row>
<van-row>
<van-col span="4">
<div class="gray">span: 4</div>
</van-col>
<van-col span="10" offset="4">
<div class="gray">offset: 4, span: 10</div>
</van-col>
</van-row>
<van-row>
<van-col offset="12" span="12">
<div class="gray">offset: 12, span: 12</div>
</van-col>
</van-row>
</example-block><example-block title="在列元素之间增加间距">
<van-row gutter="10">
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
</van-row>
</example-block></section></template>
<style>
@component-namespace demo {
@b layout {
.van-row {
padding: 0 20px;
}
.van-col {
margin-bottom: 10px;
}
}
}
.gray {
height: 30px;
line-height: 30px;
font-size: 12px;
background: #666;
color: #fff;
text-align: center;
}
.white {
height: 30px;
line-height: 30px;
font-size: 12px;
background: #fff;
color: #333;
text-align: center;
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,78 @@
<template><section class="demo-lazyload"><h1 class="demo-title">Lazyload 图片懒加载</h1><example-block title="基础用法">
<ul class="image-list" ref="container">
<li v-for="img in imageList">
<img class="lazy-img" v-lazy="img">
</li>
</ul>
</example-block><example-block title="背景图懒加载">
<ul class="image-list" ref="container">
<li v-for="img in backgroundImageList">
<div class="lazy-background" v-lazy:background-image="img"></div>
</li>
</ul>
</example-block><example-block title="懒加载模块">
<lazy-component @show="handleComponentShow">
<ul class="image-list">
<li v-for="img in componentImageList">
<img class="lazy-img" v-lazy="img">
</li>
</ul>
</lazy-component>
</example-block></section></template>
<style>
@component-namespace demo {
@b lazyload {
.lazy-img {
display: block;
width: 100%;
height: auto;
}
.lazy-background {
height: 300px;
background-size: cover;
background-repeat: no-repeat;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
imageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL',
'https://img.yzcdn.cn/upload_files/2016/01/27/FpWD3kX18w8qjM6faH-4JqOWHsF4',
'https://img.yzcdn.cn/upload_files/2016/09/08/9ff28d555e5760fa830344f12efa0087.jpg',
'https://img.yzcdn.cn/upload_files/2016/11/13/FlZIeSgbSANSPkmUHttMjoIgY3cv.jpg',
'https://img.yzcdn.cn/upload_files/2016/12/12/FuxgsGPRnupGu_eaMuaR8W0DuSKp.jpeg'
],
backgroundImageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL'
],
componentImageList: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
]
};
},
methods: {
handleComponentShow() {
console.log('component show');
}
}
}
</script>

View File

@ -0,0 +1,36 @@
<template><section class="demo-loading"><h1 class="demo-title">Loading 加载</h1><example-block title="渐变深色spinner">
<van-loading class="some-customized-class"></van-loading>
</example-block><example-block title="渐变浅色spinner">
<div class="demo-loading__example demo-loading__example--with-bg">
<van-loading class="some-customized-class" :color="'white'"></van-loading>
</div>
</example-block><example-block title="单色spinner">
<van-loading class="circle-loading" :type="'circle'" :color="'white'"></van-loading>
<van-loading class="circle-loading" :type="'circle'" :color="'black'"></van-loading>
</example-block></section></template>
<style>
@component-namespace demo {
@b loading {
.van-loading {
margin: 0 auto;
}
.circle-loading {
margin: 20px auto;
}
.demo-loading__example--with-bg {
background-color: rgba(0, 0, 0, 0.5);
margin: 0 auto;
width: 80px;
padding: 25px 0;
border-radius: 10px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,65 @@
<template><section class="demo-panel"><h1 class="demo-title">Panel 面板</h1><example-block title="基础用法">
<van-panel title="标题" desc="标题描述" status="状态">
<div class="panel-content">
panel内容
</div>
</van-panel>
</example-block><example-block title="高级用法">
<van-panel title="标题" desc="标题描述" status="状态">
<van-card title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余" desc="商品SKU1商品SKU2" thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余两行显示状态如效果图多余多余多余</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
<h4 class="van-card__desc">商品sku</h4>
<span class="van-card__num">x 2</span>
</div>
<div class="van-card__footer" slot="footer">
<van-button size="mini">按钮一</van-button>
<van-button size="mini">按钮二</van-button>
</div>
</van-card>
<div class="van-panel-sum">
合计<span>¥ 1999.90</span>
</div>
<div class="van-panel-buttons" slot="footer">
<van-button size="small">按钮一</van-button>
<van-button size="small" type="danger">按钮二</van-button>
</div>
</van-panel>
</example-block></section></template>
<style>
@component-namespace demo {
@b panel {
.van-panel-sum {
background: #fff;
text-align: right;
font-size: 14px;
color: #333;
line-height: 30px;
padding-right: 15px;
span {
color: red;
}
}
.van-panel-buttons {
text-align: right;
.van-button {
margin-left: 5px;
}
}
.panel-content {
padding: 20px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,49 @@
<template><section class="demo-picker"><h1 class="demo-title">Picker 选择器</h1><example-block title="基础用法">
<zan-picker :columns="pickerColumns" @change="handlePickerChange"></zan-picker>
</example-block><example-block title="带toolbar的Picker">
<zan-picker :columns="pickerColumns" show-toolbar="" @change="handlePickerChange" @cancel="handlePickerCancel" @confirm="handlePickerConfirm"></zan-picker>
</example-block></section></template>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
const citys = {
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
};
export default {
data() {
return {
pickerColumns: [
{
values: Object.keys(citys),
className: 'column1'
},
{
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
className: 'column2'
}
]
};
},
methods: {
handlePickerChange(picker, values) {
picker.setColumnValues(1, citys[values[0]]);
},
handlePickerCancel() {
alert('picker cancel');
},
handlePickerConfirm() {
alert('picker confirm');
}
}
};
</script>

View File

@ -0,0 +1,112 @@
<template><section class="demo-popup"><h1 class="demo-title">Popup 弹出菜单</h1><example-block title="基础用法">
<van-button @click="popupShow1 = true">从中间弹出popup</van-button>
<van-popup v-model="popupShow1" class="van-popup-1" :lock-on-scroll="true">
从中间弹出popup
</van-popup>
</example-block><example-block title="从不同位置弹出菜单">
<van-button @click="popupShow2 = true;">从下方弹出popup</van-button>
<van-popup v-model="popupShow2" position="bottom" class="van-popup-2">
<van-button @click="showDialog">弹出dialog</van-button>
</van-popup>
<van-button @click="popupShow3 = true">从上方弹出popup</van-button>
<van-popup v-model="popupShow3" position="top" class="van-popup-3" :overlay="false">
更新成功
</van-popup>
<van-button @click="popupShow4 = true">从右方弹出popup</van-button>
<van-popup v-model="popupShow4" position="right" class="van-popup-4" :overlay="false">
<van-button @click.native="popupShow4 = false">关闭 popup</van-button>
</van-popup>
<van-button @click="popupShow5 = true">从左方弹出popup</van-button>
<van-popup v-model="popupShow5" position="left" class="van-popup-5" :overlay="false">
<van-button @click.native="popupShow5 = false">关闭 popup</van-button>
</van-popup>
</example-block></section></template>
<style>
@component-namespace demo {
@b popup {
.van-button {
margin: 10px 15px;
}
.van-popup-1 {
width: 60%;
box-sizing: border-box;
padding: 20px;
border-radius: 5px;
text-align: center;
}
.van-popup-2 {
width: 100%;
height: 200px;
box-sizing: border-box;
padding: 20px;
}
.van-popup-3 {
line-height: 50px;
text-align: center;
background-color: rgba(0, 0, 0, 0.701961);
color: #fff;
}
.van-popup-4,
.van-popup-5 {
width: 100%;
height: 100%;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import MobileComputed from 'components/mobile-computed';
import Dialog from 'packages/dialog';
export default {
mixins: [MobileComputed],
data() {
return {
popupShow1: false,
popupShow2: false,
popupShow3: false,
popupShow4: false,
popupShow5: false
}
},
watch: {
popupShow3(val) {
if (val) {
setTimeout(() => {
this.popupShow3 = false;
}, 2000);
}
}
},
methods: {
showDialog() {
Dialog.confirm({
title: 'confirm标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
}, (error) => {
console.log(error);
});
}
}
};
</script>

View File

@ -0,0 +1,46 @@
<template><section class="demo-progress"><h1 class="demo-title">Progress 进度条</h1><example-block title="基础用法">
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :percentage="0"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo2" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :percentage="100"></van-progress>
</div>
</example-block><example-block title="Inactive">
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :inactive="true" :percentage="0"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo2" :inactive="true" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :inactive="true" :percentage="100"></van-progress>
</div>
</example-block><example-block title="自定义颜色和文字">
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="红色" color="#ed5050" :percentage="26"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="橙色" color="#f60" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="黄色" color="#f09000" :percentage="66"></van-progress>
</div>
</example-block></section></template>
<style>
@component-namespace demo {
@b progress {
@e wrapper {
padding: 5px;
margin: 20px 10px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,36 @@
<template><section class="demo-quantity"><h1 class="demo-title">Quantity 数量选择</h1><example-block title="基础用法">
<van-quantity v-model="quantity1"></van-quantity>
<p class="curr-quantity">当前值{{ quantity1 }}</p>
</example-block><example-block title="禁用Quantity">
<van-quantity v-model="quantity1" disabled></van-quantity>
</example-block><example-block title="高级用法">
<van-quantity v-model="quantity2" min="5" max="40" step="2" default-value="9"></van-quantity>
<p class="curr-quantity">当前值{{ quantity2 }}</p>
</example-block></section></template>
<style>
@component-namespace demo {
@b quantity {
.van-quantity {
margin-left: 15px;
}
.curr-quantity {
margin: 15px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
quantity1: 1,
quantity2: null,
};
}
};
</script>

View File

@ -0,0 +1,63 @@
<template><section class="demo-radio"><h1 class="demo-title">Radio 单选框</h1><example-block title="基础用法">
<div class="van-radios">
<van-radio name="1" v-model="radio1">单选框1</van-radio>
<van-radio name="2" v-model="radio1">单选框2</van-radio>
</div>
</example-block><example-block title="禁用状态">
<div class="van-radios">
<van-radio name="1" v-model="radio2" disabled>未选中禁用</van-radio>
<van-radio name="2" v-model="radio2" disabled>选中且禁用</van-radio>
</div>
</example-block><example-block title="radio组">
<div class="van-radios">
<van-radio-group v-model="radio3">
<van-radio name="1">单选框1</van-radio>
<van-radio name="2">单选框2</van-radio>
</van-radio-group>
</div>
</example-block><example-block title="与Cell组件一起使用">
<van-radio-group v-model="radio4">
<van-cell-group>
<van-cell><van-radio name="1">单选框1</van-radio></van-cell>
<van-cell><van-radio name="2">单选框2</van-radio></van-cell>
</van-cell-group>
</van-radio-group>
</example-block></section></template>
<style>
@component-namespace demo {
@b radio {
.van-radios {
padding: 0 20px;
.van-radio {
margin: 10px 0;
}
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
radio1: '1',
radio2: '2',
radio3: '1',
radio4: '1'
};
}
};
</script>

View File

@ -0,0 +1,28 @@
<template><section class="demo-search"><h1 class="demo-title">Search 搜索</h1><example-block title="基础用法">
<van-search placeholder="商品名称" @search="goSearch"></van-search>
</example-block><example-block title="监听对应事件">
<van-search placeholder="商品名称" @search="goSearch" @change="handleChange" @cancel="handleCancel"></van-search>
</example-block></section></template>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
methods: {
goSearch(value) {
alert(value)
},
handleChange(value) {
console.log(value);
},
handleCancel() {
alert('cancel');
}
}
};
</script>

View File

@ -0,0 +1,50 @@
<template><section class="demo-steps"><h1 class="demo-title">Steps 步骤条</h1><example-block title="基础用法">
<van-steps :active="active" icon="logistics" icon-class="steps-success" title="等待商家发货" description="等待商家发货等待商家发货等待商家发货等待商家发货等待商家发货">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
<van-button @click="nextStep">下一步</van-button>
</example-block><example-block title="只显示步骤条">
<van-steps :active="active">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
</example-block></section></template>
<style>
@component-namespace demo {
@b steps {
.steps-success {
color: #06bf04;
}
.van-button {
margin: 15px 0 0 15px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
active: 0
};
},
methods: {
nextStep() {
if (++this.active > 3) this.active = 0;
}
}
}
</script>

View File

@ -0,0 +1,55 @@
<template><section class="demo-swipe"><h1 class="demo-title">Swipe 轮播</h1><example-block title="基础用法">
<van-swipe>
<van-swipe-item v-for="img in images">
<img v-lazy="img" alt="">
</van-swipe-item>
</van-swipe>
</example-block><example-block title="自动轮播">
<van-swipe auto-play="" @pagechange:end="handlePageEnd">
<van-swipe-item v-for="img in autoImages">
<img v-lazy="img" alt="">
</van-swipe-item>
</van-swipe>
</example-block></section></template>
<style>
@component-namespace demo {
@b swipe {
.van-swipe {
height: 200px;
img {
width: 100%;
}
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
autoImages: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
],
images: [
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]
};
},
methods: {
handlePageEnd(page, index) {
console.log(page, index);
}
}
};
</script>

View File

@ -0,0 +1,79 @@
<template><section class="demo-switch"><h1 class="demo-title">Switch 开关</h1><example-block title="基础用法">
<van-switch class="some-customized-class" v-model="switchState1"></van-switch>
<div class="demo-switch__text">{{ switchState1 ? ' ON' : 'OFF' }}</div>
</example-block><example-block title="">
<van-switch class="some-customized-class" v-model="switchState2" :on-change="updateState"></van-switch>
<div class="demo-switch__text">{{ switchState2 ? ' ON' : 'OFF' }}</div>
</example-block><example-block title="禁用状态">
<van-switch class="some-customized-class" v-model="switchStateTrue" :disabled="true"></van-switch>
<div class="demo-switch__text">ON, DISABLED</div>
<van-switch class="some-customized-class" v-model="switchStateFalse" :disabled="true"></van-switch>
<div class="demo-switch__text">OFF, DISABLED</div>
</example-block><example-block title="loading状态">
<van-switch class="some-customized-class" v-model="switchStateTrue" :loading="true"></van-switch>
<div class="demo-switch__text">ON, LOADING</div>
<van-switch class="some-customized-class" v-model="switchStateFalse" :loading="true"></van-switch>
<div class="demo-switch__text">OFF, LOADING</div>
</example-block></section></template>
<style>
@component-namespace demo {
@b switch {
.examples,
.example-block {
text-align: center;
}
.example-block {
.demo-sub-title {
text-align: left;
}
}
@e text {
margin: 20px auto;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import Dialog from 'packages/dialog';
export default {
data() {
return {
switchState1: true,
switchState2: true,
switchStateTrue: true,
switchStateFalse: false
};
},
methods: {
updateState(newState) {
const state = newState ? '打开' : '关闭';
Dialog.confirm({
title: '提醒',
message: '是否' + state + '开关?'
}).then((action) => {
this.switchState2 = newState;
}, (error) => {});
}
}
};
</script>

123
docs/examples-dist/tab.vue Normal file
View File

@ -0,0 +1,123 @@
<template><section class="demo-tab"><h1 class="demo-title">Tab 标签</h1><example-block title="基础用法">
<van-tabs>
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
</example-block><example-block title="基础用法">
<van-tabs :active="active">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
</example-block><example-block title="禁用tab">
<van-tabs>
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
</example-block><example-block title="card样式">
<van-tabs type="card">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
</example-block><example-block title="自定义样式">
<van-tabs active="2" class="custom-tabwrap">
<van-tab title="选项一" class="custom-pane">内容一</van-tab>
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
<van-tab title="选项五" class="custom-pane">内容五</van-tab>
</van-tabs>
</example-block><example-block title="click事件">
<van-tabs @click="handleTabClick">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
</example-block></section></template>
<style>
@component-namespace demo {
@b tab {
.van-tab__pane {
background-color: #fff;
padding: 20px;
}
.van-tabs--card .van-tab__pane {
background-color: transparent;
}
.custom-tabwrap .van-tab-active {
color: #20a0ff;
}
.custom-tabwrap .van-tabs-nav-bar {
background: #20a0ff;
}
.custom-pane {
text-align: center;
height: 50px;
line-height: 50px;
}
}
}
</style><style>
.custom-tabwrap .van-tab-active {
color: #20a0ff;
}
.custom-tabwrap .van-tabs-nav-bar {
background: #20a0ff;
}
.custom-pane {
text-align: center;
height: 50px;
line-height: 50px;
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
active: 2
};
},
mounted() {
setTimeout(() => {
this.active = 3;
}, 1000);
},
methods: {
popalert() {
alert('haha')
},
handleTabClick(index) {
alert(index);
}
}
};
</script>

View File

@ -0,0 +1,40 @@
<template><section class="demo-tag"><h1 class="demo-title">Tag 标记</h1><example-block title="基础用法">
<div class="tags-container">
<van-tag>返现</van-tag>
<van-tag plain="">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag type="danger">四字标签</van-tag>
<van-tag type="danger"></van-tag>
</div>
</example-block><example-block title="高级用法">
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag plain="" type="danger">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="primary">返现</van-tag>
<van-tag plain="" type="primary">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="success">返现</van-tag>
<van-tag plain="" type="success">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger" mark="">返现</van-tag>
</div>
</example-block></section></template>
<style>
.tags-container {
padding: 5px 15px;
.van-tag + .van-tag {
margin-left: 10px;
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);</script>

View File

@ -0,0 +1,86 @@
<template><section class="demo-toast"><h1 class="demo-title">Toast 轻提示</h1><example-block title="基础用法">
<van-button @click="showSimpleToast">普通文字提示</van-button>
<van-button @click="showLoadingToast">加载Toast</van-button>
<van-button @click="showSuccessToast">成功</van-button>
<van-button @click="showFailToast">失败</van-button>
<van-button @click="showForbidClickToast">背景不能点击</van-button>
<van-button @click="showCustomizedToast(5000)">倒数5秒</van-button>
</example-block><example-block title="手动关闭">
<van-button @click="showToast">打开</van-button>
<van-button @click="closeToast">关闭</van-button>
</example-block><example-block title="手动关闭">
<van-button @click="showHtmlToast">打开</van-button>
</example-block></section></template>
<style>
@component-namespace demo {
@b toast {
.van-button {
margin: 15px;
}
}
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
import { Toast } from 'src/index';
export default {
methods: {
showSimpleToast() {
Toast('我是提示文案,建议不超过十五字~');
},
showLoadingToast() {
Toast.loading();
},
showSuccessToast() {
Toast.success('成功文案');
},
showFailToast() {
Toast.fail('失败文案');
},
showForbidClickToast() {
Toast({
message: '背景不能点击',
forbidClick: true
})
},
showCustomizedToast(duration) {
let leftSec = duration / 1000;
let toast = Toast({
duration: duration + 1000,
type: 'success',
message: leftSec.toString()
});
const id = window.setInterval(() => {
if (leftSec <= 1) {
window.clearInterval(id);
toast.message = '跳转中...'
return;
}
toast.message = (--leftSec).toString();
}, 1000);
},
showToast() {
this.toast = Toast('我是提示文案,建议不超过十五字~');
},
closeToast() {
this.toast.clear();
},
showHtmlToast() {
Toast({
type: 'html',
message: '<em>HTML<em>'
})
}
}
};
</script>

View File

@ -0,0 +1,23 @@
<template><section class="demo-uploader"><h1 class="demo-title">Uploader 图片上传</h1><example-block title="基础用法">
<div class="uploader-container">
<van-uploader :after-read="logContent">
<van-icon name="photograph"></van-icon>
</van-uploader>
</div>
</example-block></section></template>
<style>
.uploader-container {
padding: 5px 15px;
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
methods: {
logContent(file) {
console.log(file)
}
}
};
</script>

View File

@ -0,0 +1,58 @@
<template><section class="demo-waterfall"><h1 class="demo-title">Waterfall 瀑布流</h1><example-block title="基础用法">
<div class="waterfall">
<div v-waterfall-lower="loadMore" v-waterfall-upper="loadMoreUpper" waterfall-disabled="isWaterfallDisabled" waterfall-offset="400">
<div class="waterfall-item" v-for="item in list" style="text-align: center;">
{{ item }}
</div>
<div v-if="loading" style="text-align: center;">
loading
</div>
</div>
</div>
</example-block></section></template>
<style>
.waterfall {
max-height: 300px;
overflow: scroll;
}
</style>
<script>
import Vue from "vue";import ExampleBlock from "components/example-block";Vue.component("example-block", ExampleBlock);
export default {
data() {
return {
list: [1, 2, 3, 4, 5],
loading: false,
finished: false
};
},
methods: {
loadMore() {
if (this.list.length >= 200) {
this.finished = true;
return;
}
this.loading = true;
setTimeout(() => {
let lastNumber = this.list[this.list.length - 1];
for (let i = 0; i < 5; i ++) {
lastNumber += 1;
this.list.push(lastNumber);
}
this.loading = false;
}, 2500);
},
loadMoreUpper() {
if (this.list[0] < 0) return;
this.list.unshift(-1);
}
},
computed: {
isWaterfallDisabled: function() {
return this.loading || this.finished;
}
}
};
</script>

View File

@ -0,0 +1,226 @@
<style>
@component-namespace demo {
@b actionsheet {
.actionsheet-wx {
color: #06BF04;
}
.van-button {
margin-left: 15px;
}
.title-actionsheet p {
padding: 20px;
}
}
}
</style>
<script>
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
data() {
return {
show1: false,
show2: false,
show3: false,
actions1: [
{
name: '微信安全支付',
className: 'actionsheet-wx',
callback: this.handleActionClick
},
{
name: '支付宝支付',
loading: true
},
{
name: '有赞E卡',
subname: '剩余260.50元)'
},
{
name: '信用卡支付'
},
{
name: '其他支付方式'
}
]
};
},
methods: {
handleActionClick(item) {
console.log(item);
}
}
}
</script>
## ActionSheet 行动按钮
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`ActionSheet`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`ActionSheet`组件了:
```js
import Vue from 'vue';
import { ActionSheet } from 'vant';
import 'vant/lib/vant-css/actionSheet.css';
Vue.component(ActionSheet.name, ActionSheet);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`ActionSheet`组件,这样只能在你注册的组件中使用`ActionSheet`
```js
import { ActionSheet } from 'vant';
export default {
components: {
'van-actionSheet': ActionSheet
}
};
```
### 代码演示
#### 基础用法
需要传入一个`actions`的属性,该属性为一个数组,数组的每一项是一个对象,可以根据下面的[action对象](#actions)设置你想要的信息。
:::demo 基础用法
```html
<van-button @click="show1 = true">弹出actionsheet</van-button>
<van-actionsheet v-model="show1" :actions="actions1">
</van-actionsheet>
<script>
export default {
data() {
return {
show1: false,
actions1: [
{
name: '微信安全支付',
className: 'actionsheet-wx',
callback: this.handleActionClick
},
{
name: '支付宝支付',
loading: true
},
{
name: '有赞E卡',
subname: '剩余260.50元)'
},
{
name: '信用卡支付'
},
{
name: '其他支付方式'
}
]
};
},
methods: {
handleActionClick(item) {
console.log(item);
}
}
}
</script>
```
:::
#### 带取消按钮的ActionSheet
如果传入了`cancelText`属性,且不为空,则会在下方显示一个取消按钮,点击会将当前`ActionSheet`关闭。
:::demo 带取消按钮的ActionSheet
```html
<van-button @click="show2 = true">弹出带取消按钮的actionsheet</van-button>
<van-actionsheet v-model="show2" :actions="actions1" cancel-text="取消">
</van-actionsheet>
<script>
export default {
data() {
return {
show2: false,
actions1: [
{
name: '微信安全支付',
className: 'actionsheet-wx',
callback: this.handleActionClick
},
{
name: '支付宝支付',
loading: true
},
{
name: '有赞E卡',
subname: '剩余260.50元)'
},
{
name: '信用卡支付'
},
{
name: '其他支付方式'
}
]
};
}
}
</script>
```
:::
#### 带标题的ActionSheet
如果传入了`title`属性,且不为空,则另外一种样式的`ActionSheet`,里面内容需要自定义。
:::demo 带标题的ActionSheet
```html
<van-button @click="show3 = true">弹出带标题的actionsheet</van-button>
<van-actionsheet v-model="show3" title="支持以下配送方式" class="title-actionsheet">
<p>一些内容</p>
</van-actionsheet>
```
:::
点击以下按钮查看手机端效果:
<van-button @click="mobileShow = true">点击查看手机端效果</van-button>
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| actions | 行动按钮数组 | `Array` | `[]` | |
| title | 标题 | `String` | | |
| cancelText | 取消按钮文案 | `String` | | |
| overlay | 是否显示遮罩 | `Boolean` | | |
| closeOnClickOverlay | 点击遮罩是否关闭`ActionSheet` | `Boolean` | | |
### actions
`API`中的`actions`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
| key | 说明 |
|-----------|-----------|
| name | 标题 |
| subname | 二级标题 |
| className | 为对应列添加特殊的`class` |
| loading | 是否是`loading`状态 |
| callback | 点击时的回调。该回调接受一个参数,参数为当前点击`action`的对象信息 |

113
docs/examples-docs/badge.md Normal file
View File

@ -0,0 +1,113 @@
<style>
@component-namespace demo {
@b badge {
.badge-group-wrapper {
padding: 30px 20px;
background-color: #fff;
}
.van-badge-group {
margin: 0 auto;
}
}
}
</style>
<script>
export default {
data() {
return {
activeKey: '2'
};
},
methods: {
onItemClick(e, data) {
this.activeKey = data.mark;
}
}
};
</script>
## Badge 徽章
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Badge`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Badge`组件了:
```js
import Vue from 'vue';
import { Badge, BadgeGroup } from 'vant';
import 'vant/lib/vant-css/badge.css';
Vue.component(Badge.name, Badge);
Vue.component(BadgeGroup.name, BadgeGroup);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Badge`组件,这样只能在你注册的组件中使用`Badge`
```js
import { Badge, BadgeGroup } from 'vant';
export default {
components: {
'van-badge': Badge,
'van-badge-group': BadgeGroup
}
};
```
### 代码演示
#### 基础用法
默认情况下激活第一个`badge`
:::demo 基础用法
```html
<div class="badge-group-wrapper">
<van-badge-group>
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
```
:::
#### 选中某个badge
如果想默认选中某个`badge`,你可以在`van-badge-group`上设置`activeKey`属性,属性值为对应的`badge`索引。
:::demo 选中某个badge
```html
<div class="badge-group-wrapper">
<van-badge-group :active-key="2">
<van-badge title="热销榜" info="8" url="http://baidu.com" @click="onItemClick"></van-badge>
<van-badge title="花式寿司" info="99" @click="onItemClick"></van-badge>
<van-badge title="火炽寿司" @click="onItemClick"></van-badge>
<van-badge title="手握寿司" info="199" @click="onItemClick"></van-badge>
</van-badge-group>
</div>
```
:::
### z-badge-group API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| active-key | 激活的`badge`的索引 | `string` | `0`但必须子badge里的mark是有`0`位索引 | |
### z-badge API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| title | badge的文案标题 | `string` | `''` | `required` |
| info | 当前badge的提示消息 | `string` | `''` | |
| url | 跳转链接 | `string` | 链接直接跳转或者hash | |

View File

@ -0,0 +1,174 @@
<style>
@component-namespace demo {
@b button {
.van-row {
padding: 0 15px;
}
.van-col {
margin-bottom: 10px;
}
}
}
</style>
## Button 按钮
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Button`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Button`组件了:
```js
import Vue from 'vue';
import { Button } from 'vant';
import 'vant/lib/vant-css/button.css';
Vue.component(Button.name, Button);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Button`组件,这样只能在你注册的组件中使用`Button`
```js
import { Button } from 'vant';
export default {
components: {
'van-button': Button
}
};
```
### 代码演示
#### 按钮功能
只接受`primary`, `default`, `danger`三种类型,默认`default`
:::demo 按钮功能
```html
<van-row>
<van-col span="24">
<van-button block>default</van-button>
</van-col>
<van-col span="24">
<van-button type="primary" block>primary</van-button>
</van-col>
<van-col span="24">
<van-button type="danger" block>danger</van-button>
</van-col>
</van-row>
```
:::
#### 禁用状态
在组件上加上`disabled`属性即可,此时按钮不可点击。
:::demo 禁用状态
```html
<van-row>
<van-col span="24">
<van-button disabled block>diabled</van-button>
</van-col>
</van-row>
```
:::
#### 按钮尺寸
只接受`large`, `normal`, `small`, `mini`四种尺寸,默认`normal``large`按钮默认100%宽度。
:::demo 按钮尺寸
```html
<van-row>
<van-col span="24">
<van-button size="large">large</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="normal">normal</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="small">small</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<van-button size="mini">mini</van-button>
</van-col>
</van-row>
```
:::
#### 自定义按钮标签
按钮默认是`button`标签,可以使用`tag`属性修改为一个`a`标签。
:::demo 自定义按钮标签
```html
<van-row>
<van-col span="24">
<van-button tag="a" type="primary" href="https://www.youzan.com" target="_blank">a标签按钮</van-button>
</van-col>
</van-row>
```
:::
#### loading按钮
`loading`状态的按钮。
:::demo loading按钮
```html
<van-row>
<van-col span="24">
<van-button type="primary" loading block>loading</van-button>
</van-col>
<van-col span="24">
<van-button loading block></van-button>
</van-col>
</van-row>
```
:::
#### 页面底部操作按钮
一般用于`fixed`在底部的区域或是`popup`弹层的底部,一般只使用`primary``normal`两种状态。
:::demo
```html
<van-row>
<van-col span="24">
<van-button type="primary" bottom-action>立即购买</van-button>
</van-col>
</van-row>
<van-row>
<van-col span="12">
<van-button bottom-action>加入购物车</van-button>
</van-col>
<van-col span="12">
<van-button type="primary" bottom-action>立即购买</van-button>
</van-col>
</van-row>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 按钮类型 | `string` | `default` | `primary`, `danger` |
| size | 按钮尺寸 | `string` | `normal` | `large`, `small`, `mini` |
| tag | 按钮标签 | `string` | `button` | `a`, `span`, ... |
| diabled | 按钮是否禁用 | `boolean` | `false` | |
| block | 按钮是否显示为块级元素 | `boolean` | `false` | |
| bottomAction | 按钮是否显示为底部行动按钮,一般显示在页面底部,有特殊样式 | `boolean` | `false` | |

View File

@ -0,0 +1,88 @@
## Card 图文组件
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Card`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Card`组件了:
```js
import Vue from 'vue';
import { Card } from 'vant';
import 'vant/lib/vant-css/card.css';
Vue.component(Card.name, Card);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Card`组件,这样只能在你注册的组件中使用`Card`
```js
import { Card } from 'vant';
export default {
components: {
'van-card': Card
}
};
```
### 代码演示
#### 基础用法
当没有底部按钮时,右侧内容会居中显示。
:::demo 基础用法
```html
<van-card
title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余"
desc="描述"
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
</van-card>
```
:::
#### 高级用法
可以使用具名`slot`重写标题等信息,其中包含`title``desc``footer``tag`四个`slot`
:::demo 高级用法
```html
<van-card
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
<span class="van-card__num">x 2</span>
</div>
<div class="van-card__footer" slot="footer">
<van-button size="mini">按钮一</van-button>
<van-button size="mini">按钮二</van-button>
</div>
</van-card>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| thumb | 左侧图片 | `string` | | |
| title | 标题 | `string` | | |
| desc | 描述 | `string` | | |
### Slot
| name | 描述 |
|-----------|-----------|
| title | 自定义标题 |
| desc | 自定义描述 |
| tags | 自定义tags |
| footer | 自定义footer |

130
docs/examples-docs/cell.md Normal file
View File

@ -0,0 +1,130 @@
<script>
export default {
methods: {
handleClick() {
console.log('cell click');
}
}
};
</script>
## Cell 单元格
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Cell`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Cell`组件了:
```js
import Vue from 'vue';
import { Cell } from 'vant';
import 'vant/lib/vant-css/cell.css';
Vue.component(Cell.name, Cell);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Cell`组件,这样只能在你注册的组件中使用`Cell`
```js
import { Cell } from 'vant';
export default {
components: {
'van-cell': Cell
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-cell-group>
<van-cell title="单元格1" value="单元格1内容"></van-cell>
<van-cell title="单元格2" value="单元格2内容"></van-cell>
</van-cell-group>
```
:::
#### 标题带描述信息
传入`label`属性,属性值为描述信息的值。
:::demo 标题带描述信息
```html
<van-cell-group>
<van-cell title="单元格1" label="描述信息" is-link url="javascript:void(0)" @click="handleClick"></van-cell>
<van-cell title="单元格2" label="描述信息"></van-cell>
</van-cell-group>
```
:::
#### 带图标
传入`icon`属性。
:::demo 带图标
```html
<van-cell-group>
<van-cell title="起码运动馆" icon="home"></van-cell>
<van-cell title="线下门店" icon="location"></van-cell>
</van-cell-group>
```
:::
#### 可点击的链接
传入`url`属性,传入`isLink`属性则会在右侧显示箭头。
:::demo 可点击的链接
```html
<van-cell-group>
<van-cell title="起码运动馆" value="进入店铺" icon="home" url="http://youzan.com" is-link></van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link></van-cell>
</van-cell-group>
```
:::
#### 高级用法
如以上用法不能满足你的需求,可以使用对应的`slot`来自定义显示的内容。包含三个`slot`,默认`slot``icon``title``slot`
:::demo 高级用法
```html
<van-cell-group>
<van-cell value="进入店铺" icon="home" url="http://youzan.com" is-link>
<template slot="title">
<span class="van-cell-text">起码运动馆</span>
<van-tag type="danger">官方</van-tag>
</template>
</van-cell>
<van-cell title="线下门店" icon="location" url="http://youzan.com" is-link></van-cell>
</van-cell-group>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| icon | 左侧图标 | `string` | | |
| title | 左侧标题 | `string` | | |
| value | 右侧内容 | `string` | | |
| isLink | 是否为链接,链接会在右侧出现箭头 | `boolean` | | |
| url | 跳转链接 | `string` | | |
| label | 描述信息,显示在标题下方 | `string` | | |
### Slot
| name | 描述 |
|-----------|-----------|
| - | 自定义显示内容 |
| icon | 自定义`icon` |
| title | 自定义`title` |

View File

@ -0,0 +1,230 @@
<style>
@component-namespace demo {
@b checkbox {
.van-checkbox-wrapper {
padding: 0 20px;
.van-checkbox {
margin: 10px 0;
}
}
}
}
</style>
<script>
export default {
data() {
return {
checkbox1: true,
checkbox2: true,
list: [
'a',
'b',
'c'
],
result: ['a', 'b']
};
},
watch: {
result(val) {
console.log(val);
}
}
};
</script>
## Checkbox 复选框
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Checkbox`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Checkbox`组件了:
```js
import Vue from 'vue';
import { Checkbox, CheckboxGroup } from 'vant';
import 'vant/lib/vant-css/checkbox.css';
Vue.component(Checkbox.name, Checkbox);
Vue.component(CheckboxGroup.name, CheckboxGroup);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Checkbox`组件,这样只能在你注册的组件中使用`Checkbox`
```js
import { Checkbox, CheckboxGroup } from 'vant';
export default {
components: {
'van-checkbox': Checkbox,
'van-checkbox-group': CheckboxGroup
}
};
```
### 代码演示
#### 基础用法
通过`v-model`绑定值即可。当`Checkbox`选中时,绑定的值即为`true`,否则为`false`。当单个`Checkbox`使用时,更建议使用`Switch`组件。
:::demo 基础用法
```html
<div class="van-checkbox-wrapper">
<van-checkbox v-model="checkbox1">复选框1</van-checkbox>
</div>
<script>
export default {
data() {
return {
checkbox1: true
};
}
};
</script>
```
:::
#### 禁用状态
设置`disabled`属性即可,此时`Checkbox`不能点击。
:::demo 禁用状态
```html
<div class="van-checkbox-wrapper">
<van-checkbox v-model="checkbox2">复选框2</van-checkbox>
</div>
<script>
export default {
data() {
return {
checkbox2: true
};
}
};
</script>
```
:::
#### Checkbox组
需要与`van-checkbox-group`一起使用,值通过`v-model`绑定在`van-checkbox-group`上,例如下面的`result`,此时`result`的值是一个数组。数组中的项即为选中的`Checkbox``name`属性设置的值。
:::demo Checkbox组
```html
<div class="van-checkbox-wrapper">
<van-checkbox-group v-model="result">
<van-checkbox v-for="item in list" :name="item">复选框{{item}}</van-checkbox>
</van-checkbox-group>
</div>
<script>
export default {
data() {
return {
list: [
'a',
'b',
'c'
],
result: ['a', 'b']
};
},
watch: {
result(val) {
console.log(val);
}
}
};
</script>
```
:::
#### 禁用Checkbox组
禁用`van-checkbox-group`,此时整个组都不可点击。
:::demo 禁用Checkbox组
```html
<div class="van-checkbox-wrapper">
<van-checkbox-group v-model="result" disabled>
<van-checkbox v-for="item in list" :name="item">复选框{{item}}</van-checkbox>
</van-checkbox-group>
</div>
<script>
export default {
data() {
return {
list: [
'a',
'b',
'c'
],
result: ['a', 'b']
};
}
};
</script>
```
:::
#### 与Cell组件一起使用
此时你需要再引入`Cell``CellGroup`组件。
:::demo 与Cell组件一起使用
```html
<van-checkbox-group v-model="result">
<van-cell-group>
<van-cell v-for="item in list">
<van-checkbox :name="item">复选框{{item}}</van-checkbox>
</van-cell>
</van-cell-group>
</van-checkbox-group>
<script>
export default {
data() {
return {
list: [
'a',
'b',
'c'
],
result: ['a', 'b']
};
}
};
</script>
```
:::
### Checkbox API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| name | 根据这个来判断radio是否选中 | `boolean` | `false` | |
### CheckboxGroup API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
### CheckboxGroup Event
| 事件名称 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| change | 当绑定值变化时触发的事件 | 当前组件的值 |

View File

@ -0,0 +1,159 @@
<script>
export default {
data() {
return {
minHour: 10,
maxHour: 20,
minDate: new Date(),
currentDate: null
};
},
methods: {
handlePickerChange(picker, values) {
// picker.setColumnValues(1, citys[values[0]]);
console.log(values);
},
handlePickerCancel() {
alert('picker cancel');
},
handlePickerConfirm() {
alert('picker confirm');
}
}
};
</script>
## Datetime Picker 时间选择
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Radio`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Radio`组件了:
```js
import Vue from 'vue';
import { DatetimePicker } from 'vant';
Vue.component(DatetimePicker.name, DatetimePicker);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`DatetimePicker`组件,这样只能在你注册的组件中使用`DatetimePicker`
```js
import { DatetimePicker } from 'vant';
export default {
components: {
'van-datetime-picker': DatetimePicker
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-datetime-picker
v-model="currentDate"
type="datetime"
format="yyyy.mm.dd hh时 mm分"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
@change="handlePickerChange">
</van-datetime-picker>
<script>
export default {
data() {
return {
minHour: 10,
maxHour: 20,
minDate: new Date()
};
},
methods: {
handlePickerChange(picker, values) {
picker.setColumnValues(1, citys[values[0]]);
}
}
};
</script>
```
:::
#### 选择日期
:::demo 选择日期
```html
<van-datetime-picker
v-model="currentDate"
type="date"
format="yyyy.mm.dd hh时 mm分"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
@change="handlePickerChange">
</van-datetime-picker>
```
:::
#### 选择时间
:::demo 选择时间
```html
<van-datetime-picker
v-model="currentDate"
type="time"
format="yyyy.mm.dd hh时 mm分"
:min-hour="minHour"
:max-hour="maxHour"
:min-date="minDate"
@change="handlePickerChange">
</van-datetime-picker>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| visibileColumnCount | 每一列可见备选元素的个数 | Number | 5 | |
| itemHeight | 选中元素区高度 | Number | 44 | |
| columns | 对象数组,配置每一列显示的数据 | Array | | |
| showToolbar | 是否在组件顶部显示一个toolbar | Boolean | true | |
### columns
`API`中的`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
| key | 说明 |
|-----------|-----------|
| values | 列中对应的备选值 |
| defaultIndex | 初始选中值的索引默认为0 |
| className | 为对应列添加特殊的`class` |
### change事件
`change`事件中,可以获取到`picker`实例,对`picker`进行相应的更新等操作:
| 函数 | 说明 |
|-----------|-----------|
| getColumnValue(index) | 获取对应列中选中的值 |
| setColumnValue(index, value) | 设置对应列中选中的值 |
| getColumnValues(index) | 获取对应列中所有的备选值 |
| setColumnValues(index, values) | 设置对应列中所有的备选值 |
| getValues() | 获取所有列中被选中的值,返回一个数组 |
| setValues(values) | `values`为一个数组,设置所有列中被选中的值 |

View File

@ -0,0 +1,145 @@
<style>
@component-namespace demo {
@b dialog {
.van-button {
margin: 15px;
}
}
}
</style>
<script>
import { Dialog } from 'src/index';
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
methods: {
handleAlertClick() {
Dialog.alert({
title: 'alert标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
});
},
handleAlert2Click() {
Dialog.alert({
message: '无标题alert'
}).then((action) => {
console.log(action);
});
},
handleConfirmClick() {
Dialog.confirm({
title: 'confirm标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
}, (error) => {
console.log(error);
});
}
}
};
</script>
## Dialog 弹出框
### 使用指南
`Dialog`和其他组件不同不是通过HTML结构的方式来使用而是通过函数调用的方式。使用前需要先引入它它接受一个数组作为参数数组中的每一项对应了图片链接。
```js
import { Dialog } from 'vant';
```
### 代码演示
#### 消息提示
用于提示一些消息,只包含一个确认按钮。
:::demo 消息提示
```html
<van-button @click="handleAlertClick">alert</van-button>
<van-button @click="handleAlert2Click">无标题alert</van-button>
<script>
export default {
methods: {
handleAlertClick() {
Dialog.alert({
title: 'alert标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
});
},
handleAlert2Click() {
Dialog.alert({
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
});
}
}
};
</script>
```
:::
#### 消息确认
用于确认消息,包含取消和确认按钮。
:::demo 消息确认
```html
<van-button @click="handleConfirmClick">confirm</van-button>
<script>
export default {
methods: {
handleConfirmClick() {
Dialog.confirm({
title: 'confirm标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
}, (error) => {
console.log(error);
});
}
}
};
</script>
```
:::
点击以下按钮查看手机端效果:
<van-button @click="mobileShow = true">点击查看手机端效果</van-button>
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
### 方法
#### Dialog.alert(options)
消息提示时使用该方法。
#### Dialog.confirm(options)
消息确认时使用该方法。
### Options
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| title | 标题 | `string` | | |
| message | 内容 | `string` | | |
| confirmButtonText | 确认按钮的文案 | `string` | `确认` | |
| cancelButtonText | 取消按钮的文案 | `string` | `取消` | |

147
docs/examples-docs/field.md Normal file
View File

@ -0,0 +1,147 @@
<style>
@component-namespace demo {
@b field {
.van-field-wrapper {
padding: 0 10px;
}
}
}
</style>
<script>
export default {
data() {
return {
username: 'zhangmin'
};
}
};
</script>
## Field 输入框
表单中`input``textarea`的输入框。
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Field`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Field`组件了:
```js
import Vue from 'vue';
import { Field } from 'vant';
import 'vant/lib/vant-css/field.css';
Vue.component(Field.name, Field);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Field`组件,这样只能在你注册的组件中使用`Field`
```js
import { Field } from 'vant';
export default {
components: {
'van-field': Field
}
};
```
### 代码演示
#### 基础用法
根据`type`属性显示不同的输入框。
:::demo 基础用法
```html
<van-cell-group>
<van-field type="text" label="用户名:" placeholder="请输入用户名" v-model="username" required></van-field>
<van-field type="password" label="密码:" placeholder="请输入密码" required></van-field>
<van-field type="textarea" label="个人介绍:" placeholder="请输入个人介绍" required></van-field>
</van-cell-group>
```
:::
#### 无label的输入框
不传入`label`属性即可。
:::demo 无label的输入框
```html
<van-cell-group>
<van-field type="text" placeholder="请输入用户名"></van-field>
</van-cell-group>
```
:::
#### 带border的输入框
传入一个`border`属性。
:::demo 带border的输入框
```html
<div class="van-field-wrapper">
<van-field type="text" placeholder="请输入用户名" border></van-field>
</div>
```
:::
#### 禁用的输入框
传入`disabled`属性即可。
:::demo 禁用的输入框
```html
<van-cell-group>
<van-field label="用户名:" type="text" placeholder="请输入用户名" v-model="username" disabled></van-field>
</van-cell-group>
```
:::
#### 错误的输入框
传入`error`属性即可。
:::demo 错误的输入框
```html
<van-cell-group>
<van-field label="用户名:" type="text" placeholder="请输入用户名" error></van-field>
</van-cell-group>
```
:::
#### Autosize的输入框(仅支持textarea)
传入`autosize`属性, 且将`rows`设为1。
:::demo 错误的输入框
```html
<van-cell-group>
<van-field label="留言:" type="textarea" placeholder="请输入留言" rows="1" autosize></van-field>
</van-cell-group>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 输入框类型 | `string` | `text` | `text`, `number`, `email`, `url`, `tel`, `date`, `datetime`, `password`, `textarea` |
| placeholder | 输入框placeholder | `string` | | |
| value | 输入框的值 | `string` | | |
| label | 输入框标签 | `string` | | |
| disabled | 是否禁用输入框 | `boolean` | `false` | |
| error | 输入框是否有错误 | `boolean` | `false` | |
| readonly | 输入框是否只读 | `boolean` | `false` | |
| maxlength | 输入框maxlength | `string`, `number` | | |
| rows | textarea rows | `string`, `number` | | |
| cols | textarea cols | `string`, `number` | | |
| autosize | 自动调整高度(仅支持textarea) | `boolean` | `false` | `true`, `false` |

200
docs/examples-docs/icon.md Normal file
View File

@ -0,0 +1,200 @@
<style>
@component-namespace demo {
@b icon {
.van-col {
text-align: center;
}
.van-icon {
font-size: 45px;
display: block;
margin: 15px 0;
}
}
}
</style>
## Icon 图标
### 使用指南
如果你已经按照快速上手中引入了整个,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Icon`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Icon`组件了:
```js
import Vue from 'vue';
import { Icon } from 'vant';
import 'vant/lib/vant-css/icon.css';
Vue.component(Icon.name, Icon);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Icon`组件,这样只能在你注册的组件中使用`Icon`
```js
import { Icon } from 'vant';
export default {
components: {
'van-icon': Icon
}
};
```
### 代码演示
#### 基础用法
设置`name`属性为对应的图标名称即可,以下目前有的所有图标:
:::demo 所有Icon
```html
<van-row>
<van-col span="8">
<van-icon name="qr-invalid"></van-icon>
<span>qr-invalid</span>
</van-col>
<van-col span="8">
<van-icon name="qr"></van-icon>
<span>qr</span>
</van-col>
<van-col span="8">
<van-icon name="exchange"></van-icon>
<span>exchange</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="close"></van-icon>
<span>close</span>
</van-col>
<van-col span="8">
<van-icon name="location"></van-icon>
<span>location</span>
</van-col>
<van-col span="8">
<van-icon name="upgrade"></van-icon>
<span>upgrade</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="check"></van-icon>
<span>check</span>
</van-col>
<van-col span="8">
<van-icon name="checked"></van-icon>
<span>checked</span>
</van-col>
<van-col span="8">
<van-icon name="like-o"></van-icon>
<span>like-o</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="like" style="color: red;"></van-icon>
<span>like</span>
</van-col>
<van-col span="8">
<van-icon name="chat"></van-icon>
<span>chat</span>
</van-col>
<van-col span="8">
<van-icon name="shop"></van-icon>
<span>shop</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="photograph"></van-icon>
<span>photograph</span>
</van-col>
<van-col span="8">
<van-icon name="add"></van-icon>
<span>add</span>
</van-col>
<van-col span="8">
<van-icon name="add2"></van-icon>
<span>add2</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="photo"></van-icon>
<span>photo</span>
</van-col>
<van-col span="8">
<van-icon name="logistics"></van-icon>
<span>logistics</span>
</van-col>
<van-col span="8">
<van-icon name="edit"></van-icon>
<span>edit</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="passed"></van-icon>
<span>passed</span>
</van-col>
<van-col span="8">
<van-icon name="cart"></van-icon>
<span>cart</span>
</van-col>
<van-col span="8">
<van-icon name="arrow"></van-icon>
<span>arrow</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="gift"></van-icon>
<span>gift</span>
</van-col>
<van-col span="8">
<van-icon name="search"></van-icon>
<span>search</span>
</van-col>
<van-col span="8">
<van-icon name="clear"></van-icon>
<span>clear</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="success"></van-icon>
<span>success</span>
</van-col>
<van-col span="8">
<van-icon name="fail"></van-icon>
<span>fail</span>
</van-col>
<van-col span="8">
<van-icon name="contact"></van-icon>
<span>contact</span>
</van-col>
</van-row>
<van-row>
<van-col span="8">
<van-icon name="wechat"></van-icon>
<span>wechat</span>
</van-col>
<van-col span="8">
<van-icon name="alipay"></van-icon>
<span>alipay</span>
</van-col>
</van-row>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| name | icon名称 | `string` | `''` | |

View File

@ -0,0 +1,74 @@
<style>
@component-namespace demo {
@b image-preview {
.van-button {
margin-left: 15px;
}
}
}
</style>
<script>
import { ImagePreview } from 'src/index';
import MobileComputed from 'components/mobile-computed';
export default {
mixins: [MobileComputed],
methods: {
handleImagePreview() {
ImagePreview([
'https://img.yzcdn.cn/upload_files/2017/03/15/FkubrzN7AgGwLlTeb1E89-T_ZjBg.png',
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]);
}
}
};
</script>
## ImagePreview 图片预览
### 使用指南
`ImagePreview`和其他组件不同不是通过HTML结构的方式来使用而是通过函数调用的方式。使用前需要先引入它。
```js
import { ImagePreview } from 'vant';
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-button @click="handleImagePreview">预览图片</van-button>
<script>
import { ImagePreview } from 'src/index';
export default {
methods: {
handleImagePreview() {
ImagePreview([
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]);
}
}
};
</script>
```
:::
点击以下按钮查看手机端效果:
<van-button @click="mobileShow = true">点击查看手机端效果</van-button>
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
### 方法参数
| 参数名 | 说明 | 类型 |
|-----------|-----------|-----------|
| imageUrls | 需要预览的图片 | `Array` |

View File

@ -0,0 +1,7 @@
## 安装
### ynpm安装
```shell
npm i vant -S
```

View File

@ -0,0 +1,134 @@
<style>
@component-namespace demo {
@b layout {
.van-row {
padding: 0 20px;
}
.van-col {
margin-bottom: 10px;
}
}
}
.gray {
height: 30px;
line-height: 30px;
font-size: 12px;
background: #666;
color: #fff;
text-align: center;
}
.white {
height: 30px;
line-height: 30px;
font-size: 12px;
background: #fff;
color: #333;
text-align: center;
}
</style>
## Layout 布局
主要提供了`van-row``van-col`两个组件来进行行列布局。
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Row``Col`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Row``Col`组件了:
```js
import Vue from 'vue';
import { Row, Col } from 'vant';
import 'vant/lib/vant-css/col.css';
import 'vant/lib/vant-css/row.css';
Vue.component(Row.name, Row);
Vue.component(Col.name, Col);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Row``Col`组件,这样只能在你注册的组件中使用`Row``Col`
```js
import { Row, Col } from 'vant';
export default {
components: {
'van-row': Row,
'van-col': Col
}
};
```
### 代码演示
#### 常规用法
Layout组件提供了`24列栅格`,通过在`van-col`上添加`span`属性设置列所占的宽度百分比`(span / 24)`;此外,添加`offset`属性可以设置列的偏移宽度计算方式与span相同。
:::demo 常规用法
```html
<van-row>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="white">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
</van-row>
<van-row>
<van-col span="4">
<div class="gray">span: 4</div>
</van-col>
<van-col span="10" offset="4">
<div class="gray">offset: 4, span: 10</div>
</van-col>
</van-row>
<van-row>
<van-col offset="12" span="12">
<div class="gray">offset: 12, span: 12</div>
</van-col>
</van-row>
```
:::
#### 在列元素之间增加间距
列元素之间默认间距为0如果希望在列元素增加相同的间距可以在`van-row`上添加`gutter`属性来设置列元素之间的间距。
:::demo 在列元素之间增加间距
```html
<van-row gutter="10">
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
<van-col span="8">
<div class="gray">span: 8</div>
</van-col>
</van-row>
```
:::
### API
#### Row
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| gutter | 列元素之间的间距单位为px | `String | Number` | - | |
#### Column
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| span | 列元素宽度 | `String | Number` | - | |
| offset | 列元素偏移宽度 | `String | Number` | - | |

View File

@ -0,0 +1,169 @@
<style>
@component-namespace demo {
@b lazyload {
.lazy-img {
display: block;
width: 100%;
height: auto;
}
.lazy-background {
height: 300px;
background-size: cover;
background-repeat: no-repeat;
}
}
}
</style>
<script>
export default {
data() {
return {
imageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL',
'https://img.yzcdn.cn/upload_files/2016/01/27/FpWD3kX18w8qjM6faH-4JqOWHsF4',
'https://img.yzcdn.cn/upload_files/2016/09/08/9ff28d555e5760fa830344f12efa0087.jpg',
'https://img.yzcdn.cn/upload_files/2016/11/13/FlZIeSgbSANSPkmUHttMjoIgY3cv.jpg',
'https://img.yzcdn.cn/upload_files/2016/12/12/FuxgsGPRnupGu_eaMuaR8W0DuSKp.jpeg'
],
backgroundImageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL'
],
componentImageList: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
]
};
},
methods: {
handleComponentShow() {
console.log('component show');
}
}
}
</script>
## Lazyload 图片懒加载
### 使用指南
`Lazyload``Vue`指令,所以需要使用它必须将它注册到`Vue`的指令中。
```js
import Vue from 'vue';
import { Lazyload } from 'vant';
Vue.use(Lazyload, options);
```
### 代码演示
#### 基础用法
比如商品详情页很多图片的情况需要对图片进行懒加载,只需将`v-lazy`指令的值设置为你需要懒加载的图片。
:::demo 基础用法
```html
<ul class="image-list" ref="container">
<li v-for="img in imageList">
<img class="lazy-img" v-lazy="img">
</li>
</ul>
<script>
export default {
data() {
return {
imageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL',
'https://img.yzcdn.cn/upload_files/2016/01/27/FpWD3kX18w8qjM6faH-4JqOWHsF4',
'https://img.yzcdn.cn/upload_files/2016/09/08/9ff28d555e5760fa830344f12efa0087.jpg',
'https://img.yzcdn.cn/upload_files/2016/11/13/FlZIeSgbSANSPkmUHttMjoIgY3cv.jpg',
'https://img.yzcdn.cn/upload_files/2016/12/12/FuxgsGPRnupGu_eaMuaR8W0DuSKp.jpeg'
]
};
}
}
</script>
```
:::
#### 背景图懒加载
和图片懒加载不同的背景图懒加载需要使用`v-lazy:background-image`,值设置为背景图片的地址。还有一个需要注意的是你需要设置容器的样式,否则高度不会撑开。
:::demo 背景图懒加载
```html
<ul class="image-list" ref="container">
<li v-for="img in backgroundImageList">
<div class="lazy-background" v-lazy:background-image="img"></div>
</li>
</ul>
<script>
export default {
data() {
return {
backgroundImageList: [
'https://img.yzcdn.cn/upload_files/2016/01/27/Fo2dFWjXYzWDR9Jaa1AEqk1jt7e0',
'https://img.yzcdn.cn/upload_files/2016/01/27/FkyhiZfVE8tx-4qjxR2VeiqsSZYL'
]
};
}
}
</script>
```
:::
#### 懒加载模块
懒加载模块需要使用到`lazy-component`,将需要懒加载的内容放在`lazy-component`中即可。
:::demo 懒加载模块
```html
<lazy-component @show="handleComponentShow">
<ul class="image-list">
<li v-for="img in componentImageList">
<img class="lazy-img" v-lazy="img">
</li>
</ul>
</lazy-component>
<script>
export default {
data() {
return {
componentImageList: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
]
};
},
methods: {
handleComponentShow() {
console.log('component show');
}
}
}
</script>
```
:::
### Options
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| loading | 加载时的图片 | `string` | | |
| error | 错误时的图片 | `string` | | |
| preload | 预加载高度的比例 | `string` | | |
| attempt | 尝试次数 | `number` | `3` | |
| listenEvents | 监听的事件 | `Array` | `['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']` | |
| adapter | 适配器 | `Object` | | |
| filter | 图片url过滤 | `Object` | | |
| lazyComponent | 是否能懒加载模块 | `boolean` | `false` | |

View File

@ -0,0 +1,89 @@
<style>
@component-namespace demo {
@b loading {
.van-loading {
margin: 0 auto;
}
.circle-loading {
margin: 20px auto;
}
.demo-loading__example--with-bg {
background-color: rgba(0, 0, 0, 0.5);
margin: 0 auto;
width: 80px;
padding: 25px 0;
border-radius: 10px;
}
}
}
</style>
## Loading 加载
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Loading`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Loading`组件了:
```js
import Vue from 'vue';
import { Loading } from 'vant';
import 'vant/lib/vant-css/loading.css';
Vue.component(Loading.name, Loading);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Loading`组件,这样只能在你注册的组件中使用`Loading`
```js
import { Loading } from 'vant';
export default {
components: {
'van-loading': Loading
}
};
```
### 代码演示
#### 渐变深色spinner
:::demo 渐变深色spinner
```html
<van-loading class="some-customized-class"></van-loading>
```
:::
#### 渐变浅色spinner
:::demo 渐变浅色spinner
```html
<div class="demo-loading__example demo-loading__example--with-bg">
<van-loading class="some-customized-class" :color="'white'"></van-loading>
</div>
```
:::
#### 单色spinner
:::demo 单色spinner
```html
<van-loading class="circle-loading" :type="'circle'" :color="'white'"></van-loading>
<van-loading class="circle-loading" :type="'circle'" :color="'black'"></van-loading>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| color | `loading`颜色 | `string` | `black` | `black`, `white` |
| type | `loading`类型 | `string` | `gradient-circle` | `gradient-circle`, `circle` |

130
docs/examples-docs/panel.md Normal file
View File

@ -0,0 +1,130 @@
<style>
@component-namespace demo {
@b panel {
.van-panel-sum {
background: #fff;
text-align: right;
font-size: 14px;
color: #333;
line-height: 30px;
padding-right: 15px;
span {
color: red;
}
}
.van-panel-buttons {
text-align: right;
.van-button {
margin-left: 5px;
}
}
.panel-content {
padding: 20px;
}
}
}
</style>
## Panel 面板
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Panel`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Panel`组件了:
```js
import Vue from 'vue';
import { Panel } from 'vant';
import 'vant/lib/vant-css/panel.css';
Vue.component(Panel.name, Panel);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Panel`组件,这样只能在你注册的组件中使用`Panel`
```js
import { Panel } from 'vant';
export default {
components: {
'van-panel': Panel
}
};
```
### 代码演示
#### 基础用法
面板只是一个容器,里面可以放入自定义的内容。
:::demo 基础用法
```html
<van-panel title="标题" desc="标题描述" status="状态">
<div class="panel-content">
panel内容
</div>
</van-panel>
```
:::
#### 高级用法
使用`slot`自定义内容。比如在自定义内容中放入一个`van-card`
:::demo 高级用法
```html
<van-panel title="标题" desc="标题描述" status="状态">
<van-card
title="商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余"
desc="商品SKU1商品SKU2"
thumb="https://img.yzcdn.cn/upload_files/2017/02/17/FnDwvwHmU-OiqsbjAO5X7wh1KWrR.jpg!100x100.jpg">
<div class="van-card__row" slot="title">
<h4 class="van-card__title">商品名称是什么,两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余两行显示状态如效果图,多余多余多余</h4>
<span class="van-card__price">¥ 2.00</span>
</div>
<div class="van-card__row" slot="desc">
<h4 class="van-card__desc">商品sku</h4>
<span class="van-card__num">x 2</span>
</div>
<div class="van-card__footer" slot="footer">
<van-button size="mini">按钮一</van-button>
<van-button size="mini">按钮二</van-button>
</div>
</van-card>
<div class="van-panel-sum">
合计:<span>¥ 1999.90</span>
</div>
<div class="van-panel-buttons" slot="footer">
<van-button size="small">按钮一</van-button>
<van-button size="small" type="danger">按钮二</van-button>
</div>
</van-panel>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| title | 标题 | `string` | | |
| desc | 描述 | `string` | | |
| status | 状态 | `string` | | |
### Slot
| name | 描述 |
|-----------|-----------|
| - | 自定义内容 |
| header | 自定义header |
| footer | 自定义footer |

View File

@ -0,0 +1,186 @@
<script>
const citys = {
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
};
export default {
data() {
return {
pickerColumns: [
{
values: Object.keys(citys),
className: 'column1'
},
{
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
className: 'column2'
}
]
};
},
methods: {
handlePickerChange(picker, values) {
picker.setColumnValues(1, citys[values[0]]);
},
handlePickerCancel() {
alert('picker cancel');
},
handlePickerConfirm() {
alert('picker confirm');
}
}
};
</script>
## Picker 选择器
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Picker`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Picker`组件了:
```js
import Vue from 'vue';
import { Picker } from 'vant';
import 'vant/lib/vant-css/picker.css';
Vue.component(Picker.name, Picker);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Picker`组件,这样只能在你注册的组件中使用`Picker`
```js
import { Picker } from 'vant';
export default {
components: {
'van-picker': Picker
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-picker :columns="pickerColumns" @change="handlePickerChange"></van-picker>
<script>
const citys = {
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
};
export default {
data() {
return {
pickerColumns: [
{
values: Object.keys(citys),
className: 'column1'
},
{
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
className: 'column2'
}
]
};
},
methods: {
handlePickerChange(picker, values) {
picker.setColumnValues(1, citys[values[0]]);
}
}
};
</script>
```
:::
#### 带toolbar的Picker
:::demo 带toolbar的Picker
```html
<van-picker :columns="pickerColumns" show-toolbar @change="handlePickerChange" @cancel="handlePickerCancel" @confirm="handlePickerConfirm"></van-picker>
<script>
const citys = {
'浙江': ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
'福建': ['福州', '厦门', '莆田', '三明', '泉州', '漳州', '南平', '龙岩', '宁德'],
'湖南': ['长沙', '株洲', '湘潭', '衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底', '湘西土家族苗族自治州']
};
export default {
data() {
return {
pickerColumns: [
{
values: Object.keys(citys),
className: 'column1'
},
{
values: ['杭州', '宁波', '温州', '嘉兴', '湖州', '绍兴', '金华', '衢州', '舟山', '台州', '丽水'],
className: 'column2'
}
]
};
},
methods: {
handlePickerChange(picker, values) {
picker.setColumnValues(1, citys[values[0]]);
},
handlePickerCancel() {
alert('picker cancel');
},
handlePickerConfirm() {
alert('picker confirm');
}
}
};
</script>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| visibileColumnCount | 每一列可见备选元素的个数 | `number` | `5` | |
| itemHeight | 选中元素区高度 | `number` | `44` | |
| columns | 对象数组,配置每一列显示的数据 | `Array` | | |
| showToolbar | 是否在组件顶部显示一个toolbar | `Boolean` | `true` | |
### columns
`API`中的`columns`为一个对象数组,数组中的每一个对象配置每一列,每一列有以下`key`
| key | 说明 |
|-----------|-----------|
| values | 列中对应的备选值 |
| defaultIndex | 初始选中值的索引默认为0 |
| className | 为对应列添加特殊的`class` |
### change事件
`change`事件中,可以获取到`picker`实例,对`picker`进行相应的更新等操作:
| 函数 | 说明 |
|-----------|-----------|
| getColumnValue(index) | 获取对应列中选中的值 |
| setColumnValue(index, value) | 设置对应列中选中的值 |
| getColumnValues(index) | 获取对应列中所有的备选值 |
| setColumnValues(index, values) | 设置对应列中所有的备选值 |
| getValues() | 获取所有列中被选中的值,返回一个数组 |
| setValues(values) | `values`为一个数组,设置所有列中被选中的值 |

204
docs/examples-docs/popup.md Normal file
View File

@ -0,0 +1,204 @@
<style>
@component-namespace demo {
@b popup {
.van-button {
margin: 10px 15px;
}
.van-popup-1 {
width: 60%;
box-sizing: border-box;
padding: 20px;
border-radius: 5px;
text-align: center;
}
.van-popup-2 {
width: 100%;
height: 200px;
box-sizing: border-box;
padding: 20px;
}
.van-popup-3 {
line-height: 50px;
text-align: center;
background-color: rgba(0, 0, 0, 0.701961);
color: #fff;
}
.van-popup-4,
.van-popup-5 {
width: 100%;
height: 100%;
}
}
}
</style>
<script>
import MobileComputed from 'components/mobile-computed';
import Dialog from 'packages/dialog';
export default {
mixins: [MobileComputed],
data() {
return {
popupShow1: false,
popupShow2: false,
popupShow3: false,
popupShow4: false,
popupShow5: false
}
},
watch: {
popupShow3(val) {
if (val) {
setTimeout(() => {
this.popupShow3 = false;
}, 2000);
}
}
},
methods: {
showDialog() {
Dialog.confirm({
title: 'confirm标题',
message: '弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。弹窗提示文字左右始终距离边20PX上下距离20PX文字左对齐。'
}).then((action) => {
console.log(action);
}, (error) => {
console.log(error);
});
}
}
};
</script>
## Popup 弹出菜单
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Popup`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Popup`组件了:
```js
import Vue from 'vue';
import { Popup } from 'vant';
import 'vant/lib/vant-css/popup.css';
Vue.component(Popup.name, Popup);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Popup`组件,这样只能在你注册的组件中使用`Popup`
```js
import { Popup } from 'vant';
export default {
components: {
'van-popup': Popup
}
};
```
### 代码演示
#### 基础用法
`popup`默认情况下是从中间弹出。
:::demo 基础用法
```html
<van-button @click="popupShow1 = true">从中间弹出popup</van-button>
<van-popup v-model="popupShow1" class="van-popup-1" :lock-on-scroll="true">
从中间弹出popup
</van-popup>
<script>
export default {
data() {
return {
popupShow1: false
}
}
};
</script>
```
:::
#### 从不同位置弹出菜单
可以设置`position`属性,`popup`即能从不同位置弹出,`position`的可选值有`top``bottom``right``left`
:::demo 从不同位置弹出菜单
```html
<van-button @click="popupShow2 = true;">从下方弹出popup</van-button>
<van-popup v-model="popupShow2" position="bottom" class="van-popup-2">
<van-button @click="showDialog">弹出dialog</van-button>
</van-popup>
<van-button @click="popupShow3 = true">从上方弹出popup</van-button>
<van-popup v-model="popupShow3" position="top" class="van-popup-3" :overlay="false">
更新成功
</van-popup>
<van-button @click="popupShow4 = true">从右方弹出popup</van-button>
<van-popup v-model="popupShow4" position="right" class="van-popup-4" :overlay="false">
<van-button @click.native="popupShow4 = false">关闭 popup</van-button>
</van-popup>
<van-button @click="popupShow5 = true">从左方弹出popup</van-button>
<van-popup v-model="popupShow5" position="left" class="van-popup-5" :overlay="false">
<van-button @click.native="popupShow5 = false">关闭 popup</van-button>
</van-popup>
<script>
export default {
data() {
return {
popupShow1: false,
popupShow2: false,
popupShow3: false,
popupShow4: false
}
},
watch: {
popupShow2(val) {
if (val) {
setTimeout(() => {
this.popupShow2 = false;
}, 2000);
}
}
}
};
</script>
```
:::
点击以下按钮查看手机端效果:
<van-button @click="mobileShow = true">点击查看手机端效果</van-button>
<mobile-popup v-model="mobileShow" :url="mobileUrl"></mobile-popup>
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| value | 利用`v-model`绑定当前组件是否显示 | `boolean` | `false` | `true`, `false` |
| overlay | 是否显示背景遮罩层 | `boolean` | `true` | `true`, `false` |
| lockOnScroll | 背景是否跟随滚动 | `boolean` | `false` | `true`, `false` |
| position | 弹出菜单位置 | `string` | | `top`, `bottom`, `right`, `left` |
| closeOnClickOverlay | 点击遮罩层是否关闭弹出菜单 | `boolean` | `true` | `true`, `false` |
| transition | 弹出菜单的`transition` | `string` | `popup-slide` | |

View File

@ -0,0 +1,112 @@
<style>
@component-namespace demo {
@b progress {
@e wrapper {
padding: 5px;
margin: 20px 10px;
}
}
}
</style>
## Progress 进度条
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Progress`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Progress`组件了:
```js
import Vue from 'vue';
import { Progress } from 'vant';
import 'vant/lib/vant-css/progress.css';
Vue.component(Progress.name, Progress);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Progress`组件,这样只能在你注册的组件中使用`Progress`
```js
import { Progress } from 'vant';
export default {
components: {
'van-progress': Progress
}
};
```
### 代码演示
#### 基础用法
默认情况进度条为蓝色,使用`percentage`属性来设置当前进度。
:::demo 基础用法
```html
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :percentage="0"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo2" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :percentage="100"></van-progress>
</div>
```
:::
#### Inactive
是否置灰进度条,一般用于进度条被取消时。
:::demo Inactive
```html
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :inactive="true" :percentage="0"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo2" :inactive="true" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" :inactive="true" :percentage="100"></van-progress>
</div>
```
:::
#### 自定义颜色和文字
可以使用`pivot-text`属性自定义文字,`color`属性自定义进度条颜色
:::demo 自定义颜色和文字
```html
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="红色" color="#ed5050" :percentage="26"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="橙色" color="#f60" :percentage="46"></van-progress>
</div>
<div class="demo-progress__wrapper">
<van-progress class="demo-progress__demo1" pivot-text="黄色" color="#f09000" :percentage="66"></van-progress>
</div>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| inactive | 是否置灰 | `boolean` | `false` | `true`, `false` |
| percentage | 进度百分比 | `number` | `false` | `0-100` |
| pivotText | 文字显示 | `string` | 百分比文字 | - |
| color | 进度条颜色 | `string` | `#38f` | hexvalue |
| textColor | 进度条文字颜色 | `string` | `#fff` | hexvalue |

View File

@ -0,0 +1,99 @@
<style>
@component-namespace demo {
@b quantity {
.van-quantity {
margin-left: 15px;
}
.curr-quantity {
margin: 15px;
}
}
}
</style>
<script>
export default {
data() {
return {
quantity1: 1,
quantity2: null,
};
}
};
</script>
## Quantity 数量选择
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Quantity`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Quantity`组件了:
```js
import Vue from 'vue';
import { Quantity } from 'vant';
import 'vant/lib/vant-css/quantity.css';
Vue.component(Quantity.name, Quantity);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Quantity`组件,这样只能在你注册的组件中使用`Quantity`
```js
import { Quantity } from 'vant';
export default {
components: {
'van-quantity': Quantity
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-quantity v-model="quantity1"></van-quantity>
<p class="curr-quantity">当前值:{{ quantity1 }}</p>
```
:::
#### 禁用Quantity
设置`disabled`属性,此时`quantity`不可改变。
:::demo 禁用Quantity
```html
<van-quantity v-model="quantity1" disabled></van-quantity>
```
:::
#### 高级用法
默认是每次加减为1可以对组件设置`step``min``max``defaultValue`属性。
:::demo 高级用法
```html
<van-quantity v-model="quantity2" min="5" max="40" step="2" default-value="9"></van-quantity>
<p class="curr-quantity">当前值:{{ quantity2 }}</p>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| min | 最小值 | `string`, `number` | `1` | |
| max | 最大值 | `string`, `number` | | |
| step | 步数 | `string`, `number` | `1` | |
| disabled | 是否被禁用了 | `boolean` | `false` | |
| defaultValue | 默认值 | `string`, `number` | `1` | |

View File

@ -0,0 +1,23 @@
## 快速上手
### 完整引入
```javascript
import Vue from 'vue';
import ZanUI from 'vant';
import 'vant/lib/vant-css/index.css';
Vue.use(ZanUI);
```
### 按需引入
```javascript
import Vue from 'vue';
import { Button, Cell } from 'vant';
import 'vant/lib/vant-css/button.css';
import 'vant/lib/vant-css/cell.css';
Vue.component(Button.name, Button);
Vue.component(Cell.name, Cell);
```

176
docs/examples-docs/radio.md Normal file
View File

@ -0,0 +1,176 @@
<style>
@component-namespace demo {
@b radio {
.van-radios {
padding: 0 20px;
.van-radio {
margin: 10px 0;
}
}
}
}
</style>
<script>
export default {
data() {
return {
radio1: '1',
radio2: '2',
radio3: '1',
radio4: '1'
};
}
};
</script>
## Radio 单选框
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Radio`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Radio`组件了:
```js
import Vue from 'vue';
import { Radio, RadioGroup } from 'vant';
import 'vant/lib/vant-css/radio.css';
Vue.component(Radio.name, Radio);
Vue.component(RadioGroup.name, RadioGroup);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Radio`组件,这样只能在你注册的组件中使用`Radio`
```js
import { Radio, RadioGroup } from 'vant';
export default {
components: {
'van-radio': Radio,
'van-radio-group': RadioGroup
}
};
```
### 代码演示
#### 基础用法
通过`v-model`绑定值即可。当`Radio`选中时,绑定的值即为`Radio``name`属性设置的值。
:::demo 基础用法
```html
<div class="van-radios">
<van-radio name="1" v-model="radio1">单选框1</van-radio>
<van-radio name="2" v-model="radio1">单选框2</van-radio>
</div>
<script>
export default {
data() {
return {
radio1: '1'
}
}
};
</script>
```
:::
#### 禁用状态
设置`disabled`属性即可,此时`Radio`不能点击。
:::demo 禁用状态
```html
<div class="van-radios">
<van-radio name="1" v-model="radio2" disabled>未选中禁用</van-radio>
<van-radio name="2" v-model="radio2" disabled>选中且禁用</van-radio>
</div>
<script>
export default {
data() {
return {
radio2: '2'
}
}
};
</script>
```
:::
#### radio组
需要与`van-radio-group`一起使用,在`van-radio-group`通过`v-model`来绑定当前选中的值。例如下面的`radio3`
:::demo radio组
```html
<div class="van-radios">
<van-radio-group v-model="radio3">
<van-radio name="1">单选框1</van-radio>
<van-radio name="2">单选框2</van-radio>
</van-radio-group>
</div>
<script>
export default {
data() {
return {
radio3: '1'
}
}
};
</script>
```
:::
#### 与Cell组件一起使用
此时你需要再引入`Cell``CellGroup`组件。
:::demo 与Cell组件一起使用
```html
<van-radio-group v-model="radio4">
<van-cell-group>
<van-cell><van-radio name="1">单选框1</van-radio></van-cell>
<van-cell><van-radio name="2">单选框2</van-radio></van-cell>
</van-cell-group>
</van-radio-group>
<script>
export default {
data() {
return {
radio4: '1'
}
}
};
</script>
```
:::
### Radio API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
| name | 根据这个来判断radio是否选中 | `boolean` | `false` | |
### RadioGroup API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| disabled | 是否禁用单选框 | `boolean` | `false` | |
### RadioGroup Event
| 事件名称 | 说明 | 回调参数 |
|-----------|-----------|-----------|
| change | 当绑定值变化时触发的事件 | 当前组件的值 |

View File

@ -0,0 +1,109 @@
<script>
export default {
methods: {
goSearch(value) {
alert(value)
},
handleChange(value) {
console.log(value);
},
handleCancel() {
alert('cancel');
}
}
};
</script>
## Search 搜索
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Search`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Search`组件了:
```js
import Vue from 'vue';
import { Search } from 'vant';
import 'vant/lib/vant-css/search.css';
Vue.component(Search.name, Search);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Search`组件,这样只能在你注册的组件中使用`Search`
```js
import { Search } from 'vant';
export default {
components: {
'van-search': Search
}
};
```
### 代码演示
#### 基础用法
如果你只需要在搜索时有个回调,只要监听一个`search`事件。
:::demo 基础用法
```html
<van-search placeholder="商品名称" @search="goSearch"></van-search>
<script>
export default {
methods: {
goSearch(value) {
alert(value)
}
}
};
</script>
```
:::
#### 监听对应事件
除了`search`事件,还有`change``cancel`事件,`change`事件在`input`输入框每次`change`时触发,适用于实时搜索等,`cancel`在取消按钮点击时触发。
:::demo 监听对应事件
```html
<van-search placeholder="商品名称" @search="goSearch" @change="handleChange" @cancel="handleCancel"></van-search>
<script>
export default {
methods: {
goSearch(value) {
alert(value)
},
handleChange(value) {
console.log(value);
},
handleCancel() {
alert('cancel');
}
}
};
</script>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 必须 |
|-----------|-----------|-----------|-------------|-------------|
| placeholder | `input``placeholder`文案 | `string` | | |
### Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| change | `input`输入框每次`change`时触发,适用于实时搜索等 | value当前`input`输入框的值 |
| cancel | 取消搜索 | |
| search | 确定搜索 | value当前`input`输入框的值 |

130
docs/examples-docs/steps.md Normal file
View File

@ -0,0 +1,130 @@
<style>
@component-namespace demo {
@b steps {
.steps-success {
color: #06bf04;
}
.van-button {
margin: 15px 0 0 15px;
}
}
}
</style>
<script>
export default {
data() {
return {
active: 0
};
},
methods: {
nextStep() {
if (++this.active > 3) this.active = 0;
}
}
}
</script>
## Steps 步骤条
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Steps`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Steps`组件了:
```js
import Vue from 'vue';
import { Steps, Step } from 'vant';
import 'vant/lib/vant-css/steps.css';
Vue.component(Steps.name, Steps);
Vue.component(Step.name, Step);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Steps`组件,这样只能在你注册的组件中使用`Steps`
```js
import { Steps, Step } from 'vant';
export default {
components: {
'van-steps': Steps,
'van-step': Step
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-steps :active="active" icon="logistics" icon-class="steps-success" title="等待商家发货" description="等待商家发货等待商家发货等待商家发货等待商家发货等待商家发货">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
<van-button @click="nextStep">下一步</van-button>
<script>
export default {
data() {
return {
active: 0
};
},
methods: {
nextStep() {
if (++this.active > 3) this.active = 0;
}
}
}
</script>
```
:::
#### 只显示步骤条
当你不设置`title``description`属性时,就会🈯️显示步骤条,而没有步骤的详细信息。
:::demo 只显示步骤条
```html
<van-steps :active="active">
<van-step>买家下单</van-step>
<van-step>商家接单</van-step>
<van-step>买家提货</van-step>
<van-step>交易完成</van-step>
</van-steps>
```
:::
### Steps API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| active | 当前激活的步骤从0开始 | `number` | | |
| icon | 当前步骤的icon | `string` | | |
| iconClass | 当前步骤栏为icon添加的类 | `string` | | |
| title | 当前步骤从标题 | `string` | | |
| description | 当前步骤描述 | `string` | | |
### Steps Slot
| 名称 | 说明 |
|-----------|-----------|
| icon | 自定义icon区域 |
| message-extra | 状态栏添加额外的元素 |

143
docs/examples-docs/swipe.md Normal file
View File

@ -0,0 +1,143 @@
<style>
@component-namespace demo {
@b swipe {
.van-swipe {
height: 200px;
img {
width: 100%;
}
}
}
}
</style>
<script>
export default {
data() {
return {
autoImages: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
],
images: [
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]
};
},
methods: {
handlePageEnd(page, index) {
console.log(page, index);
}
}
};
</script>
## Swipe 轮播
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Swipe`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Swipe`组件了:
```js
import Vue from 'vue';
import { Swipe, SwipeItem } from 'vant';
import 'vant/lib/vant-css/swipe.css';
Vue.component(Swipe.name, Swipe);
Vue.component(SwipeItem.name, SwipeItem);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Swipe`组件,这样只能在你注册的组件中使用`Swipe`
```js
import { Swipe, SwipeItem } from 'vant';
export default {
components: {
'van-swipe': Swipe,
'van-swipe-item': SwipeItem
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-swipe>
<van-swipe-item v-for="img in images">
<img v-lazy="img" alt="">
</van-swipe-item>
</van-swipe>
<script>
export default {
data() {
return {
images: [
'https://img.yzcdn.cn/upload_files/2017/03/14/FmTPs0SeyQaAOSK1rRe1sL8RcwSY.jpeg',
'https://img.yzcdn.cn/upload_files/2017/03/15/FvexrWlG_WxtCE9Omo5l27n_mAG_.jpeg'
]
};
}
};
</script>
```
:::
#### 自动轮播
需要设置`auto-play`属性为`true`,即会自动轮播。
:::demo 自动轮播
```html
<van-swipe auto-play @pagechange:end="handlePageEnd">
<van-swipe-item v-for="img in autoImages">
<img v-lazy="img" alt="">
</van-swipe-item>
</van-swipe>
<script>
export default {
data() {
return {
autoImages: [
'https://img.yzcdn.cn/upload_files/2017/03/09/FvkZahKoq1vkxLQFdVWeLf2UCqDz.png',
'https://img.yzcdn.cn/upload_files/2017/03/09/Fk0rpe_svu9d5Xk3MUCWd1QeMXOu.png'
]
};
},
methods: {
handlePageEnd(page, index) {
console.log(page, index);
}
}
};
</script>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| autoPlay | 是否自动轮播 | `boolean` | `false` | `true`, `false` |
| showIndicators | 是否显示指示器 | `boolean` | `true` | `true`, `false` |
### 事件
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| `pagechange:end` | 每一页轮播结束后触发 | `(elem, currIndex)``elem`为触发页当前的DOM节点 |

View File

@ -0,0 +1,192 @@
<style>
@component-namespace demo {
@b switch {
.examples,
.example-block {
text-align: center;
}
.example-block {
.demo-sub-title {
text-align: left;
}
}
@e text {
margin: 20px auto;
}
}
}
</style>
<script>
import Dialog from 'packages/dialog';
export default {
data() {
return {
switchState1: true,
switchState2: true,
switchStateTrue: true,
switchStateFalse: false
};
},
methods: {
updateState(newState) {
const state = newState ? '打开' : '关闭';
Dialog.confirm({
title: '提醒',
message: '是否' + state + '开关?'
}).then((action) => {
this.switchState2 = newState;
}, (error) => {});
}
}
};
</script>
## Switch 开关
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Switch`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Switch`组件了:
```js
import Vue from 'vue';
import { Switch } from 'vant';
import 'vant/lib/vant-css/switch.css';
Vue.component(Switch.name, Switch);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Switch`组件,这样只能在你注册的组件中使用`Switch`
```js
import { Switch } from 'vant';
export default {
components: {
'van-switch': Switch
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-switch class="some-customized-class" v-model="switchState1"></van-switch>
<div class="demo-switch__text">{{ switchState1 ? ' ON' : 'OFF' }}</div>
<script>
export default {
data() {
return {
switchState1: true
};
}
};
</script>
```
:::
:::demo
```html
<van-switch class="some-customized-class" v-model="switchState2" :on-change="updateState"></van-switch>
<div class="demo-switch__text">{{ switchState2 ? ' ON' : 'OFF' }}</div>
<script>
import Dialog from 'packages/dialog';
export default {
data() {
return {
switchState2: true
};
},
methods: {
updateState(newState) {
const state = newState ? '打开' : '关闭';
Dialog.confirm({
title: '提醒',
message: '是否' + state + '开关?'
}).then((action) => {
this.switchState2 = newState;
}, (error) => {
});
}
}
};
</script>
```
:::
#### 禁用状态
设置`disabled`属性为`true`,此时开关不可点击。
:::demo 禁用状态
```html
<van-switch class="some-customized-class" v-model="switchStateTrue" :disabled="true"></van-switch>
<div class="demo-switch__text">ON, DISABLED</div>
<van-switch class="some-customized-class" v-model="switchStateFalse" :disabled="true"></van-switch>
<div class="demo-switch__text">OFF, DISABLED</div>
<script>
export default {
data() {
return {
switchStateTrue: true,
switchStateFalse: false
};
}
};
</script>
```
:::
#### loading状态
设置`loading`属性为`true`此时开关为加载状态一般用于点击开关时正在向后端发送请求此时正在loading请求成功后结束loading。
:::demo loading状态
```html
<van-switch class="some-customized-class" v-model="switchStateTrue" :loading="true"></van-switch>
<div class="demo-switch__text">ON, LOADING</div>
<van-switch class="some-customized-class" v-model="switchStateFalse" :loading="true"></van-switch>
<div class="demo-switch__text">OFF, LOADING</div>
<script>
export default {
data() {
return {
switchStateTrue: true,
switchStateFalse: false
};
}
};
</script>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-model | 开关状态 | `boolean` | `false` | `true`, `false` |
| loading | loading状态 | `boolean` | `false` | `true`, `false` |
| disabled | 禁用状态 | `boolean` | `false` | `true`, `false` |
| onChange | 开关状态切换回调(默认则改变开关状态) | `function` | - | - |

253
docs/examples-docs/tab.md Normal file
View File

@ -0,0 +1,253 @@
<style>
@component-namespace demo {
@b tab {
.van-tab__pane {
background-color: #fff;
padding: 20px;
}
.van-tabs--card .van-tab__pane {
background-color: transparent;
}
.custom-tabwrap .van-tab-active {
color: #20a0ff;
}
.custom-tabwrap .van-tabs-nav-bar {
background: #20a0ff;
}
.custom-pane {
text-align: center;
height: 50px;
line-height: 50px;
}
}
}
</style>
<script>
export default {
data() {
return {
active: 2
};
},
mounted() {
setTimeout(() => {
this.active = 3;
}, 1000);
},
methods: {
popalert() {
alert('haha')
},
handleTabClick(index) {
alert(index);
}
}
};
</script>
## Tab 标签
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Tab`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Tab`组件了:
```js
import Vue from 'vue';
import { Tab, Tabs } from 'vant';
import 'vant/lib/vant-css/tab.css';
Vue.component(Tab.name, Tab);
Vue.component(Tabs.name, Tabs);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Tab`组件,这样只能在你注册的组件中使用`Tab`
```js
import { Tab, Tabs } from 'vant';
export default {
components: {
'van-tab': Tab,
'van-tabs': Tabs
}
};
```
### 代码演示
#### 基础用法
默认情况下是启用第一个`tab`
:::demo 基础用法
```html
<van-tabs>
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
```
:::
#### active特定tab
可以在`van-tabs`上设置`active`为对应`tab`的索引从0开始即0代表第一个即可激活对应`tab`
:::demo 基础用法
```html
<van-tabs :active="active">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
```
:::
#### 禁用tab
在对应的`van-tab`上设置`disabled`属性即可,如果需要监听禁用事件,可以监听`disabled`事件。
:::demo 禁用tab
```html
<van-tabs>
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二" disabled @disabled="popalert">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
<script>
export default {
methods: {
popalert() {
alert('haha')
}
}
};
</script>
```
:::
#### card样式
`Tabs`目前有两种样式:`line``card`,默认为`line`样式,也就上面基础用法中的样式,你可以在`van-tabs`上设置`type``card`改为card样式。
:::demo card样式
```html
<van-tabs type="card">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
```
:::
<style>
.custom-tabwrap .van-tab-active {
color: #20a0ff;
}
.custom-tabwrap .van-tabs-nav-bar {
background: #20a0ff;
}
.custom-pane {
text-align: center;
height: 50px;
line-height: 50px;
}
</style>
#### 自定义样式
可以在`van-tabs`上设置对应的`class`,从而自定义某些样式。
:::demo 自定义样式
```html
<van-tabs active="2" class="custom-tabwrap">
<van-tab title="选项一" class="custom-pane">内容一</van-tab>
<van-tab title="选项二" class="custom-pane">内容二</van-tab>
<van-tab title="选项三" class="custom-pane">内容三</van-tab>
<van-tab title="选项四" class="custom-pane">内容四</van-tab>
<van-tab title="选项五" class="custom-pane">内容五</van-tab>
</van-tabs>
<style>
.custom-tabwrap .van-tab-active {
color: #20a0ff;
}
.custom-tabwrap .van-tabs-nav-bar {
background: #20a0ff;
}
.custom-pane {
text-align: center;
height: 50px;
line-height: 50px;
}
</style>
```
:::
#### click事件
可以在`van-tabs`上绑定一个`click`事件,事件处理函数有一个参数,参数为对应`tab``tabs`中的索引。
:::demo click事件
```html
<van-tabs @click="handleTabClick">
<van-tab title="选项一">内容一</van-tab>
<van-tab title="选项二">内容二</van-tab>
<van-tab title="选项三">内容三</van-tab>
<van-tab title="选项四">内容四</van-tab>
<van-tab title="选项五">内容五</van-tab>
</van-tabs>
<script>
export default {
methods: {
handleTabClick(index) {
alert(index);
}
}
};
</script>
```
:::
### van-tabs API
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|-----------|-----------|-----------|-------------|-------------|
| classtype | 两种UI | `string` | `line` | `line`, `card` |
| active | 默认激活的tab | `string`, `number` | `0` | |
| navclass | tabs的内部nav上的自定义classname | `string` | | |
### van-tab API
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|-----------|-----------|-----------|-------------|-------------|
| title | tab的标题 | `string` | | |
| disabled | 是否禁用这个tab | `boolean` | `false` | |
### van-tabs Event
| 事件名 | 说明 | 参数 |
|-----------|-----------|-----------|
| click | 某个tab点击事件 | index点击的`tab`的索引 |
| disabled | 某个tab禁用时点击事件 | index点击的`tab`的索引 |

99
docs/examples-docs/tag.md Normal file
View File

@ -0,0 +1,99 @@
<style>
.tags-container {
padding: 5px 15px;
.van-tag + .van-tag {
margin-left: 10px;
}
}
</style>
## Tag 标记
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Tag`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Tag`组件了:
```js
import Vue from 'vue';
import { Tag } from 'vant';
import 'vant/lib/vant-css/tag.css';
Vue.component(Tag.name, Tag);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Tag`组件,这样只能在你注册的组件中使用`Tag`
```js
import { Tag } from 'vant';
export default {
components: {
'van-tag': Tag
}
};
```
### 代码演示
#### 基础用法
`Tag`目前有三种类型,`danger``success``primary`,它们分别显示为红色,绿色和蓝色,你也可以加上自定义的类,为它们加上其他的颜色。
:::demo 基础用法
```html
<div class="tags-container">
<van-tag>返现</van-tag>
<van-tag plain>返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag type="danger">四字标签</van-tag>
<van-tag type="danger"></van-tag>
</div>
```
:::
#### 高级用法
设置`plain``true`时表示空心的`tag`,还可以设置`mark``true`,表示是否为标记。
:::demo 高级用法
```html
<div class="tags-container">
<van-tag type="danger">返现</van-tag>
<van-tag plain type="danger">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="primary">返现</van-tag>
<van-tag plain type="primary">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="success">返现</van-tag>
<van-tag plain type="success">返现</van-tag>
</div>
<div class="tags-container">
<van-tag type="danger" mark>返现</van-tag>
</div>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| plain | 是否是空心tag | `boolean` | `false` | |
| mark | 是否是标记 | `boolean` | `false` | |
| type | tag类型 | `string` | `''` | `primary`, `success`, `danger` |
### Slot
| name | 描述 |
|-----------|-----------|
| - | 自定义tag显示内容 |

229
docs/examples-docs/toast.md Normal file
View File

@ -0,0 +1,229 @@
<style>
@component-namespace demo {
@b toast {
.van-button {
margin: 15px;
}
}
}
</style>
<script>
import { Toast } from 'src/index';
export default {
methods: {
showSimpleToast() {
Toast('我是提示文案,建议不超过十五字~');
},
showLoadingToast() {
Toast.loading();
},
showSuccessToast() {
Toast.success('成功文案');
},
showFailToast() {
Toast.fail('失败文案');
},
showForbidClickToast() {
Toast({
message: '背景不能点击',
forbidClick: true
})
},
showCustomizedToast(duration) {
let leftSec = duration / 1000;
let toast = Toast({
duration: duration + 1000,
type: 'success',
message: leftSec.toString()
});
const id = window.setInterval(() => {
if (leftSec <= 1) {
window.clearInterval(id);
toast.message = '跳转中...'
return;
}
toast.message = (--leftSec).toString();
}, 1000);
},
showToast() {
this.toast = Toast('我是提示文案,建议不超过十五字~');
},
closeToast() {
this.toast.clear();
},
showHtmlToast() {
Toast({
type: 'html',
message: '<em>HTML<em>'
})
}
}
};
</script>
## Toast 轻提示
### 使用指南
`Toast`和其他组件不同不是通过HTML结构的方式来使用而是通过函数调用的方式。使用前需要先引入它。
```js
import { Toast } from 'vant';
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<van-button @click="showSimpleToast">普通文字提示</van-button>
<van-button @click="showLoadingToast">加载Toast</van-button>
<van-button @click="showSuccessToast">成功</van-button>
<van-button @click="showFailToast">失败</van-button>
<van-button @click="showForbidClickToast">背景不能点击</van-button>
<van-button @click="showCustomizedToast(5000)">倒数5秒</van-button>
<script>
import { Toast } from 'src/index';
export default {
methods: {
showSimpleToast() {
Toast('我是提示文案,建议不超过十五字~');
},
showLoadingToast() {
Toast.loading();
},
showSuccessToast() {
Toast.success('成功文案');
},
showFailToast() {
Toast.fail('失败文案');
},
showForbidClickToast() {
Toast({
message: '背景不能点击',
forbidClick: true
})
},
showCustomizedToast(duration) {
let leftSec = duration / 1000;
let toast = Toast({
duration: duration + 1000,
type: 'success',
message: leftSec.toString()
});
const id = window.setInterval(() => {
if (leftSec <= 1) {
window.clearInterval(id);
toast.message = '跳转中...'
return;
}
toast.message = (--leftSec).toString();
}, 1000);
}
}
};
</script>
```
:::
#### 手动关闭
:::demo 手动关闭
```html
<van-button @click="showToast">打开</van-button>
<van-button @click="closeToast">关闭</van-button>
<script>
import { Toast } from 'src/index';
export default {
methods: {
showToast() {
Toast('我是提示文案,建议不超过十五字~');
},
closeToast() {
Toast.clear();
}
}
};
</script>
```
:::
#### 传入html
:::demo 手动关闭
```html
<van-button @click="showHtmlToast">打开</van-button>
<script>
import { Toast } from 'src/index';
export default {
methods: {
showHtmlToast() {
Toast({
type: 'html',
message: '<em>HTML<em>'
})
}
}
};
</script>
```
:::
### 基础用法
#### Toast(options)
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 类型 | String | 'text' | 'text', 'loading', 'success', 'fail', 'html' |
| message | 内容 | String | '' | - |\| message | 内容 | String | '' | -
| forbidClick | 不允许背景点击 | Boolean | false | true, false|
| duration | 时长(ms) | Number | 3000ms | -|
### 快速用法
#### Toast(message) || Toast(message, options)
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| message | 内容 | String | '' | - |
| forbidClick | 不允许背景点击 | Boolean | false | true, false|
| duration | 时长(ms) | Number | 3000ms | -|
#### Toast.loading() || Toast.loading(message, options)
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| forbidClick | 不允许背景点击 | Boolean | false | true, false|
| duration | 时长(ms) | Number | 3000ms | -|
#### Toast.success(message) || Toast.success(message, options)
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 类型 | String | 'text' | 'text', 'loading', 'success', 'failure' |
| forbidClick | 不允许背景点击 | Boolean | false | true, false|
| duration | 时长(ms) | Number | 3000ms | -|
#### Toast.fail(message) || Toast.fail(message, options)
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| type | 类型 | String | 'text' | 'text', 'loading', 'success', 'failure' |
| forbidClick | 不允许背景点击 | Boolean | false | true, false|
| duration | 时长(ms) | Number | 3000ms | -|
#### Toast.clear()
关闭toast。

View File

@ -0,0 +1,76 @@
<style>
.uploader-container {
padding: 5px 15px;
}
</style>
<script>
export default {
methods: {
logContent(file) {
console.log(file)
}
}
};
</script>
## Uploader 图片上传
### 使用指南
如果你已经按照快速上手中引入了整个`vant`,以下**组件注册**就可以忽略了,因为你已经全局注册了`vant`中的全部组件。
#### 全局注册
你可以在全局注册`Uploader`组件,比如页面的主文件(`index.js``main.js`),这样页面任何地方都可以直接使用`Uploader`组件了:
```js
import Vue from 'vue';
import { Uploader } from 'vant';
import 'vant/lib/vant-css/uploader.css';
Vue.component(Uploader.name, Uploader);
```
#### 局部注册
如果你只是想在某个组件中使用,你可以在对应组件中注册`Uploader`组件,这样只能在你注册的组件中使用`Uploader`
```js
import { Uploader } from 'vant';
export default {
components: {
'van-uploader': Uploader
}
};
```
### 代码演示
#### 基础用法
:::demo 基础用法
```html
<div class="uploader-container">
<van-uploader :after-read="logContent">
<van-icon name="photograph"></van-icon>
</van-uploader>
</div>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| result-type | 读取文件的方式以base64的方式读取以文本的方式读取 | `string` | `dataUrl` | `dataUrl`, `text` |
| disable | 是否禁用上传,在图片上传期间设置为true禁止用户点击此组件上传图片 | `boolean` | `false` | |
| before-read | 读文件之前的钩子,参数为选择的文件,若返回 false 则停止读取文件。 | `Function` | | |
| after-read | 文件读完之后回调此函数,参数为{file:'选择的文件',content:'读的内容'} | `Function` | | |
### Slot
| name | 描述 |
|-----------|-----------|
| - | 自定义上传显示图标 |

View File

@ -0,0 +1,113 @@
## Waterfall 瀑布流
### 使用指南
#### 全局注册
`Waterfall`引入后就自动全局安装。如果需要,可以再次手动安装:
```js
import Vue from 'vue';
import { Waterfall } from 'vant';
Waterfall.install(Vue);
```
#### 局部注册
如果你只是想在某个组件中使用`Waterfall`,你可以在对应组件中注册`Waterfall`指令,这样只能在你注册的组件中使用`Waterfall`
```js
import { Waterfall } from 'vant';
export default {
directives: {
WaterfallLower: Waterfall('lower'),
WaterfallUpper: Waterfall('upper')
}
};
```
### 代码演示
<script>
export default {
data() {
return {
list: [1, 2, 3, 4, 5],
loading: false,
finished: false
};
},
methods: {
loadMore() {
if (this.list.length >= 200) {
this.finished = true;
return;
}
this.loading = true;
setTimeout(() => {
let lastNumber = this.list[this.list.length - 1];
for (let i = 0; i < 5; i ++) {
lastNumber += 1;
this.list.push(lastNumber);
}
this.loading = false;
}, 2500);
},
loadMoreUpper() {
if (this.list[0] < 0) return;
this.list.unshift(-1);
}
},
computed: {
isWaterfallDisabled: function() {
return this.loading || this.finished;
}
}
};
</script>
<style>
.waterfall {
max-height: 300px;
overflow: scroll;
}
</style>
#### 基础用法
:::demo 基础用法
```html
<div class="waterfall">
<div
v-waterfall-lower="loadMore"
v-waterfall-upper="loadMoreUpper"
waterfall-disabled="isWaterfallDisabled"
waterfall-offset="400"
>
<div
class="waterfall-item"
v-for="item in list"
style="text-align: center;"
>
{{ item }}
</div>
<div v-if="loading" style="text-align: center;">
loading
</div>
</div>
</div>
```
:::
### API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| v-waterfall-lower | 滚动到底部, 触发执行的函数 | `function` | - | |
| v-waterfall-upper | 滚动到顶部, 触发执行的函数 | `function` | - | |
| waterfall-disabled | 在vue对象中表示是否禁止瀑布流触发的key值 | `string` | - | |
| waterfall-offset | 触发瀑布流加载的阈值 | `number` | `300` | |

104
docs/src/ExamplesApp.vue Normal file
View File

@ -0,0 +1,104 @@
<template>
<div class="examples-container">
<router-view></router-view>
<div class="footer">
<img src="https://img.yzcdn.cn/upload_files/2017/04/18/FjupTe9o1apJhJr5qR-4ucXqPs7e.png" alt="logo" class="zanui-logo">
</div>
</div>
</template>
<script>
export default {
computed: {
visible() {
return ['/'].indexOf(this.$route.path) < 0;
}
}
};
</script>
<style>
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
vertical-align: baseline;
}
a {
color: #4078c0;
text-decoration: none;
}
body, html {
height: 100%;
}
.examples-container {
padding-bottom: 54px;
height: 100%;
overflow: auto;
background: #f8f8f8;
position: relative;
}
.page-back {
display: inline-block;
position: absolute;
top: 12px;
left: 10px;
width: 40px;
height: 40px;
text-align: center;
color: #333;
transform: rotate(180deg);
i {
font-size: 24px;
line-height: 40px;
}
}
.demo-title {
font-size: 16px;
display: block;
line-height: 1;
padding: 20px 15px 0;
}
.demo-sub-title {
font-size: 14px;
color: #999;
padding: 30px 15px 10px;
}
.footer {
margin-top: 30px;
width: 100%;
padding: 10px 0 20px;
position: fixed;
bottom: 0;
left: 0;
background: #f8f8f8;
}
.zanui-logo {
display: block;
margin: 0 auto;
width: 150px;
height: auto;
}
</style>

View File

@ -0,0 +1,40 @@
<template>
<div class="app">
<page-header></page-header>
<div class="main-content">
<div class="page-container clearfix">
<side-nav :data="navConfig['zh-CN']" base="/component"></side-nav>
<div class="page-content">
<router-view></router-view>
<footer-nav></footer-nav>
</div>
</div>
</div>
<page-footer></page-footer>
</div>
</template>
<script>
import Vue from 'vue';
import 'highlight.js/styles/color-brewer.css';
import navConfig from './nav.config.js';
import SideNav from './components/side-nav';
import DemoBlock from './components/demo-block';
import FooterNav from './components/footer-nav';
import PageHeader from './components/page-header';
import PageFooter from './components/page-footer';
Vue.component('side-nav', SideNav);
Vue.component('demo-block', DemoBlock);
Vue.component('footer-nav', FooterNav);
Vue.component('page-header', PageHeader);
Vue.component('page-footer', PageFooter);
export default {
data() {
return {
navConfig: navConfig
};
}
};
</script>

View File

@ -0,0 +1,66 @@
<template>
<div class="demo-block" :class="blockClass">
<slot name="examples"></slot>
<slot name="highlight"></slot>
</div>
</template>
<script>
export default {
computed: {
blockClass() {
return `demo-${this.$route.path.split('/').pop()}`;
}
}
};
</script>
<style>
.demo-block {
transition: .2s;
overflow: hidden;
margin-bottom: 20px;
code {
font-family: Menlo, Monaco, Consolas, Courier, monospace;
overflow: auto;
white-space: pre-wrap;
}
.examples {
width: 320px;
box-sizing: border-box;
padding: 10px 0;
min-height: 60px;
max-height: 500px;
overflow: auto;
background-color: #F8F8F8;
border: 1px solid #E5E5E5;
float: right;
}
.highlight {
box-sizing: border-box;
border: 1px solid #E5E5E5;
border-radius: 4px;
margin-right: 345px;
pre {
margin: 0;
}
code.hljs {
margin: 0;
border: none;
max-height: none;
border-radius: 0;
padding: 20px;
background-color: #F8F8F8;
&::before {
content: none;
}
}
}
}
</style>

View File

@ -0,0 +1,64 @@
<template>
<div class="side-nav">
<h1 class="zanui-title">Zan UI Wap</h1>
<h2 class="zanui-desc">有赞移动wap端组件库</h2>
<div class="mobile-navs">
<template v-for="item in data">
<div class="mobile-nav-item" v-if="item.showInMobile">
<mobile-nav v-for="group in item.groups" :group="group" :base="base"></mobile-nav>
</div>
</template>
</div>
</div>
</template>
<script>
import navConfig from '../nav.config.js';
import MobileNav from './mobile-nav';
export default {
data() {
return {
highlights: [],
navState: [],
data: navConfig['zh-CN'],
base: '/component'
};
},
components: {
MobileNav
}
};
</script>
<style>
.side-nav {
width: 100%;
box-sizing: border-box;
padding: 90px 15px 20px;
position: relative;
z-index: 1;
.zanui-title,
.zanui-desc {
text-align: center;
font-weight: normal;
}
.zanui-title {
padding-top: 40px;
height: 0;
overflow: hidden;
background: url(https://img.yzcdn.cn/upload_files/2017/04/18/FveNmX6aFsQm1jUhcvBBZn6UrZFi.png) center center no-repeat;
background-size: 156px 40px;
margin-bottom: 10px;
}
.zanui-desc {
font-size: 14px;
color: #666;
margin-bottom: 50px;
}
}
</style>

View File

@ -0,0 +1,14 @@
<template>
<div class="example-block">
<h2 class="demo-sub-title" v-text="title"></h2>
<slot></slot>
</div>
</template>
<script>
export default {
props: {
title: String
}
};
</script>

View File

@ -0,0 +1,130 @@
<template>
<div class="footer-nav">
<a
href="javascript:void(0)"
v-if="leftNav"
class="footer-nav__link footer-nav__left"
@click="handleNavClick('prev')">
<van-icon name="arrow"></van-icon>
<span>{{ leftNav.title }}</span>
</a>
<a
href="javascript:void(0)"
v-if="rightNav"
class="footer-nav__link footer-nav__right"
@click="handleNavClick('next')">
<van-icon name="arrow"></van-icon>
<span>{{ rightNav.title }}</span>
</a>
</div>
</template>
<script>
import navConfig from '../nav.config.js';
export default {
data() {
return {
currentPath: null,
nav: [],
leftNav: null,
rightNav: null
};
},
watch: {
'$route.path'() {
this.setNav();
this.updateNav();
}
},
methods: {
setNav() {
let nav = navConfig['zh-CN'];
for (let i = 0; i < nav.length; i++) {
let navItem = nav[i];
if (!navItem.groups) {
this.nav.push(nav[i]);
} else {
for (let j = 0; j < navItem.groups.length; j++) {
this.nav = this.nav.concat(navItem.groups[j].list);
}
}
}
},
updateNav() {
let baseUrl = '/component';
let currentIndex;
this.currentPath = this.$route.path.slice(baseUrl.length);
for (let i = 0, len = this.nav.length; i < len; i++) {
if (this.nav[i].path === this.currentPath) {
currentIndex = i;
break;
}
}
this.leftNav = this.nav[currentIndex - 1];
this.rightNav = this.nav[currentIndex + 1];
},
handleNavClick(direction) {
this.$router.push(`/component${ direction === 'prev' ? this.leftNav.path : this.rightNav.path }`);
}
},
created() {
this.setNav();
this.updateNav();
}
};
</script>
<style>
@component-namespace footer {
@b nav {
padding: 24px 40px;
overflow: hidden;
border-top: 1px solid #e5e5e5;
@e link {
color: #3388FF;
overflow: hidden;
position: relative;
font-size: 20px;
line-height: 1.5;
.zan-icon {
width: 20px;
font-size: 12px;
line-height: 20px;
border: 2px solid #3388FF;
border-radius: 50%;
text-align: center;
margin-top: 3px;
}
}
@e left {
float: left;
.zan-icon {
float: left;
transform: rotate(180deg);
margin-right: 10px;
}
}
@e right {
float: right;
.zan-icon {
float: right;
margin-left: 10px;
}
}
}
}
</style>

View File

@ -0,0 +1,23 @@
import MobilePopup from './mobile-popup.vue';
export default {
components: {
MobilePopup
},
computed: {
mobileUrl() {
if (process.env.NODE_ENV === 'production') {
return '/zanui/vue/examples#' + location.pathname.slice(10);
} else {
return '/examples.html#' + location.pathname;
}
}
},
data() {
return {
mobileShow: false
};
}
};

View File

@ -0,0 +1,119 @@
<template>
<div class="mobile-nav-group">
<div
class="mobile-nav-group__title mobile-nav-group__basetitle"
:class="{
'mobile-nav-group__title--open': isOpen
}"
@click="isOpen = !isOpen">
{{group.groupName}}
</div>
<ul class="mobile-nav-group__list" :class="{ 'mobile-nav-group__list--open': isOpen }">
<template v-for="navItem in group.list">
<li
class="mobile-nav-group__title"
v-if="!navItem.disabled">
<router-link
active-class="active"
:to="base + navItem.path">
<p>
{{ navItem.title }}
</p>
</router-link>
<zan-icon name="arrow"></zan-icon>
</li>
</template>
</ul>
</div>
</template>
<script>
export default {
props: {
group: {
type: Object,
default: () => {
return [];
}
},
base: String
},
data() {
return {
isOpen: false
};
}
};
</script>
<style>
@component-namespace mobile {
@b nav-group {
border-radius: 2px;
margin-bottom: 15px;
background-color: #fff;
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.10);
@e basetitle {
padding-left: 20px;
}
@e title {
font-size: 16px;
color: #333;
line-height: 56px;
position: relative;
user-select: none;
@m open {
color: #999;
}
a {
color: #333;
display: block;
user-select: none;
padding-left: 20px;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&:active {
background: #ECECEC;
}
> p {
border-top: 1px solid #e5e5e5;
}
}
.zan-icon-arrow {
position: absolute;
font-size: 12px;
line-height: 1;
top: 24px;
right: 20px;
}
}
@e list {
height: 0;
transition: height .5s ease-out;
@m open {
height: auto;
}
}
li {
list-style: none;
}
ul {
padding: 0;
margin: 0;
overflow: hidden;
}
}
}
</style>

View File

@ -0,0 +1,51 @@
<template>
<van-popup v-model="currentValue" :lock-on-scroll="true">
<div class="mobile-popup">
<iframe :src="url" class="mobile-popup-iframe"></iframe>
</div>
</van-popup>
</template>
<script>
export default {
props: {
url: String,
value: {}
},
data() {
return {
currentValue: this.value
};
},
watch: {
currentValue(val) {
this.$emit('input', val);
},
value(val) {
console.log(val);
this.currentValue = val;
}
}
};
</script>
<style>
.mobile-popup {
width: 375px;
height: 650px;
background: url(https://b.yzcdn.cn/v2/image/wap/zanui-mobile-container.png) no-repeat;
}
.mobile-popup-iframe {
width: 100%;
box-sizing: border-box;
border-left: 1px solid #e5e5e5;
border-right: 1px solid #e5e5e5;
border-bottom: 1px solid #e5e5e5;
position: relative;
top: 64px;
height: 586px;
}
</style>

View File

@ -0,0 +1,59 @@
<template>
<div class="page-footer">
<ul class="page-footer__navs">
<li class="page-footer__item">
<a href="https://www.youzan.com/" class="page-footer__link" target="_blank">有赞官网</a>
</li>
<li class="page-footer__item">
<a href="#" class="page-footer__link" target="_blank">有赞云</a>
</li>
<li class="page-footer__item">
<a href="https://job.youzan.com/" class="page-footer__link" target="_blank">加入我们</a>
</li>
</ul>
<p class="page-footer__copyright">
2012-{{ curYear }} © youzanyun.com - 浙公网安备 33010602004354 增值电信业务经营许可证浙B2-20140331 - 浙ICP备13037466号
</p>
</div>
</template>
<script>
export default {
data() {
return {
curYear: (new Date()).getFullYear()
};
}
};
</script>
<style>
@component-namespace page {
@b footer {
height: 72px;
margin-top: 40px;
background-color: #34383B;
display: flex;
justify-content: center;
@e item {
float: left;
margin: 0 20px;
}
@e link {
display: block;
color: #E5E5E5;
font-size: 12px;
line-height: 72px;
}
@e copyright {
color: #999;
font-size: 12px;
line-height: 72px;
margin-left: 50px;
}
}
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div class="page-header">
<div class="page-header__top">
<h1 class="page-header__logo">
<a href="#"></a>
</h1>
<ul class="page-header__navs">
<li class="page-header__item">
<a href="/" class="page-header__link">首页</a>
</li>
<li class="page-header__item">
<a href="http://react.fe.qima-inc.com/" class="page-header__link">PC端</a>
</li>
<li class="page-header__item">
<a href="http://zanui.qima-inc.com/vue" class="page-header__link page-header__link--active">移动端</a>
</li>
<li class="page-header__item">
<a href="https://github.com/youzan/zanui-weapp" class="page-header__link">微信小程序</a>
</li>
</ul>
</div>
<ul class="page-header__subnavs" :class="{ 'page-header__subnavs--shadow': scrollTop > 0 }">
<li class="page-header__item">
<a href="http://zanui.qima-inc.com/vue" class="page-header__link page-header__link--active">基础组件</a>
</li>
<li class="page-header__item">
<a href="http://zanui.qima-inc.com/captain" class="page-header__link">业务组件</a>
</li>
<li class="page-header__item">
<span class="page-header__link">V{{ version }}</span>
</li>
<li class="page-header__item">
<a href="#" class="page-header__github" target="_blank"></a>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
version: window._global.version,
scrollTop: 0
};
},
mounted() {
const _this = this;
let timer;
window.addEventListener('scroll', () => {
clearTimeout(timer);
const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
timer = setTimeout(() => {
_this.scrollTop = scrollTop;
}, 500);
});
}
};
</script>
<style>
@component-namespace page {
@b header {
position: fixed;
top: 0;
z-index: 1;
width: 100%;
@e top {
overflow: hidden;
height: 60px;
background-color: #fbfbfb;
box-shadow: 0 1px 4px rgba(0, 0, 0, .1);
}
@e logo {
float: left;
> a {
display: block;
width: 78px;
height: 20px;
background-image: url(https://img.yzcdn.cn/upload_files/2017/03/30/Fjm3aSwID8ROIV_5TO6dZdJ_IEgz.png);
background-size: contain;
background-repeat: no-repeat;
margin: 20px 0 0 20px;
}
}
@e navs {
float: right;
}
@e item {
float: left;
height: 50px;
}
@e subnavs {
line-height: 50px;
display: flex;
justify-content: center;
background-color: #f2f2f2;
position: relative;
z-index: -1;
@m shadow {
box-shadow: 0 1px 4px rgba(0, 0, 0, .1);
}
a,
span {
line-height: 50px;
}
}
@e link {
display: block;
line-height: 60px;
color: #333;
font-size: 16px;
margin: 0 20px;
&:hover {
color: #3388FF;
}
@m active {
color: #3388FF;
}
}
@e github {
display: inline-block;
width: 22px;
height: 22px;
overflow: hidden;
background-image: url(https://img.yzcdn.cn/upload_files/2017/03/30/Fil9peDfgzvk3kj-oFCsElS4FS1x.png);
background-size: contain;
background-repeat: no-repeat;
margin: 14px 20px 0;
}
}
}
</style>

View File

@ -0,0 +1,123 @@
<template>
<div class="side-nav">
<ul>
<li class="nav-item" v-for="item in data">
<a href="javascript:void(0)" v-if="!item.path" @click="handleTitleClick(item)">{{item.name}}</a>
<router-link
v-else
active-class="active"
:to="base + item.path"
exact
v-text="item.title || item.name">
</router-link>
<ul class="pure-menu-list sub-nav" v-if="item.children">
<li class="nav-item" v-for="navItem in item.children">
<router-link
active-class="active"
:to="base + navItem.path"
v-text="navItem.title || navItem.name">
</router-link>
</li>
</ul>
<template v-if="item.groups">
<div class="nav-group" v-for="group in item.groups">
<div class="nav-group__title">{{group.groupName}}</div>
<ul class="pure-menu-list">
<template v-for="navItem in group.list">
<li
class="nav-item"
v-if="!navItem.disabled">
<router-link
active-class="active"
:to="base + navItem.path"
v-text="navItem.title">
</router-link>
</li>
</template>
</ul>
</div>
</template>
</li>
</ul>
</div>
</template>
<script>
export default {
props: {
data: Array,
base: {
type: String,
default: ''
}
},
methods: {
handleTitleClick(item) {
const firstGroup = item.groups && item.groups[0];
if (firstGroup && firstGroup.list && firstGroup.list.length !== 0) {
return this.$router.replace(this.base + firstGroup.list[0].path);
}
}
}
};
</script>
<style lang="css">
.side-nav {
flex: 0 0 250px;
box-sizing: border-box;
padding: 40px 0;
border-right: 1px solid #e5e5e5;
li {
list-style: none;
}
ul {
padding: 0;
margin: 0;
overflow: hidden;
}
.nav-item {
a {
font-size: 16px;
color: #333;
line-height: 40px;
height: 40px;
margin: 0;
padding: 0;
text-decoration: none;
display: block;
position: relative;
transition: all .3s;
padding: 0 20px;
&.active {
color: #3388FF;
background-color: #F2F2F2;
}
}
.nav-item {
a {
display: block;
height: 40px;
line-height: 40px;
font-size: 14px;
padding-left: 44px;
&:hover {
color: #3388FF;
}
}
}
}
.nav-group__title {
font-size: 12px;
color: #666;
padding-left: 28px;
line-height: 26px;
margin-top: 10px;
}
}
</style>

52
docs/src/examples.js Normal file
View File

@ -0,0 +1,52 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './ExamplesApp';
import navConfig from './nav.config.js';
import routes from './router.config';
import ZanUI from 'src/index';
import 'packages/vant-css/src/index.css';
import DemoList from './components/demo-list.vue';
Vue.use(ZanUI);
Vue.use(ZanUI.Lazyload, {
lazyComponent: true
});
Vue.use(VueRouter);
const isProduction = process.env.NODE_ENV === 'production';
const routesConfig = routes(navConfig, true);
routesConfig.push({
path: '/',
component: DemoList.default || DemoList
});
const router = new VueRouter({
mode: 'hash',
base: isProduction ? '/zanui/vue/' : __dirname,
routes: routesConfig
});
let indexScrollTop = 0;
router.beforeEach((route, redirect, next) => {
if (route.path !== '/') {
indexScrollTop = document.body.scrollTop;
}
document.title = route.meta.title || document.title;
next();
});
router.afterEach(route => {
if (route.path !== '/') {
document.body.scrollTop = 0;
} else {
Vue.nextTick(() => {
document.body.scrollTop = indexScrollTop;
});
}
});
new Vue({ // eslint-disable-line
render: h => h(App),
router
}).$mount('#app-container');

59
docs/src/index.js Normal file
View File

@ -0,0 +1,59 @@
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './ExamplesDocsApp';
import navConfig from './nav.config.js';
import routes from './router.config';
import ZanUI from 'src/index.js';
import packageJson from '../../package.json';
const isProduction = process.env.NODE_ENV === 'production';
const global = {
version: packageJson.version
};
window._global = global;
import '../assets/docs.css';
import 'packages/vant-css/src/index.css';
function isMobile() {
var platform = navigator.userAgent.toLowerCase();
return (/(android|bb\d+|meego).+mobile|kdtunion|weibo|m2oapp|micromessenger|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i).test(platform) ||
(/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i).test(platform.substr(0, 4));
}
Vue.use(VueRouter);
Vue.use(ZanUI);
Vue.use(ZanUI.Lazyload, {
lazyComponent: true
});
const routesConfig = routes(navConfig);
routesConfig.push({
path: '/',
redirect: '/component/install'
});
const router = new VueRouter({
mode: 'history',
base: isProduction ? '/zanui/vue/' : __dirname,
routes: routesConfig
});
router.beforeEach((route, redirect, next) => {
if (route.path !== '/') {
window.scrollTo(0, 0);
}
const pathname = isProduction ? '/vue/examples' : '/examples.html';
if (isMobile()) {
window.location.replace(pathname);
return;
}
document.title = route.meta.title || document.title;
next();
});
new Vue({ // eslint-disable-line
render: h => h(App),
router
}).$mount('#app-container');

15
docs/src/index.tpl Normal file
View File

@ -0,0 +1,15 @@
<!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, minimum-scale=1.0">
<title>Vant - Vue mobile ui in Youzan</title>
</head>
<body>
<div id="app-container">
<app></app>
</div>
</body>
</html>

159
docs/src/nav.config.js Normal file
View File

@ -0,0 +1,159 @@
/* eslint-disable */
module.exports = {
"zh-CN": [
{
"name": "开发指南",
"groups": [
{
"list": [
{
"path": "/install",
"title": "安装"
},
{
"path": "/quickstart",
"title": "快速上手"
}
]
}
]
},
{
"name": "ZanUI组件",
"showInMobile": true,
"groups": [
{
"groupName": "基础组件",
"list": [
{
"path": "/button",
"title": "Button 按钮"
},
{
"path": "/icon",
"title": "Icon 图标"
},
{
"path": "/cell",
"title": "Cell 单元格"
},
{
"path": "/progress",
"title": "Progress 进度条"
},
{
"path": "/panel",
"title": "Panel 面板"
},
{
"path": "/card",
"title": "Card 图文组件"
},
{
"path": "/loading",
"title": "Loading 加载"
},
{
"path": "/layout",
"title": "Layout 布局"
},
{
"path": "/steps",
"title": "Steps 步骤条"
},
{
"path": "/tag",
"title": "Tag 标记"
},
{
"path": "/badge",
"title": "Badge 徽章"
},
{
"path": "/tab",
"title": "Tab 标签"
},
{
"path": "/popup",
"title": "Popup 弹出菜单"
},
{
"path": "/swipe",
"title": "Swipe 轮播"
},
{
"path": "/search",
"title": "Search 搜索"
},
{
"path": "/quantity",
"title": "Quantity 数量选择"
},
{
"path": "/waterfall",
"title": "Waterfall 瀑布流"
},
{
"path": "/image-preview",
"title": "ImagePreview 图片预览"
},
{
"path": "/lazyload",
"title": "Lazyload 图片懒加载"
}
]
},
{
"groupName": "表单",
"list": [
{
"path": "/switch",
"title": "Switch 开关"
},
{
"path": "/field",
"title": "Field 输入框"
},
{
"path": "/radio",
"title": "Radio 单选框"
},
{
"path": "/checkbox",
"title": "Checkbox 复选框"
},
{
"path": "/uploader",
"title": "Uploader 图片上传"
}
]
},
{
"groupName": "操作反馈",
"list": [
{
"path": "/actionsheet",
"title": "Actionsheet 行动按钮"
},
{
"path": "/toast",
"title": "Toast 轻提示"
},
{
"path": "/picker",
"title": "Picker 选择器"
},
{
"path": "/datetime-picker",
"title": "Datetime Picker 时间选择"
},
{
"path": "/dialog",
"title": "Dialog 弹出框"
}
]
}
]
}
]
}

39
docs/src/router.config.js Normal file
View File

@ -0,0 +1,39 @@
const registerRoute = (navConfig, isExample) => {
let route = [];
let navs = navConfig['zh-CN'];
navs.forEach(nav => {
if (isExample && !nav.showInMobile) {
return;
}
if (nav.groups) {
nav.groups.forEach(group => {
group.list.forEach(nav => {
addRoute(nav);
});
});
} else if (nav.children) {
nav.children.forEach(nav => {
addRoute(nav);
});
} else {
addRoute(nav);
}
});
function addRoute(page) {
const component = isExample
? require(`../examples-dist${page.path}.vue`)
: require(`../examples-docs${page.path}.md`);
route.push({
path: '/component' + page.path,
component: component.default || component
});
}
// console.log(route);
return route;
};
export default registerRoute;

4
lerna.json Normal file
View File

@ -0,0 +1,4 @@
{
"lerna": "2.0.0-beta.31",
"version": "independent"
}

134
package.json Normal file
View File

@ -0,0 +1,134 @@
{
"name": "vant",
"version": "0.1.2",
"description": "有赞vue wap组件库",
"main": "lib/vant.js",
"style": "lib/vant-css/index.css",
"files": [
"lib",
"src",
"packages"
],
"scripts": {
"bootstrap": "yarn || npm i --registry=http://registry.npm.qima-inc.com",
"dev": "npm run build:file && webpack-dev-server --inline --history-api-fallback --hot --config build/webpack.config.js --content-base ./",
"build:file": "node build/bin/build-entry.js",
"build:utils": "cross-env BABEL_ENV=utils babel src --out-dir lib --ignore src/index.js",
"build:vant-css": "gulp build --gulpfile packages/vant-css/gulpfile.js && cp-cli packages/vant-css/lib lib/vant-css",
"build:components": "webpack --progress --hide-modules --config build/webpack.components.js",
"build:vant": "webpack --progress --hide-modules --config build/webpack.build.js && webpack --progress --hide-modules --config build/webpack.build.min.js",
"build:example": "node build/genExamples.js",
"deploy": "npm run deploy:docs && gh-pages -d docs/dist && rimraf docs/dist",
"deploy:docs": "rimraf docs/dist && npm run build:example && cross-env NODE_ENV=production webpack --progress --hide-modules --config build/webpack.config.js",
"dist": "npm run clean && npm run build:file && npm run lint && npm run build:vant && npm run build:components && npm run build:utils && npm run build:vant-css",
"clean": "rimraf lib && rimraf packages/*/lib",
"lint": "felint lint src/**/*.js packages/**/*.{js,vue} build/**/*.js",
"test": "karma start test/unit/karma.conf.js --single-run; npm run coverage",
"test:watch": "karma start test/unit/karma.conf.js",
"coverage": "find test/unit/coverage/lcov-report -name 'index.html' | sed -n 1,1p | xargs -I {} open {} ",
"release": "npm run bootstrap && sh build/release.sh"
},
"repository": {
"type": "git",
"url": "git@gitlab.qima-inc.com:fe/zanui-vue.git"
},
"keywords": [
"youzan",
"vue",
"component"
],
"author": "youzanfe",
"license": "ISC",
"dependencies": {
"raf.js": "0.0.4",
"vue-lazyload": "^1.0.3"
},
"peerDependencies": {
"vue": "2.1.8"
},
"devDependencies": {
"2webpack2": "^1.2.1",
"autoprefixer": "^6.7.5",
"avoriaz": "^1.11.1",
"babel-cli": "^6.14.0",
"babel-core": "^6.17.0",
"babel-eslint": "^6.1.2",
"babel-helper-vue-jsx-merge-props": "^2.0.2",
"babel-loader": "^6.2.5",
"babel-plugin-module-resolver": "^2.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-plugin-transform-vue-jsx": "^3.3.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.16.0",
"babel-runtime": "^6.11.0",
"chai": "^3.5.0",
"chalk": "^1.1.3",
"cheerio": "^0.22.0",
"copy-webpack-plugin": "^4.0.1",
"cp-cli": "^1.0.2",
"cross-env": "^3.1.3",
"css-loader": "^0.24.0",
"decamelize": "^1.2.0",
"eslint-loader": "^1.7.1",
"extract-text-webpack-plugin": "^2.0.0-beta.5",
"felint": "^0.5.0-alpha.3",
"file-loader": "^0.9.0",
"file-save": "^0.2.0",
"gh-pages": "^0.12.0",
"gulp": "^3.9.1",
"gulp-util": "^3.0.8",
"highlight.js": "^9.8.0",
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.22.0",
"inject-loader": "^3.0.0-beta2",
"isparta-loader": "^2.0.0",
"json-loader": "^0.5.4",
"json-templater": "^1.0.4",
"karma": "^1.5.0",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.1",
"karma-mocha": "^1.3.0",
"karma-sinon-chai": "^1.2.4",
"karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.30",
"karma-webpack": "^2.0.2",
"lerna": "2.0.0-beta.31",
"lolex": "^1.5.1",
"markdown-it": "^6.1.1",
"markdown-it-anchor": "^2.5.0",
"markdown-it-container": "^2.0.0",
"mocha": "^3.2.0",
"optimize-css-assets-webpack-plugin": "^1.3.0",
"postcss": "^5.1.2",
"postcss-easy-import": "^2.0.0",
"postcss-loader": "^1.3.3",
"precss": "^1.4.0",
"prismjs": "^1.5.1",
"progress-bar-webpack-plugin": "^1.9.3",
"rimraf": "^2.5.4",
"run-sequence": "^1.2.2",
"saladcss-bem": "^0.0.1",
"sinon": "^1.17.7",
"sinon-chai": "^2.8.0",
"style-loader": "^0.13.1",
"theaterjs": "^3.0.0",
"transliteration": "^1.1.11",
"uppercamelcase": "^1.1.0",
"url-loader": "^0.5.7",
"vue": "2.1.8",
"vue-hot-reload-api": "^1.3.3",
"vue-html-loader": "^1.2.3",
"vue-loader": "^10.3.0",
"vue-markdown-loader": "^0.6.1",
"vue-router": "^2.0.0",
"vue-style-loader": "^1.0.0",
"vue-template-compiler": "2.1.8",
"vue-template-es2015-compiler": "^1.4.2",
"webpack": "^2.2.1",
"webpack-dev-server": "^1.16.3",
"webpack-merge": "^2.0.0",
"webpack-node-externals": "^1.5.4",
"webpack-vendor-chunk-plugin": "^1.0.0"
}
}

View File

@ -0,0 +1,8 @@
## 0.0.2 (2017-01-20)
* 改了bug A
* 加了功能B
## 0.0.1 (2017-01-10)
* 第一版

Some files were not shown because too many files have changed in this diff Show More