Parcourir la source

项目初始化

wanxing il y a 5 mois
commit
2e37989e7b
100 fichiers modifiés avec 3605 ajouts et 0 suppressions
  1. 34 0
      .babelrc
  2. 9 0
      .editorconfig
  3. 9 0
      .eslintignore
  4. 41 0
      .eslintrc.yml
  5. 20 0
      .gitignore
  6. 47 0
      .gitlab-ci.yml
  7. 3 0
      .npmrc
  8. 10 0
      .postcssrc.js
  9. 16 0
      Dockerfile
  10. 27 0
      README.md
  11. 41 0
      build/build.js
  12. 54 0
      build/check-versions.js
  13. 52 0
      build/gulpfile.babel.js
  14. 101 0
      build/utils.js
  15. 22 0
      build/vue-loader.conf.js
  16. 94 0
      build/webpack.base.conf.js
  17. 96 0
      build/webpack.dev.conf.js
  18. 158 0
      build/webpack.prod.conf.js
  19. 7 0
      config/debug-build.json
  20. 7 0
      config/debug.json
  21. 7 0
      config/dev.env.js
  22. 80 0
      config/index.js
  23. 4 0
      config/prod.env.js
  24. 7 0
      config/test.env.js
  25. BIN
      doc/node-sass-lib/darwin-x64-48/binding.node
  26. BIN
      doc/node-sass-lib/darwin-x64-53/binding.node
  27. BIN
      doc/node-sass-lib/win32-x64-48/binding.node
  28. BIN
      doc/node-sass-lib/win32-x64-53/binding.node
  29. BIN
      doc/node-sass-lib/win32-x64-57/binding.node
  30. 707 0
      doc/scss官方文档.md
  31. 294 0
      doc/vuex官方文档.md
  32. 222 0
      doc/vue入门文档.md
  33. 1196 0
      doc/vue官方文档.md
  34. 20 0
      doc/代码规范.md
  35. 29 0
      doc/前端开发规范.md
  36. 45 0
      doc/常见错误.md
  37. 8 0
      docker-compose.yml
  38. 9 0
      index.pug
  39. 113 0
      package.json
  40. 12 0
      src/App.vue
  41. 4 0
      src/assets/icon/iconfont.css
  42. 0 0
      src/assets/icon/iconfont.js
  43. BIN
      src/assets/images/1077.png
  44. BIN
      src/assets/images/123.png
  45. BIN
      src/assets/images/12345-大.png
  46. BIN
      src/assets/images/12345-小.png
  47. BIN
      src/assets/images/12345.png
  48. BIN
      src/assets/images/12345logo.png
  49. BIN
      src/assets/images/app.png
  50. BIN
      src/assets/images/back.png
  51. BIN
      src/assets/images/background.png
  52. BIN
      src/assets/images/clipboard.png
  53. BIN
      src/assets/images/earth.png
  54. BIN
      src/assets/images/earthCircle.png
  55. BIN
      src/assets/images/edit.png
  56. BIN
      src/assets/images/exitImg.png
  57. BIN
      src/assets/images/favicon.ico
  58. BIN
      src/assets/images/governmentCenter1.png
  59. BIN
      src/assets/images/governmentCenter11.png
  60. BIN
      src/assets/images/governmentCenter2.png
  61. BIN
      src/assets/images/governmentCenter22.png
  62. BIN
      src/assets/images/governmentHead.png
  63. BIN
      src/assets/images/governmentLeft1.png
  64. BIN
      src/assets/images/governmentLeft11.png
  65. BIN
      src/assets/images/governmentLeft2.png
  66. BIN
      src/assets/images/governmentLeft22.png
  67. BIN
      src/assets/images/governmentRight1.png
  68. BIN
      src/assets/images/governmentRight11.png
  69. BIN
      src/assets/images/governmentRight2.png
  70. BIN
      src/assets/images/governmentRight22.png
  71. BIN
      src/assets/images/inter.png
  72. BIN
      src/assets/images/left2.png
  73. BIN
      src/assets/images/leftB.png
  74. BIN
      src/assets/images/leftT.png
  75. BIN
      src/assets/images/leftTopBackgroundPicture.png
  76. BIN
      src/assets/images/lightPoint.png
  77. BIN
      src/assets/images/line.png
  78. BIN
      src/assets/images/loginBack.png
  79. BIN
      src/assets/images/loginBackground.png
  80. BIN
      src/assets/images/logo.png
  81. BIN
      src/assets/images/middle2.png
  82. BIN
      src/assets/images/middle_center.png
  83. BIN
      src/assets/images/peopleLine.png
  84. BIN
      src/assets/images/phone.png
  85. BIN
      src/assets/images/publicBig.png
  86. BIN
      src/assets/images/publicBig1.png
  87. BIN
      src/assets/images/publicHead.png
  88. BIN
      src/assets/images/publicSmall.png
  89. BIN
      src/assets/images/publicSmall1.png
  90. BIN
      src/assets/images/rate.png
  91. BIN
      src/assets/images/rectangle1.png
  92. BIN
      src/assets/images/rectangle2.png
  93. BIN
      src/assets/images/rectangle3.png
  94. BIN
      src/assets/images/rectangle4.png
  95. BIN
      src/assets/images/rectangle5.png
  96. BIN
      src/assets/images/rectangle6.png
  97. BIN
      src/assets/images/rectangle7.png
  98. BIN
      src/assets/images/rectangle8.png
  99. BIN
      src/assets/images/right.png
  100. BIN
      src/assets/images/right2.png

+ 34 - 0
.babelrc

@@ -0,0 +1,34 @@
+{
+  "presets": [
+    [
+      "env",
+      {
+        "targets": {
+          "browsers": [
+            "> 1%",
+            "last 2 versions",
+            "not ie <= 8"
+          ]
+        }
+      }
+    ],
+    "stage-2"
+  ],
+  "plugins": [
+    "transform-vue-jsx",
+    "transform-runtime"
+  ],
+  "env": {
+    "test": {
+      "presets": [
+        "env",
+        "stage-2"
+      ],
+      "plugins": [
+        "transform-vue-jsx",
+        "transform-es2015-modules-commonjs",
+        "dynamic-import-node"
+      ]
+    }
+  }
+}

+ 9 - 0
.editorconfig

@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true

+ 9 - 0
.eslintignore

@@ -0,0 +1,9 @@
+/build/
+/config/
+/doc/
+/dist/
+/node_modules/
+/src/assets/icon/iconfont.js
+/*.js
+/test/unit/coverage/
+/src/assets/icon/icon.js

+ 41 - 0
.eslintrc.yml

@@ -0,0 +1,41 @@
+---
+  root: true
+  extends:
+    - eslint:recommended
+    - plugin:vue/essential
+    - standard
+
+  env:
+    browser: true
+
+  parserOptions:
+    parser: babel-eslint
+
+  plugins:
+    - vue
+
+  rules:
+    no-new: 0
+    generator-star-spacing: 0
+    no-debugger: 2
+    comma-dangle: 0
+    no-unused-vars: 1
+    no-console: 0
+    eqeqeq: 2
+    no-else-return: 1
+    no-empty-function: 1
+    no-unexpected-multiline: 1
+    dot-location: 1
+    guard-for-in: 0
+    no-invalid-this: 0
+    space-before-function-paren: 0
+    indent: 0
+    no-eval: 2
+    default-case: 2
+    no-bitwise: 2
+    semi: 0
+    radix: 2
+    max-len: [
+      1,
+      140
+    ]

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+# Created by .ignore support plugin (hsz.mobi)
+/*
+!/build
+!/config
+!/doc
+!/src
+!/test
+!/.babelrc
+!/.editorconfig
+!/.eslintignore
+!/.eslintrc.yml
+!/.gitignore
+!/.npmrc
+!/.postcssrc.js
+!/index.pug
+!/package.json
+!/README.md
+!/yarn.lock
+!/docker*
+!/.gitlab*

+ 47 - 0
.gitlab-ci.yml

@@ -0,0 +1,47 @@
+# This file is a template, and might need editing before it works on your project.
+# Official framework image. Look for the different tagged releases at:
+# https://hub.docker.com/r/library/node/tags/
+
+stages:
+  - build
+  - deploy
+
+variables:
+  PLUGIN_REPO: $CI_REGISTRY_IMAGE
+
+构建:
+  stage: build
+  image: registry.cn-shenzhen.aliyuncs.com/lighttcm/plugins-docker
+  variables:
+    PLUGIN_REGISTRY: $CI_REGISTRY
+    PLUGIN_USERNAME: $CI_REGISTRY_USER
+    PLUGIN_PASSWORD: $CI_REGISTRY_PASSWORD
+    PLUGIN_MIRROR: https://ustc-edu-cn.mirror.aliyuncs.com
+    # PLUGIN_BUILD_ARGS: "MIRROR_URL=$MIRROR_URL,WEB_GIT_OATUH2_PASSWORD=$WEB_GIT_OATUH2_PASSWORD,WEB_GIT_OAUTH_USERNAME=$WEB_GIT_OAUTH_USERNAME"
+    PLUGIN_INSECURE: "true"
+    PLUGIN_CONTEXT: $CI_PROJECT_DIR
+    # PLUGIN_NO_CACHE: "true"
+    PLUGIN_DOCKERFILE: $CI_PROJECT_DIR/Dockerfile
+    PLUGIN_TAGS: &build_tag $CI_COMMIT_REF_SLUG-$CI_COMMIT_SHORT_SHA
+  script:
+    - /bin/drone-docker
+  only:
+    - deploy.stage
+
+部署:
+  stage: deploy
+  image: registry.cn-shenzhen.aliyuncs.com/lighttcm/kubernetes-deploy
+  variables:
+    PLUGIN_KUBERNETES_SERVER: $SINGULARITY_KUBERNETES_SERVER
+    PLUGIN_KUBERNETES_TOKEN: $SINGULARITY_KUBERNETES_TOKEN
+    PLUGIN_KUBERNETES_CERT: $SINGULARITY_KUBERNETES_CERT
+    PLUGIN_NAMESPACE: acupoint
+    PLUGIN_DEPLOYMENT: government-admin
+    PLUGIN_CONTAINER: government-admin
+    PLUGIN_TAG: *build_tag
+  script:
+    - /bin/bash /bin/build.sh
+  only:
+    - deploy.stage
+  when: on_success
+

+ 3 - 0
.npmrc

@@ -0,0 +1,3 @@
+sass_binary_site=https://npmmirror.com/mirrors/node-sass/
+registry=https://registry.npmmirror.com
+# package-lock=false

+ 10 - 0
.postcssrc.js

@@ -0,0 +1,10 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  "plugins": {
+    "postcss-import": {},
+    "postcss-url": {},
+    // to edit target browsers: use "browserslist" field in package.json
+    "autoprefixer": {}
+  }
+}

+ 16 - 0
Dockerfile

@@ -0,0 +1,16 @@
+FROM registry.cn-shenzhen.aliyuncs.com/zhiyuan-health/build-images:node-14-alpine as build-deps
+
+# ARG MIRROR_URL=http://npmmirror.com
+# ENV SASS_BINARY_SITE $MIRROR_URL/repository/npm-sass-mirror
+# ENV NPM_CONFIG_REGISTRY $MIRROR_URL/repository/npm-proxy
+
+# RUN yarn config set sass_binary_site $SASS_BINARY_SITE -g && yarn config set registry $NPM_CONFIG_REGISTRY
+COPY ./ /usr/src/app
+WORKDIR /usr/src/app
+RUN npm install && npm run build
+
+FROM registry.cn-shenzhen.aliyuncs.com/zhiyuan-health/build-images:caddy-2
+COPY --from=build-deps /usr/src/app/dist /usr/share/caddy/
+COPY ./Caddyfile /etc/caddy/Caddyfile
+WORKDIR /usr/share/caddy/
+EXPOSE 20001

+ 27 - 0
README.md

@@ -0,0 +1,27 @@
+## vue-client
+- 前置
+   1. 阅读doc目录文档
+   2. 只需要在src文件夹里面写内容,其它文件不允许修改
+   
+- 项目需要用到的技术
+   - [webpack](http://webpack.github.io/)
+   - [vue](https://cn.vuejs.org/v2/guide/index.html)
+   - [vuex](https://vuex.vuejs.org/zh-cn/intro.html)
+   - [scss](https://www.sass.hk/docs/)
+   - [element-ui](http://element-cn.eleme.io/#/zh-CN/component/installation)
+   - babel
+   - localStorage / sessionStorage
+
+- 使用  
+  - 运行环境: "node": ">= 6.0.0" "npm": ">= 3.0.0"
+    
+  - 安装依赖 
+  ```
+  npm install || yarn
+  ```
+  - 建议使用 yarn  安装地址 https://yarn.bootcss.com/docs/install.html
+
+- 运行
+   - 启动 `npm start`
+   - 编译 `npm run build`
+

+ 41 - 0
build/build.js

@@ -0,0 +1,41 @@
+'use strict'
+require('./check-versions')()
+
+process.env.NODE_ENV = 'production'
+
+const ora = require('ora')
+const rm = require('rimraf')
+const path = require('path')
+const chalk = require('chalk')
+const webpack = require('webpack')
+const config = require('../config')
+const webpackConfig = require('./webpack.prod.conf')
+
+const spinner = ora('building for production...')
+spinner.start()
+
+rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
+  if (err) throw err
+  webpack(webpackConfig, (err, stats) => {
+    spinner.stop()
+    if (err) throw err
+    process.stdout.write(stats.toString({
+      colors: true,
+      modules: false,
+      children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
+      chunks: false,
+      chunkModules: false
+    }) + '\n\n')
+
+    if (stats.hasErrors()) {
+      console.log(chalk.red('  Build failed with errors.\n'))
+      process.exit(1)
+    }
+
+    console.log(chalk.cyan('  Build complete.\n'))
+    console.log(chalk.yellow(
+      '  Tip: built files are meant to be served over an HTTP server.\n' +
+      '  Opening index.html over file:// won\'t work.\n'
+    ))
+  })
+})

+ 54 - 0
build/check-versions.js

@@ -0,0 +1,54 @@
+'use strict'
+const chalk = require('chalk')
+const semver = require('semver')
+const packageConfig = require('../package.json')
+const shell = require('shelljs')
+
+function exec (cmd) {
+  return require('child_process').execSync(cmd).toString().trim()
+}
+
+const versionRequirements = [
+  {
+    name: 'node',
+    currentVersion: semver.clean(process.version),
+    versionRequirement: packageConfig.engines.node
+  }
+]
+
+if (shell.which('npm')) {
+  versionRequirements.push({
+    name: 'npm',
+    currentVersion: exec('npm --version'),
+    versionRequirement: packageConfig.engines.npm
+  })
+}
+
+module.exports = function () {
+  const warnings = []
+
+  for (let i = 0; i < versionRequirements.length; i++) {
+    const mod = versionRequirements[i]
+
+    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
+      warnings.push(mod.name + ': ' +
+        chalk.red(mod.currentVersion) + ' should be ' +
+        chalk.green(mod.versionRequirement)
+      )
+    }
+  }
+
+  if (warnings.length) {
+    console.log('')
+    console.log(chalk.yellow('To use this template, you must update following to modules:'))
+    console.log()
+
+    for (let i = 0; i < warnings.length; i++) {
+      const warning = warnings[i]
+      console.log('  ' + warning)
+    }
+
+    console.log()
+    process.exit(1)
+  }
+}

+ 52 - 0
build/gulpfile.babel.js

@@ -0,0 +1,52 @@
+import gulp from 'gulp'
+import del from 'del'
+import fs from 'fs'
+import path from 'path'
+import request from 'request'
+
+const iconUrl = [
+  '//at.alicdn.com/t/font_587370_tp7x8hrg53lerk9.css',
+  '//at.alicdn.com/t/font_587370_tp7x8hrg53lerk9.js',
+];
+
+function path__dime(expath) {
+  return path.join(__dirname, expath)
+}
+
+/**
+ * 清理编译目录
+ */
+gulp.task('clean', function () {
+  return del.sync(['../dist'], {force: true});
+});
+
+/**
+ * 更新图标库
+ */
+gulp.task('updateIcon', ['clean:icon', 'down:icon'], function () {
+  fs.readFile(path__dime('../src/assets/icon/iconfont.css'), 'utf8', function (err, data) {
+    const regexp = /url\(('\/\/at.alicdn.com\/(\S+)'\))/g;
+    console.log(data.toString().match(regexp));
+  });
+});
+
+/**
+ *  清空图标
+ */
+gulp.task('clean:icon', function () {
+  return del.sync(['../src/assets/icon/**.{js,css}'], {force: true});
+});
+
+/**
+ * 下载图标
+ */
+gulp.task('down:icon', function () {
+  for (let i = 0; i < iconUrl.length; i++) {
+    const fileUrl = `http:${iconUrl[i]}`;
+    const filename = path__dime(`../src/assets/icon/iconfont${fileUrl.match(/\.(css|js)/)[0]}`);
+    request(fileUrl).pipe(fs.createWriteStream(filename)).on('close', function () {
+      console.log('更新完毕')
+    });
+  }
+});
+

+ 101 - 0
build/utils.js

@@ -0,0 +1,101 @@
+'use strict'
+const path = require('path')
+const config = require('../config')
+const ExtractTextPlugin = require('extract-text-webpack-plugin')
+const packageConfig = require('../package.json')
+
+exports.assetsPath = function (_path) {
+  const assetsSubDirectory = process.env.NODE_ENV === 'production'
+    ? config.build.assetsSubDirectory
+    : config.dev.assetsSubDirectory
+
+  return path.posix.join(assetsSubDirectory, _path)
+}
+
+exports.cssLoaders = function (options) {
+  options = options || {}
+
+  const cssLoader = {
+    loader: 'css-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  const postcssLoader = {
+    loader: 'postcss-loader',
+    options: {
+      sourceMap: options.sourceMap
+    }
+  }
+
+  // generate loader string to be used with extract text plugin
+  function generateLoaders (loader, loaderOptions) {
+    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
+
+    if (loader) {
+      loaders.push({
+        loader: loader + '-loader',
+        options: Object.assign({}, loaderOptions, {
+          sourceMap: options.sourceMap
+        })
+      })
+    }
+
+    // Extract CSS when that option is specified
+    // (which is the case during production build)
+    if (options.extract) {
+      return ExtractTextPlugin.extract({
+        use: loaders,
+        fallback: 'vue-style-loader'
+      })
+    } else {
+      return ['vue-style-loader'].concat(loaders)
+    }
+  }
+
+  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
+  return {
+    css: generateLoaders(),
+    postcss: generateLoaders(),
+    less: generateLoaders('less'),
+    sass: generateLoaders('sass', { indentedSyntax: true }),
+    scss: generateLoaders('sass'),
+    stylus: generateLoaders('stylus'),
+    styl: generateLoaders('stylus')
+  }
+}
+
+// Generate loaders for standalone style files (outside of .vue)
+exports.styleLoaders = function (options) {
+  const output = []
+  const loaders = exports.cssLoaders(options)
+
+  for (const extension in loaders) {
+    const loader = loaders[extension]
+    output.push({
+      test: new RegExp('\\.' + extension + '$'),
+      use: loader
+    })
+  }
+
+  return output
+}
+
+exports.createNotifierCallback = () => {
+  const notifier = require('node-notifier')
+
+  return (severity, errors) => {
+    if (severity !== 'error') return
+
+    const error = errors[0]
+    const filename = error.file && error.file.split('!').pop()
+
+    notifier.notify({
+      title: packageConfig.name,
+      message: severity + ': ' + error.name,
+      subtitle: filename || '',
+      icon: path.join(__dirname, 'favicon.ico')
+    })
+  }
+}

+ 22 - 0
build/vue-loader.conf.js

@@ -0,0 +1,22 @@
+'use strict'
+const utils = require('./utils')
+const config = require('../config')
+const isProduction = process.env.NODE_ENV === 'production'
+const sourceMapEnabled = isProduction
+  ? config.build.productionSourceMap
+  : config.dev.cssSourceMap
+
+module.exports = {
+  loaders: utils.cssLoaders({
+    sourceMap: sourceMapEnabled,
+    extract: isProduction
+  }),
+  cssSourceMap: sourceMapEnabled,
+  cacheBusting: config.dev.cacheBusting,
+  transformToRequire: {
+    video: ['src', 'poster'],
+    source: 'src',
+    img: 'src',
+    image: 'xlink:href'
+  }
+}

+ 94 - 0
build/webpack.base.conf.js

@@ -0,0 +1,94 @@
+'use strict'
+const path = require('path')
+const utils = require('./utils')
+const config = require('../config')
+const vueLoaderConfig = require('./vue-loader.conf')
+
+function resolve(dir) {
+  return path.join(__dirname, '..', dir)
+}
+
+const createLintingRule = () => ({
+  // test: /\.(js|vue)$/,
+  // loader: 'eslint-loader',
+  // enforce: 'pre',
+  // include: [resolve('src'), resolve('test')],
+  // options: {
+  //   formatter: require('eslint-friendly-formatter'),
+  //   emitWarning: !config.dev.showEslintErrorsInOverlay
+  // }
+})
+
+module.exports = {
+  context: path.resolve(__dirname, '../'),
+  entry: {
+    app: './src/main.js'
+  },
+  output: {
+    path: config.build.assetsRoot,
+    filename: '[name].js',
+    publicPath: process.env.NODE_ENV === 'production'
+      ? config.build.assetsPublicPath
+      : config.dev.assetsPublicPath
+  },
+  resolve: {
+    extensions: ['.js', '.vue', '.json'],
+    alias: {
+      'vue$': 'vue/dist/vue.esm.js',
+      '@': resolve('src'),
+      'pkgs': resolve('src/packages'),
+      'assets': resolve('src/assets'),
+    }
+  },
+  module: {
+    rules: [
+      // ...(config.dev.useEslint ? [createLintingRule()] : []),
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader',
+        options: vueLoaderConfig
+      },
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
+      },
+      {
+        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('img/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('media/[name].[hash:7].[ext]')
+        }
+      },
+      {
+        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
+        loader: 'url-loader',
+        options: {
+          limit: 10000,
+          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
+        }
+      }
+    ]
+  },
+  node: {
+    // prevent webpack from injecting useless setImmediate polyfill because Vue
+    // source contains it (although only uses it if it's native).
+    setImmediate: false,
+    // prevent webpack from injecting mocks to Node native modules
+    // that does not make sense for the client
+    dgram: 'empty',
+    fs: 'empty',
+    net: 'empty',
+    tls: 'empty',
+    child_process: 'empty'
+  }
+}

+ 96 - 0
build/webpack.dev.conf.js

@@ -0,0 +1,96 @@
+'use strict'
+const utils = require('./utils')
+const webpack = require('webpack')
+const config = require('../config')
+const merge = require('webpack-merge')
+const path = require('path')
+const baseWebpackConfig = require('./webpack.base.conf')
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+const HtmlWebpackPlugin = require('html-webpack-plugin')
+const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
+const portfinder = require('portfinder')
+
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+
+const HOST = process.env.HOST
+const PORT = process.env.PORT && Number(process.env.PORT)
+
+const devWebpackConfig = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({sourceMap: config.dev.cssSourceMap, usePostCSS: true})
+  },
+  // cheap-module-eval-source-map is faster for development
+  devtool: config.dev.devtool,
+
+  // these devServer options should be customized in /config/servers.js
+  devServer: {
+    clientLogLevel: 'warning',
+    historyApiFallback: {
+      rewrites: [
+        {from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html')},
+      ],
+    },
+    hot: true,
+    contentBase: false, // since we use CopyWebpackPlugin.
+    compress: true,
+    host: HOST || config.dev.host,
+    port: PORT || config.dev.port,
+    open: config.dev.autoOpenBrowser,
+    overlay: config.dev.errorOverlay
+      ? {warnings: false, errors: true}
+      : false,
+    publicPath: config.dev.assetsPublicPath,
+    proxy: config.dev.proxyTable,
+    quiet: true, // necessary for FriendlyErrorsPlugin
+    watchOptions: {
+      poll: config.dev.poll,
+    }
+  },
+  plugins: [
+    new webpack.DefinePlugin({
+      'process.env': require('../config/dev.env')
+    }),
+    new webpack.HotModuleReplacementPlugin(),
+    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
+    new webpack.NoEmitOnErrorsPlugin(),
+    new HtmlWebpackPlugin({
+      filename: 'index.html',
+      template: '!!pug-loader!index.pug',
+      inject: true,
+      title: '巴中政务可视化',
+      favicon: path.resolve(__dirname, '../src/assets/images/favicon.ico'),
+    }),
+    // new CopyWebpackPlugin([
+    //   {
+    //     from: path.resolve(__dirname, '../static'),
+    //     to: config.dev.assetsSubDirectory,
+    //     ignore: ['.*']
+    //   }
+    // ])
+  ].concat(config.dev.bundleAnalyzerReport ? new BundleAnalyzerPlugin() : [])
+})
+
+module.exports = new Promise((resolve, reject) => {
+  portfinder.basePort = process.env.PORT || config.dev.port
+  portfinder.getPort((err, port) => {
+    if (err) {
+      reject(err)
+    } else {
+      // publish the new Port, necessary for e2e tests
+      process.env.PORT = port
+      // add port to devServer config
+      devWebpackConfig.devServer.port = port
+
+      // Add FriendlyErrorsPlugin
+      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
+        compilationSuccessInfo: {
+          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
+        },
+        onErrors: config.dev.notifyOnErrors
+          ? utils.createNotifierCallback()
+          : undefined
+      }))
+      resolve(devWebpackConfig)
+    }
+  })
+})

+ 158 - 0
build/webpack.prod.conf.js

@@ -0,0 +1,158 @@
+'use strict'
+const path = require('path');
+const utils = require('./utils');
+const webpack = require('webpack');
+const config = require('../config');
+const merge = require('webpack-merge');
+const baseWebpackConfig = require('./webpack.base.conf');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
+const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
+
+const env = process.env.NODE_ENV === 'testing'
+  ? require('../config/test.env')
+  : require('../config/prod.env')
+
+const webpackConfig = merge(baseWebpackConfig, {
+  module: {
+    rules: utils.styleLoaders({
+      sourceMap: config.build.productionSourceMap,
+      extract: true,
+      usePostCSS: true
+    })
+  },
+  devtool: config.build.productionSourceMap ? config.build.devtool : false,
+  output: {
+    path: config.build.assetsRoot,
+    filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
+    chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
+  },
+  plugins: [
+    // http://vuejs.github.io/vue-loader/en/workflow/production.html
+    new webpack.DefinePlugin({
+      'process.env': env
+    }),
+    new UglifyJsPlugin({
+      uglifyOptions: {
+        compress: {
+          warnings: false
+        }
+      },
+      sourceMap: config.build.productionSourceMap,
+      parallel: true
+    }),
+    // extract css into its own file
+    new ExtractTextPlugin({
+      filename: utils.assetsPath('css/[name].[contenthash:8].css'),
+      // Setting the following option to `false` will not extract CSS from codesplit chunks.
+      // Their CSS will instead be inserted dynamically with styles-loader when the codesplit chunk has been loaded by webpack.
+      // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
+      // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
+      allChunks: true,
+    }),
+    // Compress extracted CSS. We are using this plugin so that possible
+    // duplicated CSS from different components can be deduped.
+    new OptimizeCSSPlugin({
+      cssProcessorOptions: config.build.productionSourceMap
+        ? {safe: true, map: {inline: false}}
+        : {safe: true}
+    }),
+    // generate dist index.html with correct asset hash for caching.
+    // you can customize output by editing /index.html
+    // see https://github.com/ampedandwired/html-webpack-plugin
+    new HtmlWebpackPlugin({
+      filename: process.env.NODE_ENV === 'testing'
+        ? 'index.html'
+        : config.build.index,
+      template: '!!pug-loader!index.pug',
+      inject: true,
+      title: '巴中政务可视化',
+      favicon: path.resolve(__dirname, '../src/assets/images/favicon.ico'),
+      minify: {
+        removeComments: true,
+        collapseWhitespace: true,
+        removeAttributeQuotes: true
+        // more options:
+        // https://github.com/kangax/html-minifier#options-quick-reference
+      },
+      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
+      chunksSortMode: 'dependency'
+    }),
+    // keep module.id stable when vendor modules does not change
+    new webpack.HashedModuleIdsPlugin(),
+    // enable scope hoisting
+    new webpack.optimize.ModuleConcatenationPlugin(),
+    // split vendor js into its own file
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'vendor',
+      minChunks(module) {
+        // any required modules inside node_modules are extracted to vendor
+        return (
+          module.resource &&
+          /\.js$/.test(module.resource) &&
+          module.resource.indexOf(
+            path.join(__dirname, '../node_modules')
+          ) === 0
+        )
+      }
+    }),
+    // extract webpack runtime and module manifest to its own file in order to
+    // prevent vendor hash from being updated whenever app bundle is updated
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'manifest',
+      minChunks: Infinity
+    }),
+    // This instance extracts shared chunks from code splitted chunks and bundles them
+    // in a separate chunk, similar to the vendor chunk
+    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
+    new webpack.optimize.CommonsChunkPlugin({
+      name: 'app',
+      async: 'vendor-async',
+      children: true,
+      minChunks: 3
+    }),
+    // split vue2-edito into its own file
+    new webpack.optimize.CommonsChunkPlugin({
+      async: 'vue2-editor',
+      minChunks(module) {
+        const context = module.context;
+        return context && (context.indexOf('vue2-editor') >= 0);
+      }
+    }),
+    // copy custom static assets
+    // new CopyWebpackPlugin([
+    //   {
+    //     from: path.resolve(__dirname, '../static'),
+    //     to: config.build.assetsSubDirectory,
+    //     ignore: ['.*']
+    //   }
+    // ])
+  ]
+})
+
+if (config.build.productionGzip) {
+  const CompressionWebpackPlugin = require('compression-webpack-plugin')
+
+  webpackConfig.plugins.push(
+    new CompressionWebpackPlugin({
+      asset: '[path].gz[query]',
+      algorithm: 'gzip',
+      test: new RegExp(
+        '\\.(' +
+        config.build.productionGzipExtensions.join('|') +
+        ')$'
+      ),
+      threshold: 10240,
+      minRatio: 0.8
+    })
+  )
+}
+
+if (config.build.bundleAnalyzerReport) {
+  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
+  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
+}
+
+module.exports = webpackConfig

+ 7 - 0
config/debug-build.json

@@ -0,0 +1,7 @@
+{
+  "servers": "/server",
+  "dev": {
+    "port": 3000,
+    "host": "127.0.0.1"
+  }
+}

+ 7 - 0
config/debug.json

@@ -0,0 +1,7 @@
+{
+  "servers": "http://127.0.0.1:8090",
+  "dev": {
+    "port": 3000,
+    "host": "127.0.0.1"
+  }
+}

+ 7 - 0
config/dev.env.js

@@ -0,0 +1,7 @@
+'use strict'
+const merge = require('webpack-merge')
+const prodEnv = require('./prod.env')
+
+module.exports = merge(prodEnv, {
+  NODE_ENV: '"development"'
+})

+ 80 - 0
config/index.js

@@ -0,0 +1,80 @@
+'use strict'
+// Template version: 1.3.1
+// see http://vuejs-templates.github.io/webpack for documentation.
+
+const path = require('path')
+const debug = require('./debug.json')
+
+module.exports = {
+  dev: {
+
+    // Paths
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+    proxyTable: {},
+
+    // Various Dev Server settings
+    host: debug.dev.host, // can be overwritten by process.env.HOST
+    port: debug.dev.port, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
+    autoOpenBrowser: true,
+    errorOverlay: true,
+    notifyOnErrors: true,
+    poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
+
+    // Use Eslint Loader?
+    // If true, your code will be linted during bundling and
+    // linting errors and warnings will be shown in the console.
+    useEslint: false,
+    // If true, eslint errors and warnings will also be shown in the error overlay
+    // in the browser.
+    showEslintErrorsInOverlay: false,
+
+    /**
+     * Source Maps
+     */
+
+    // https://webpack.js.org/configuration/devtool/#development
+    devtool: 'cheap-module-eval-source-map',
+
+    // If you have problems debugging vue-files in devtools,
+    // set this to false - it *may* help
+    // https://vue-loader.vuejs.org/en/options.html#cachebusting
+    cacheBusting: true,
+
+    cssSourceMap: true,
+
+    // Set to `true` or `false` to always turn it on or off
+    bundleAnalyzerReport: false
+  },
+
+  build: {
+    // Template for index.html
+    index: path.resolve(__dirname, '../dist/index.html'),
+
+    // Paths
+    assetsRoot: path.resolve(__dirname, '../dist'),
+    assetsSubDirectory: 'static',
+    assetsPublicPath: '/',
+
+    /**
+     * Source Maps
+     */
+
+    productionSourceMap: false,
+    // https://webpack.js.org/configuration/devtool/#production
+    devtool: '#source-map',
+
+    // Gzip off by default as many popular static hosts such as
+    // Surge or Netlify already gzip all static assets for you.
+    // Before setting to `true`, make sure to:
+    // npm install --save-dev compression-webpack-plugin
+    productionGzip: false,
+    productionGzipExtensions: ['js', 'css'],
+
+    // Run the build command with an extra argument to
+    // View the bundle analyzer report after build finishes:
+    // `npm run build --report`
+    // Set to `true` or `false` to always turn it on or off
+    bundleAnalyzerReport: process.env.npm_config_report
+  }
+}

+ 4 - 0
config/prod.env.js

@@ -0,0 +1,4 @@
+'use strict'
+module.exports = {
+  NODE_ENV: '"production"'
+}

+ 7 - 0
config/test.env.js

@@ -0,0 +1,7 @@
+'use strict'
+const merge = require('webpack-merge')
+const devEnv = require('./dev.env')
+
+module.exports = merge(devEnv, {
+  NODE_ENV: '"testing"'
+})

BIN
doc/node-sass-lib/darwin-x64-48/binding.node


BIN
doc/node-sass-lib/darwin-x64-53/binding.node


BIN
doc/node-sass-lib/win32-x64-48/binding.node


BIN
doc/node-sass-lib/win32-x64-53/binding.node


BIN
doc/node-sass-lib/win32-x64-57/binding.node


+ 707 - 0
doc/scss官方文档.md

@@ -0,0 +1,707 @@
+<h2 id="t4">4. CSS 功能拓展 (CSS Extensions)</h2>
+
+<h3 id="t4-1">4.1. 嵌套规则 (Nested Rules)</h3>
+
+Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器,例如:
+
+```scss
+#main p {
+  color: #00ff00;
+  width: 97%;
+
+  .redbox {
+    background-color: #ff0000;
+    color: #000000;
+  }
+}
+```
+
+编译为
+
+```css
+#main p {
+  color: #00ff00;
+  width: 97%; }
+  #main p .redbox {
+    background-color: #ff0000;
+    color: #000000; }
+```
+
+嵌套功能避免了重复输入父选择器,而且令复杂的 CSS 结构更易于管理:
+
+```scss
+#main {
+  width: 97%;
+
+  p, div {
+    font-size: 2em;
+    a { font-weight: bold; }
+  }
+
+  pre { font-size: 3em; }
+}
+```
+
+编译为
+
+```css
+#main {
+  width: 97%; }
+  #main p, #main div {
+    font-size: 2em; }
+    #main p a, #main div a {
+      font-weight: bold; }
+  #main pre {
+    font-size: 3em; }
+```
+
+<h3 id="t4-2">4.2. 父选择器 `&` (Referencing Parent Selectors: `&`)</h3>
+
+在嵌套 CSS 规则时,有时也需要直接使用嵌套外层的父选择器,例如,当给某个元素设定 `hover` 样式时,或者当 `body` 元素有某个 classname 时,可以用 `&` 代表嵌套规则外层的父选择器。
+
+```scss
+a {
+  font-weight: bold;
+  text-decoration: none;
+  &:hover { text-decoration: underline; }
+  body.firefox & { font-weight: normal; }
+}
+```
+
+编译为
+
+```css
+a {
+  font-weight: bold;
+  text-decoration: none; }
+  a:hover {
+    text-decoration: underline; }
+  body.firefox a {
+    font-weight: normal; }
+```
+
+编译后的 CSS 文件中 `&` 将被替换成嵌套外层的父选择器,如果含有多层嵌套,最外层的父选择器会一层一层向下传递:
+
+```scss
+#main {
+  color: black;
+  a {
+    font-weight: bold;
+    &:hover { color: red; }
+  }
+}
+```
+
+编译为
+
+```css
+#main {
+  color: black; }
+  #main a {
+    font-weight: bold; }
+    #main a:hover {
+      color: red; }
+```
+
+`&` 必须作为选择器的第一个字符,其后可以跟随后缀生成复合的选择器,例如
+
+```scss
+#main {
+  color: black;
+  &-sidebar { border: 1px solid; }
+}
+```
+
+编译为
+
+```css
+#main {
+  color: black; }
+  #main-sidebar {
+    border: 1px solid; }
+```
+
+当父选择器含有不合适的后缀时,Sass 将会报错。
+
+<h3 id="t4-3">4.3. 属性嵌套 (Nested Properties)</h3>
+
+有些 CSS 属性遵循相同的命名空间 (namespace),比如 `font-family, font-size, font-weight` 都以 `font` 作为属性的命名空间。为了便于管理这样的属性,同时也为了避免了重复输入,Sass 允许将属性嵌套在命名空间中,例如:
+
+```scss
+.funky {
+  font: {
+    family: fantasy;
+    size: 30em;
+    weight: bold;
+  }
+}
+```
+
+编译为
+
+```css
+.funky {
+  font-family: fantasy;
+  font-size: 30em;
+  font-weight: bold; }
+```
+
+命名空间也可以包含自己的属性值,例如:
+
+```scss
+.funky {
+  font: 20px/24px {
+    family: fantasy;
+    weight: bold;
+  }
+}
+```
+
+编译为
+
+```css
+.funky {
+  font: 20px/24px;
+    font-family: fantasy;
+    font-weight: bold; }
+```
+
+<h3 id="t4-4">4.4. 占位符选择器 `%foo` (Placeholder Selectors: `%foo`)</h3>
+
+Sass 额外提供了一种特殊类型的选择器:占位符选择器 (placeholder selector)。与常用的 id 与 class 选择器写法相似,只是 `#` 或 `.` 替换成了 `%`。必须通过 [@extend](#t7-3) 指令调用,更多介绍请查阅 [@extend-Only Selectors](#t7-3-6)。
+
+当占位符选择器单独使用时(未通过 `@extend` 调用),不会编译到 CSS 文件中。
+
+<h2 id="t6">6. SassScript</h2>
+
+在 CSS 属性的基础上 Sass 提供了一些名为 SassScript 的新功能。 SassScript 可作用于任何属性,允许属性使用变量、算数运算等额外功能。
+
+通过 interpolation,SassScript 甚至可以生成选择器或属性名,这一点对编写 mixin 有很大帮助。
+
+<h3 id="t6-1">6.1. Interactive Shell</h3>
+
+Interactive Shell 可以在命令行中测试 SassScript 的功能。在命令行中输入 `sass -i`,然后输入想要测试的 SassScript 查看输出结果:
+
+```
+$ sass -i
+>> "Hello, Sassy World!"
+"Hello, Sassy World!"
+>> 1px + 1px + 1px
+3px
+>> #777 + #777
+#eeeeee
+>> #777 + #888
+white
+```
+
+<h3 id="t6-2">6.2. 变量 `$` (Variables: `$`)</h3>
+
+SassScript 最普遍的用法就是变量,变量以美元符号开头,赋值方法与 CSS 属性的写法一样:
+
+```scss
+$width: 5em;
+```
+
+直接使用即调用变量:
+
+```css
+#main {
+  width: $width;
+}
+```
+
+变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 `!global` 声明:
+
+```scss
+#main {
+  $width: 5em !global;
+  width: $width;
+}
+
+#sidebar {
+  width: $width;
+}
+```
+
+编译为
+
+```css
+#main {
+  width: 5em;
+}
+
+#sidebar {
+  width: 5em;
+}
+```
+
+<h3 id="t6-3">6.3. 数据类型 (Data Types)</h3>
+
+SassScript 支持 6 种主要的数据类型:
+
+- 数字,`1, 2, 13, 10px`
+- 字符串,有引号字符串与无引号字符串,`"foo", 'bar', baz`
+- 颜色,`blue, #04a3f9, rgba(255,0,0,0.5)`
+- 布尔型,`true, false`
+- 空值,`null`
+- 数组 (list),用空格或逗号作分隔符,`1.5em 1em 0 2em, Helvetica, Arial, sans-serif`
+- maps, 相当于 JavaScript 的 object,`(key1: value1, key2: value2)`
+
+SassScript 也支持其他 CSS 属性值,比如 Unicode 字符集,或 `!important` 声明。然而Sass 不会特殊对待这些属性值,一律视为无引号字符串。
+
+<h4 id="t6-3-1">6.3.1. 字符串 (Strings)</h4>
+
+SassScript 支持 CSS 的两种字符串类型:有引号字符串 (quoted strings),如 `"Lucida Grande"` `'http://sass-lang.com'`;与无引号字符串 (unquoted strings),如 `sans-serif` `bold`,在编译 CSS 文件时不会改变其类型。只有一种情况例外,使用 `#{}` (interpolation) 时,有引号字符串将被编译为无引号字符串,这样便于在 mixin 中引用选择器名:
+
+```scss
+@mixin firefox-message($selector) {
+  body.firefox #{$selector}:before {
+    content: "Hi, Firefox users!";
+  }
+}
+@include firefox-message(".header");
+```
+
+编译为
+
+```css
+body.firefox .header:before {
+  content: "Hi, Firefox users!"; }
+```
+
+<h4 id="t6-3-2">6.3.2. 数组 (Lists)</h4>
+
+数组 (lists) 指 Sass 如何处理 CSS 中 `margin: 10px 15px 0 0` 或者 `font-face: Helvetica, Arial, sans-serif` 这样通过空格或者逗号分隔的一系列的值。事实上,独立的值也被视为数组 —— 只包含一个值的数组。
+
+数组本身没有太多功能,但 [Sass list functions](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#list-functions) 赋予了数组更多新功能:`nth` 函数可以直接访问数组中的某一项;`join` 函数可以将多个数组连接在一起;`append` 函数可以在数组中添加新值;而 `@each` 指令能够遍历数组中的每一项。
+
+数组中可以包含子数组,比如 `1px 2px, 5px 6px` 是包含 `1px 2px` 与 `5px 6px` 两个数组的数组。如果内外两层数组使用相同的分隔方式,需要用圆括号包裹内层,所以也可以写成 `(1px 2px) (5px 6px)`。变化是,之前的 `1px 2px, 5px 6px` 使用逗号分割了两个子数组 (comma-separated),而 `(1px 2px) (5px 6px)` 则使用空格分割(space-separated)。
+
+当数组被编译为 CSS 时,Sass 不会添加任何圆括号(CSS 中没有这种写法),所以 `(1px 2px) (5px 6px)` 与 `1px 2px, 5px 6px` 在编译后的 CSS 文件中是完全一样的,但是它们在 Sass 文件中却有不同的意义,前者是包含两个数组的数组,而后者是包含四个值的数组。
+
+用 `()` 表示不包含任何值的空数组(在 Sass 3.3 版之后也视为空的 map)。空数组不可以直接编译成 CSS,比如编译 `font-family: ()` Sass 将会报错。如果数组中包含空数组或空值,编译时将被清除,比如 `1px 2px () 3px` 或 `1px 2px null 3px`。
+
+基于逗号分隔的数组允许保留结尾的逗号,这样做的意义是强调数组的结构关系,尤其是需要声明只包含单个值的数组时。例如 `(1,)` 表示只包含 `1` 的数组,而 `(1 2 3,)` 表示包含 `1 2 3` 这个以空格分隔的数组的数组。
+
+<h4 id="t6-3-3">6.3.3. Maps</h3>
+
+Maps represent an association between keys and values, where keys are used to look up values. They make it easy to collect values into named groups and access those groups dynamically. They have no direct parallel in CSS, although they’re syntactically similar to media query expressions:
+
+```scss
+$map: (key1: value1, key2: value2, key3: value3);
+```
+
+Unlike lists, maps must always be surrounded by parentheses and must always be comma-separated. Both the keys and values in maps can be any SassScript object. A map may only have one value associated with a given key (although that value may be a list). A given value may be associated with many keys, though.
+
+Like lists, maps are mostly manipulated using SassScript functions. The map-get function looks up values in a map and the map-merge function adds values to a map. The @each directive can be used to add styles for each key/value pair in a map. The order of pairs in a map is always the same as when the map was created.
+
+Maps can also be used anywhere lists can. When used by a list function, a map is treated as a list of pairs. For example, (key1: value1, key2: value2) would be treated as the nested list key1 value1, key2 value2 by list functions. Lists cannot be treated as maps, though, with the exception of the empty list. () represents both a map with no key/value pairs and a list with no elements.
+
+Note that map keys can be any Sass data type (even another map) and the syntax for declaring a map allows arbitrary SassScript expressions that will be evaluated to determine the key.
+
+Maps cannot be converted to plain CSS. Using one as the value of a variable or an argument to a CSS function will cause an error. Use the inspect($value) function to produce an output string useful for debugging maps.
+
+<h4 id="t6-3-4">6.3.4. 颜色 (Colors)</h3>
+
+Any CSS color expression returns a SassScript Color value. This includes a large number of named colors which are indistinguishable from unquoted strings.
+
+In compressed output mode, Sass will output the smallest CSS representation of a color. For example, #FF0000 will output as red in compressed mode, but blanchedalmond will output as #FFEBCD.
+
+A common issue users encounter with named colors is that since Sass prefers the same output format as was typed in other output modes, a color interpolated into a selector becomes invalid syntax when compressed. To avoid this, always quote named colors if they are meant to be used in the construction of a selector.
+
+<h3 id="t6-4">6.4. 运算 (Operations)</h3>
+
+所有数据类型均支持相等运算 `==` 或 `!=`,此外,每种数据类型也有其各自支持的运算方式。
+
+<h4 id="t6-4-1">6.4.1. 数字运算 (Number Operations)</h4>
+
+SassScript 支持数字的加减乘除、取整等运算 (`+, -, *, /, %`),如果必要会在不同单位间转换值。
+
+```scss
+p {
+  width: 1in + 8pt;
+}
+```
+
+编译为
+
+```css
+p {
+  width: 1.111in; }
+```
+
+关系运算 `<, >, <=, >=` 也可用于数字运算,相等运算 `==, !=` 可用于所有数据类型。
+
+<h5 id="t6-4-1-1">6.4.1.1. 除法运算 `/` (Division and `/`)</h5>
+
+`/` 在 CSS 中通常起到分隔数字的用途,SassScript 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了 `/` 除法运算的功能。也就是说,如果 `/` 在 SassScript 中把两个数字分隔,编译后的 CSS 文件中也是同样的作用。
+
+以下三种情况 `/` 将被视为除法运算符号:
+
+* 如果值,或值的一部分,是变量或者函数的返回值
+* 如果值被圆括号包裹
+* 如果值是算数表达式的一部分
+
+```scss
+p {
+  font: 10px/8px;             // Plain CSS, no division
+  $width: 1000px;
+  width: $width/2;            // Uses a variable, does division
+  width: round(1.5)/2;        // Uses a function, does division
+  height: (500px/2);          // Uses parentheses, does division
+  margin-left: 5px + 8px/2px; // Uses +, does division
+}
+```
+
+编译为
+
+```css
+p {
+  font: 10px/8px;
+  width: 500px;
+  height: 250px;
+  margin-left: 9px; }
+```
+
+如果需要使用变量,同时又要确保 `/` 不做除法运算而是完整地编译到 CSS 文件中,只需要用 `#{}` 插值语句将变量包裹。
+
+```scss
+p {
+  $font-size: 12px;
+  $line-height: 30px;
+  font: #{$font-size}/#{$line-height};
+}
+```
+
+编译为
+
+```css
+p {
+  font: 12px/30px; }
+```
+
+<h4 id="t6-4-2">6.4.2. 颜色值运算 (Color Operations)</h4>
+
+颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值:
+
+```scss
+p {
+  color: #010203 + #040506;
+}
+```
+
+计算 `01 + 04 = 05` `02 + 05 = 07` `03 + 06 = 09`,然后编译为
+
+```css
+p {
+  color: #050709; }
+```
+
+使用 [color functions](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html) 比计算颜色值更方便一些。
+
+数字与颜色值之间也可以进行算数运算,同样也是分段计算的,比如
+
+```scss
+p {
+  color: #010203 * 2;
+}
+```
+
+计算 `01 * 2 = 02` `02 * 2 = 04` `03 * 2 = 06`,然后编译为
+
+```css
+p {
+  color: #020406; }
+```
+
+需要注意的是,如果颜色值包含 alpha channel(rgba 或 hsla 两种颜色值),必须拥有相等的 alpha 值才能进行运算,因为算术运算不会作用于 alpha 值。
+
+```scss
+p {
+  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
+}
+```
+
+编译为
+
+```css
+p {
+  color: rgba(255, 255, 0, 0.75); }
+```
+
+颜色值的 alpha channel 可以通过 [opacify](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#opacify-instance_method) 或 [transparentize](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#transparentize-instance_method) 两个函数进行调整。
+
+```scss
+$translucent-red: rgba(255, 0, 0, 0.5);
+p {
+  color: opacify($translucent-red, 0.3);
+  background-color: transparentize($translucent-red, 0.25);
+}
+```
+
+编译为
+
+```css
+p {
+  color: rgba(255, 0, 0, 0.8);
+  background-color: rgba(255, 0, 0, 0.25); }
+```
+
+IE 滤镜要求所有的颜色值包含 alpha 层,而且格式必须固定 `#AABBCCDD`,使用 `ie_hex_str` 函数可以很容易地将颜色转化为 IE 滤镜要求的格式。
+
+```scss
+$translucent-red: rgba(255, 0, 0, 0.5);
+$green: #00ff00;
+div {
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}');
+}
+```
+
+编译为
+
+```css
+div {
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#FF00FF00, endColorstr=#80FF0000);
+}
+```
+
+<h4 id="t6-4-3">6.4.3. 字符串运算 (String Operations)</h4>
+
+`+` 可用于连接字符串
+
+```scss
+p {
+  cursor: e + -resize;
+}
+```
+
+编译为
+
+```css
+p {
+  cursor: e-resize; }
+```
+
+注意,如果有引号字符串(位于 `+` 左侧)连接无引号字符串,运算结果是有引号的,相反,无引号字符串(位于 `+` 左侧)连接有引号字符串,运算结果则没有引号。
+
+```scss
+p:before {
+  content: "Foo " + Bar;
+  font-family: sans- + "serif";
+}
+```
+
+编译为
+
+```css
+p:before {
+  content: "Foo Bar";
+  font-family: sans-serif; }
+```
+
+运算表达式与其他值连用时,用空格做连接符:
+
+```scss
+p {
+  margin: 3px + 4px auto;
+}
+```
+
+编译为
+
+```css
+p {
+  margin: 7px auto; }
+```
+
+在有引号的文本字符串中使用 `#{}` 插值语句可以添加动态的值:
+
+```scss
+p:before {
+  content: "I ate #{5 + 10} pies!";
+}
+```
+
+编译为
+
+```css
+p:before {
+  content: "I ate 15 pies!"; }
+```
+
+空的值被视作插入了空字符串:
+
+```scss
+$value: null;
+p:before {
+  content: "I ate #{$value} pies!";
+}
+```
+
+编译为
+
+```css
+p:before {
+  content: "I ate pies!"; }
+```
+
+<h4 id="t6-4-4">6.4.4. 布尔运算 (Boolean Operations)</h4>
+
+SassScript 支持布尔型的 `and` `or` 以及 `not` 运算。
+
+<h4 id="t6-4-5">6.4.5. 数组运算 (List Operations)</h4>
+
+数组不支持任何运算方式,只能使用 [list functions](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#list-functions) 控制。
+
+<h3 id="t6-5">6.5. 圆括号 (Parentheses)</h3>
+
+圆括号可以用来影响运算的顺序:
+
+```scss
+p {
+  width: 1em + (2em * 3);
+}
+```
+
+编译为
+
+```css
+p {
+  width: 7em; }
+```
+
+<h3 id="t6-6">6.6. 函数 (Functions)</h3>
+
+SassScript 定义了多种函数,有些甚至可以通过普通的 CSS 语句调用:
+
+```scss
+p {
+  color: hsl(0, 100%, 50%);
+}
+```
+
+编译为
+
+```css
+p {
+  color: #ff0000; }
+```
+
+<h4 id="t6-6-1">6.6.1. 关键词参数 (Keyword Arguments)</h4>
+
+Sass 函数允许使用关键词参数 (keyword arguments),上面的例子也可以写成:
+
+```scss
+p {
+  color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);
+}
+```
+
+虽然不够简明,但是阅读起来会更方便。关键词参数给函数提供了更灵活的接口,以及容易调用的参数。关键词参数可以打乱顺序使用,如果使用默认值也可以省缺,另外,参数名被视为变量名,下划线、短横线可以互换使用。
+
+通过 [Sass::Script::Functions](http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html) 查看完整的 Sass 函数列表,参数名,以及如何自定义函数。
+
+<h3 id="t6-7">6.7. 插值语句 `#{}` (Interpolation: `#{}`)</h3>
+
+通过 `#{}` 插值语句可以在选择器或属性名中使用变量:
+
+```scss
+$name: foo;
+$attr: border;
+p.#{$name} {
+  #{$attr}-color: blue;
+}
+```
+
+编译为
+
+```css
+p.foo {
+  border-color: blue; }
+```
+
+`#{}` 插值语句也可以在属性值中插入 SassScript,大多数情况下,这样可能还不如使用变量方便,但是使用 `#{}` 可以避免 Sass 运行运算表达式,直接编译 CSS。
+
+```scss
+p {
+  $font-size: 12px;
+  $line-height: 30px;
+  font: #{$font-size}/#{$line-height};
+}
+```
+
+编译为
+
+```css
+p {
+  font: 12px/30px; }
+```
+
+<h3 id="t6-8">6.8. `&` in SassScript</h3>
+
+Just like when it’s used in selectors, & in SassScript refers to the current parent selector. It’s a comma-separated list of space-separated lists. For example:
+
+```scss
+.foo.bar .baz.bang, .bip.qux {
+  $selector: &;
+}
+```
+
+The value of $selector is now ((".foo.bar" ".baz.bang"), ".bip.qux"). The compound selectors are quoted here to indicate that they’re strings, but in reality they would be unquoted. Even if the parent selector doesn’t contain a comma or a space, & will always have two levels of nesting, so it can be accessed consistently.
+
+If there is no parent selector, the value of & will be null. This means you can use it in a mixin to detect whether a parent selector exists:
+
+```scss
+@mixin does-parent-exist {
+  @if & {
+    &:hover {
+      color: red;
+    }
+  } @else {
+    a {
+      color: red;
+    }
+  }
+}
+```
+
+<h3 id="t6-9">6.9. 变量定义 `!default` (Variable Defaults: `!default`)</h3>
+
+可以在变量的结尾添加 `!default` 给一个未通过 `!default` 声明赋值的变量赋值,此时,如果变量已经被赋值,不会再被重新赋值,但是如果变量还没有被赋值,则会被赋予新的值。
+
+```scss
+$content: "First content";
+$content: "Second content?" !default;
+$new_content: "First time reference" !default;
+
+#main {
+  content: $content;
+  new-content: $new_content;
+}
+```
+
+编译为
+
+```css
+#main {
+  content: "First content";
+  new-content: "First time reference"; }
+```
+
+变量是 null 空值时将视为未被 `!default` 赋值。
+
+```scss
+$content: null;
+$content: "Non-null content" !default;
+
+#main {
+  content: $content;
+}
+```
+
+编译为
+
+```css
+#main {
+  content: "Non-null content"; }
+```

+ 294 - 0
doc/vuex官方文档.md

@@ -0,0 +1,294 @@
+# Vuex 是什么?
+
+Vuex 是一个专为 Vue.js 应用程序开发的**状态管理模式**。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 [devtools extension](https://github.com/vuejs/vue-devtools),提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
+
+### 什么是“状态管理模式”?
+
+让我们从一个简单的 Vue 计数应用开始:
+
+``` js
+new Vue({
+  // state
+  data () {
+    return {
+      count: 0
+    }
+  },
+  // view
+  template: `
+    <div>{{ count }}</div>
+  `,
+  // actions
+  methods: {
+    increment () {
+      this.count++
+    }
+  }
+})
+```
+
+这个状态自管理应用包含以下几个部分:
+
+- **state**,驱动应用的数据源;
+- **view**,以声明方式将 **state** 映射到视图;
+- **actions**,响应在 **view** 上的用户输入导致的状态变化。
+
+以下是一个表示“单向数据流”理念的极简示意:
+
+<p style="text-align: center; margin: 2em;">
+  <img style="width: 100%; max-width: 450px;" src="./images/flow.png">
+</p>
+
+但是,当我们的应用遇到**多个组件共享状态**时,单向数据流的简洁性很容易被破坏:
+
+- 多个视图依赖于同一状态。
+- 来自不同视图的行为需要变更同一状态。
+
+对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
+
+因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
+
+另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。
+
+这就是 Vuex 背后的基本思想,借鉴了 [Flux](https://facebook.github.io/flux/docs/overview.html)、[Redux](http://redux.js.org/)、和 [The Elm Architecture](https://guide.elm-lang.org/architecture/)。与其他模式不同的是,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
+
+![vuex](./images/vuex.png)
+
+### 什么情况下我应该使用 Vuex?
+
+虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
+
+如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 [global event bus](https://cn.vuejs.org/v2/guide/components.html#非父子组件通信) 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:
+
+> Flux 架构就像眼镜:您自会知道什么时候需要它。
+
+# 核心概念
+
+在这一章,我们将会学到 Vuex 的这些核心概念。他们是:
+  - [State](state.md)
+  - [Getter](getters.md)
+  - [Mutation](mutations.md)
+  - [Action](actions.md)
+  - [Module](modules.md)
+
+深入理解所有的概念对于使用 Vuex 来说是必要的。
+
+让我们开始吧。
+
+# State
+
+### 单一状态树
+
+Vuex 使用**单一状态树**——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 ([SSOT](https://en.wikipedia.org/wiki/Single_source_of_truth))”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
+
+单状态树和模块化并不冲突——在后面的章节里我们会讨论如何将状态和状态变更事件分布到各个子模块中。
+
+### 在 Vue 组件中获得 Vuex 状态
+
+那么我们如何在 Vue 组件中展示状态呢?由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在[计算属性](https://cn.vuejs.org/guide/computed.html)中返回某个状态:
+
+``` js
+// 创建一个 Counter 组件
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return store.state.count
+    }
+  }
+}
+```
+
+每当 `store.state.count` 变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
+
+然而,这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入,并且在测试组件时需要模拟状态。
+
+Vuex 通过 `store` 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 `Vue.use(Vuex)`):
+
+``` js
+const app = new Vue({
+  el: '#app',
+  // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
+  store,
+  components: { Counter },
+  template: `
+    <div class="app">
+      <counter></counter>
+    </div>
+  `
+})
+```
+
+通过在根实例中注册 `store` 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 `this.$store` 访问到。让我们更新下 `Counter` 的实现:
+
+``` js
+const Counter = {
+  template: `<div>{{ count }}</div>`,
+  computed: {
+    count () {
+      return this.$store.state.count
+    }
+  }
+}
+```
+
+### `mapState` 辅助函数
+
+当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 `mapState` 辅助函数帮助我们生成计算属性,让你少按几次键:
+
+``` js
+// 在单独构建的版本中辅助函数为 Vuex.mapState
+import { mapState } from 'vuex'
+
+export default {
+  // ...
+  computed: mapState({
+    // 箭头函数可使代码更简练
+    count: state => state.count,
+
+    // 传字符串参数 'count' 等同于 `state => state.count`
+    countAlias: 'count',
+
+    // 为了能够使用 `this` 获取局部状态,必须使用常规函数
+    countPlusLocalState (state) {
+      return state.count + this.localCount
+    }
+  })
+}
+```
+
+当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 `mapState` 传一个字符串数组。
+
+``` js
+computed: mapState([
+  // 映射 this.count 为 store.state.count
+  'count'
+])
+```
+
+### 对象展开运算符
+
+`mapState` 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 `computed` 属性。但是自从有了[对象展开运算符](https://github.com/sebmarkbage/ecmascript-rest-spread)(现处于 ECMASCript 提案 stage-3 阶段),我们可以极大地简化写法:
+
+``` js
+computed: {
+  localComputed () { /* ... */ },
+  // 使用对象展开运算符将此对象混入到外部对象中
+  ...mapState({
+    // ...
+  })
+}
+```
+
+### 组件仍然保有局部状态
+
+使用 Vuex 并不意味着你需要将**所有的**状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。
+
+# Getter
+
+有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.state.todos.filter(todo => todo.done).length
+  }
+}
+```
+
+如果有多个组件需要用到此属性,我们要么复制这个函数,或者抽取到一个共享函数然后在多处导入它——无论哪种方式都不是很理想。
+
+Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
+
+Getter 接受 state 作为其第一个参数:
+
+``` js
+const store = new Vuex.Store({
+  state: {
+    todos: [
+      { id: 1, text: '...', done: true },
+      { id: 2, text: '...', done: false }
+    ]
+  },
+  getters: {
+    doneTodos: state => {
+      return state.todos.filter(todo => todo.done)
+    }
+  }
+})
+```
+
+Getter 会暴露为 `store.getters` 对象:
+
+``` js
+store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
+```
+
+Getter 也可以接受其他 getter 作为第二个参数:
+
+``` js
+getters: {
+  // ...
+  doneTodosCount: (state, getters) => {
+    return getters.doneTodos.length
+  }
+}
+```
+
+``` js
+store.getters.doneTodosCount // -> 1
+```
+
+我们可以很容易地在任何组件中使用它:
+
+``` js
+computed: {
+  doneTodosCount () {
+    return this.$store.getters.doneTodosCount
+  }
+}
+```
+
+你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。
+
+```js
+getters: {
+  // ...
+  getTodoById: (state) => (id) => {
+    return state.todos.find(todo => todo.id === id)
+  }
+}
+```
+
+``` js
+store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
+```
+
+### `mapGetters` 辅助函数
+
+`mapGetters` 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
+
+``` js
+import { mapGetters } from 'vuex'
+
+export default {
+  // ...
+  computed: {
+  // 使用对象展开运算符将 getter 混入 computed 对象中
+    ...mapGetters([
+      'doneTodosCount',
+      'anotherGetter',
+      // ...
+    ])
+  }
+}
+```
+
+如果你想将一个 getter 属性另取一个名字,使用对象形式:
+
+``` js
+mapGetters({
+  // 映射 `this.doneCount` 为 `store.getters.doneTodosCount`
+  doneCount: 'doneTodosCount'
+})
+```

+ 222 - 0
doc/vue入门文档.md

@@ -0,0 +1,222 @@
+VUEJS
+
+### 结构介绍,生命周期,动态赋值,列表渲染
+```html
+<div id="app">
+    <button @click="add">按钮</button>
+    <button @click="change">改变</button>
+   <ol id="list">
+        <li v-for="item in arr">{{item.text}}</li>
+   </ol>
+   <p>{{msg}}</p>
+   <p>{{arr}}</p>
+   <p>{{json}}</p>
+</div>    
+```
+```vue
+new Vue({
+    el:"#app",
+    data:{
+        msg:"Hello",
+        arr:[{
+            text:"大前端"
+        },{
+            text:"Java"
+        },{
+            text:"安卓"
+        }],
+        json:{a:"appple",b:"banana"}
+    },
+    created:function(){
+            setTimeout(() => {
+                console.log("延迟下");
+                this.msg = "Hello";
+            },2000);
+            console.log(document.getElementById("app").innerHTML);
+            console.log("created");
+    },
+    methods:{
+        add:function(){
+            // 原生写法
+            // document.getElementById("list").innerHTML += "<li>1</li>"
+            this.arr.push({text: Math.random()});
+            this.change();
+        },
+        change:function(){
+            this.arr[1].text = "前端部门";
+        }
+    },
+    watch:{
+            a:function(val, oldVal){
+                console.log('new: ',val,' old:', oldVal)
+            }
+    },
+    beforeCreate:function(){
+        debugger
+        console.log("before");
+    },
+    mounted:function(){
+        console.log("计算属性");
+    }
+});
+```
+ - el: 跟节点
+ - data: vue会对这个data里面所有初始化的对象进行监听,当发生变化 vue会自动渲染所有应用到的模板
+ - created: 实例创建完成后被立即调用,注意和渲染是两回事
+ - methods:定义组件手动触发方法
+ - watch: 监听数据,当数据有变化的时候触发
+ - beforeCreate: 创建之前调用
+ - mounted: 计算属性
+ - @click | v-bind:click: 为节点绑定事件
+ - `<li v-for="item in arr">{{item.text}}</li>`: for循环li标签,arr为数据源,item为列表里等每一项
+ 
+### 输入事件
+ ```html
+    <div id="app">
+        <div><input type="text" @keydown="show()"/></div>
+        <div><input type="text" @keydown="showCode($event)"/></div>
+        <div><input type="text" @keydown.13="showEnter()"/></div>
+        <div><input type="text" @keydown.enter="showEnter()"/></div>
+    </div>
+```
+```vue
+        new Vue({
+            el: "#app",
+            data: {
+
+            },
+            methods: {
+                show: function () {
+                   console.log("哈哈");
+                },
+                showCode:function(ev){
+                    if(ev.keyCode==13){
+                        console.log("您按回车了");
+                    }
+                    console.log(ev.keyCode);
+                    
+                },
+                showEnter:function(){
+                    alert("您按回车了");
+                }
+            }
+        });
+```
+- @keydown: 为节点绑定键盘按下事件,@keydown.13和@keydown.enter 是evnet.watch===13的简写。相同的@keydown.left==='按下鼠标左键',@keydown.right==='按下鼠标右键'
+- @dblclick: 双击
+- @contextmenu: 右键
+- @keydown:按下事件
+    - ev.preventDefault() 取消默认行为
+    - ev.preventDefault = true
+    - ev.prevent:取消默认行为
+    - ev.stop:取消事件冒泡
+    - ev.cancelBubble=true
+
+### 动态控制style写法
+```html
+<div id="app">
+   <p :title="msg" :style="{color:'red'}">文字。。。。。。</p>
+   <p :title="msg" :style="[obj,bg]">文字。。。。。。</p>
+   <p :title="msg" :style="more">文字。。。。。。</p>
+</div>   
+```
+```vue
+new Vue({
+    el:"#app",
+    data:{
+        msg:"信息",
+        obj:{color:'red'},
+        bg:{background:"blue"},
+        more:{
+            color:"red",
+            background:"gray"
+        }
+    }
+});
+```
+- style: 可接收对象,数组写法。注意千万别省略了style前面的`:`号
+
+###自定义指令
+```vue
+    <div id="app">
+        <strong v-red>红色文字</strong>
+        <strong v-red>红色文字2</strong>
+        <strong v-red>红色文字3</strong>
+        <input v-focus>
+    </div>
+```
+```vue
+        Vue.directive("red", function (el, tags) {
+            el.style.color = "red";
+            el.style.background = "green";
+        });
+        Vue.directive('focus', {
+          inserted: function (el) {
+            el.focus()
+          }
+        })
+```
+- directive:注册指令入口。本例展示了全局注册指令的方式,只要节点绑定了对应的指令,就会执行指令的方法
+
+```vue
+    new Vue({
+        el: "#app",
+        data: {},
+        directives: {
+            focus: {
+                inserted: function (el,binding,vnode,oldVnode) {
+                  el.focus();
+                }
+            }
+        }
+    });
+```
+- directive:注册指令入口。本例属于局部注册,只能在当前实例当中注册
+    - focus:指令名称
+        - inserted:指令方法
+
+###组件
+```vue
+<div id="app">
+    <p>父级:{{str}}</p>
+    <child-com :msg="str"></child-com>
+    <child-com :msg="number"></child-com>
+</div>
+<template id="child">
+    <div>
+        <p>我是子组件对象</p>
+        <input type="button" value="按钮" @click="change()"/>
+        <strong>{{msg}}</strong>
+    </div>
+</template>
+```
+```vue
+new Vue({
+    el:"#app",
+    data:{
+        str:"我是父组件对象"
+    },
+    components:{
+        "child-com":{
+            template:"#child",
+            props:['msg'],
+            methods:{
+                change(){
+                    this.msg = "子对象里面的内容被改变了"
+                }
+            }
+        }
+    }
+})
+```
+- 将公共需要复用的模块抽离出来,作为一个公共模块,供各个组件/对象调用
+- components: 定义子组件。
+    - template:子组件模板
+    - props:父组件传入的值,
+    - methods: 子组件执行的方法
+
+
+
+
+
+

+ 1196 - 0
doc/vue官方文档.md

@@ -0,0 +1,1196 @@
+实例生命周期钩子
+- created 钩子可以用来在一个实例被创建之后执行代码
+
+
+
+## Vue.js 是什么
+
+Vue (读音 /vjuː/,类似于 **view**) 是一套用于构建用户界面的**渐进式框架**。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与[现代化的工具链](single-file-components.html)以及各种[支持类库](https://github.com/vuejs/awesome-vue#libraries--plugins)结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
+
+如果你想在深入学习 Vue 之前对它有更多了解,我们<a id="modal-player"  href="javascript:;">制作了一个视频</a>,带您了解其核心概念和一个示例工程。
+
+如果你已经是有经验的前端开发者,想知道 Vue 与其它库/框架有哪些区别,请查看[对比其它框架](comparison.html)。
+
+## 起步
+
+<p class="tip">官方指南假设你已了解关于 HTML、CSS 和 JavaScript 的中级知识。如果你刚开始学习前端开发,将框架作为你的第一步可能不是最好的主意——掌握好基础知识再来吧!之前有其它框架的使用经验会有帮助,但这不是必需的。</p>
+
+尝试 Vue.js 最简单的方法是使用 [JSFiddle 上的 Hello World 例子](https://jsfiddle.net/chrisvfritz/50wL7mdz/)。你可以在浏览器新标签页中打开它,跟着例子学习一些基础用法。或者你也可以<a href="https://gist.githubusercontent.com/chrisvfritz/7f8d7d63000b48493c336e48b3db3e52/raw/ed60c4e5d5c6fec48b0921edaed0cb60be30e87c/index.html" target="_blank" download="index.html">创建一个 <code>.html</code> 文件<a/>,然后通过如下方式引入 Vue:
+
+``` html
+<script src="https://cdn.jsdelivr.net/npm/vue"></script>
+```
+
+[安装教程](/guide/installation.html)给出了更多安装 Vue 的方式。请注意我们**不推荐**新手直接使用 `vue-cli`,尤其是在你还不熟悉基于 Node.js 的构建工具时。
+
+## 声明式渲染
+
+Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
+
+``` html
+<div id="app">
+  {{ message }}
+</div>
+```
+``` js
+var app = new Vue({
+  el: '#app',
+  data: {
+    message: 'Hello Vue!'
+  }
+})
+```
+{% raw %}
+<div id="app" class="demo">
+  {{ message }}
+</div>
+<script>
+var app = new Vue({
+  el: '#app',
+  data: {
+    message: 'Hello Vue!'
+  }
+})
+</script>
+{% endraw %}
+
+我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是**响应式的**。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 `app.message` 的值,你将看到上例相应地更新。
+
+除了文本插值,我们还可以像这样来绑定元素特性:
+
+``` html
+<div id="app-2">
+  <span v-bind:title="message">
+    鼠标悬停几秒钟查看此处动态绑定的提示信息!
+  </span>
+</div>
+```
+``` js
+var app2 = new Vue({
+  el: '#app-2',
+  data: {
+    message: '页面加载于 ' + new Date().toLocaleString()
+  }
+})
+```
+{% raw %}
+<div id="app-2" class="demo">
+  <span v-bind:title="message">
+    鼠标悬停几秒钟查看此处动态绑定的提示信息!
+  </span>
+</div>
+<script>
+var app2 = new Vue({
+  el: '#app-2',
+  data: {
+    message: '页面加载于 ' + new Date().toLocaleString()
+  }
+})
+</script>
+{% endraw %}
+
+这里我们遇到了一点新东西。你看到的 `v-bind` 特性被称为**指令**。指令带有前缀 `v-`,以表示它们是 Vue 提供的特殊特性。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 `title` 特性和 Vue 实例的 `message` 属性保持一致”。
+
+如果你再次打开浏览器的 JavaScript 控制台,输入 `app2.message = '新消息'`,就会再一次看到这个绑定了 `title` 特性的 HTML 已经进行了更新。
+
+## 条件与循环
+
+控制切换一个元素是否显示也相当简单:
+
+``` html
+<div id="app-3">
+  <p v-if="seen">现在你看到我了</p>
+</div>
+```
+``` js
+var app3 = new Vue({
+  el: '#app-3',
+  data: {
+    seen: true
+  }
+})
+```
+{% raw %}
+<div id="app-3" class="demo">
+  <span v-if="seen">现在你看到我了</span>
+</div>
+<script>
+var app3 = new Vue({
+  el: '#app-3',
+  data: {
+    seen: true
+  }
+})
+</script>
+{% endraw %}
+
+继续在控制台输入 `app3.seen = false`,你会发现之前显示的消息消失了。
+
+这个例子演示了我们不仅可以把数据绑定到 DOM 文本或特性,还可以绑定到 DOM **结构**。此外,Vue 也提供一个强大的过渡效果系统,可以在 Vue 插入/更新/移除元素时自动应用[过渡效果](transitions.html)。
+
+还有其它很多指令,每个都有特殊的功能。例如,`v-for` 指令可以绑定数组的数据来渲染一个项目列表:
+
+``` html
+<div id="app-4">
+  <ol>
+    <li v-for="todo in todos">
+      {{ todo.text }}
+    </li>
+  </ol>
+</div>
+```
+``` js
+var app4 = new Vue({
+  el: '#app-4',
+  data: {
+    todos: [
+      { text: '学习 JavaScript' },
+      { text: '学习 Vue' },
+      { text: '整个牛项目' }
+    ]
+  }
+})
+```
+{% raw %}
+<div id="app-4" class="demo">
+  <ol>
+    <li v-for="todo in todos">
+      {{ todo.text }}
+    </li>
+  </ol>
+</div>
+<script>
+var app4 = new Vue({
+  el: '#app-4',
+  data: {
+    todos: [
+      { text: '学习 JavaScript' },
+      { text: '学习 Vue' },
+      { text: '整个牛项目' }
+    ]
+  }
+})
+</script>
+{% endraw %}
+
+在控制台里,输入 `app4.todos.push({ text: '新项目' })`,你会发现列表最后添加了一个新项目。
+
+## 处理用户输入
+
+为了让用户和你的应用进行交互,我们可以用 `v-on` 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
+
+``` html
+<div id="app-5">
+  <p>{{ message }}</p>
+  <button v-on:click="reverseMessage">逆转消息</button>
+</div>
+```
+``` js
+var app5 = new Vue({
+  el: '#app-5',
+  data: {
+    message: 'Hello Vue.js!'
+  },
+  methods: {
+    reverseMessage: function () {
+      this.message = this.message.split('').reverse().join('')
+    }
+  }
+})
+```
+{% raw %}
+<div id="app-5" class="demo">
+  <p>{{ message }}</p>
+  <button v-on:click="reverseMessage">逆转消息</button>
+</div>
+<script>
+var app5 = new Vue({
+  el: '#app-5',
+  data: {
+    message: 'Hello Vue.js!'
+  },
+  methods: {
+    reverseMessage: function () {
+      this.message = this.message.split('').reverse().join('')
+    }
+  }
+})
+</script>
+{% endraw %}
+
+注意在 `reverseMessage` 方法中,我们更新了应用的状态,但没有触碰 DOM——所有的 DOM 操作都由 Vue 来处理,你编写的代码只需要关注逻辑层面即可。
+
+Vue 还提供了 `v-model` 指令,它能轻松实现表单输入和应用状态之间的双向绑定。
+
+``` html
+<div id="app-6">
+  <p>{{ message }}</p>
+  <input v-model="message">
+</div>
+```
+``` js
+var app6 = new Vue({
+  el: '#app-6',
+  data: {
+    message: 'Hello Vue!'
+  }
+})
+```
+{% raw %}
+<div id="app-6" class="demo">
+  <p>{{ message }}</p>
+  <input v-model="message">
+</div>
+<script>
+var app6 = new Vue({
+  el: '#app-6',
+  data: {
+    message: 'Hello Vue!'
+  }
+})
+</script>
+{% endraw %}
+
+## 组件化应用构建
+
+组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:
+
+![Component Tree](/images/components.png)
+
+在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例。在 Vue 中注册组件很简单:
+
+``` js
+// 定义名为 todo-item 的新组件
+Vue.component('todo-item', {
+  template: '<li>这是个待办项</li>'
+})
+```
+
+现在你可以用它构建另一个组件模板:
+
+``` html
+<ol>
+  <!-- 创建一个 todo-item 组件的实例 -->
+  <todo-item></todo-item>
+</ol>
+```
+
+但是这样会为每个待办项渲染同样的文本,这看起来并不炫酷。我们应该能从父作用域将数据传到子组件才对。让我们来修改一下组件的定义,使之能够接受一个 [prop](components.html#Props):
+
+``` js
+Vue.component('todo-item', {
+  // todo-item 组件现在接受一个
+  // "prop",类似于一个自定义特性。
+  // 这个 prop 名为 todo。
+  props: ['todo'],
+  template: '<li>{{ todo.text }}</li>'
+})
+```
+
+现在,我们可以使用 `v-bind` 指令将待办项传到循环输出的每个组件中:
+
+``` html
+<div id="app-7">
+  <ol>
+    <!--
+      现在我们为每个 todo-item 提供 todo 对象
+      todo 对象是变量,即其内容可以是动态的。
+      我们也需要为每个组件提供一个“key”,稍后再
+      作详细解释。
+    -->
+    <todo-item
+      v-for="item in groceryList"
+      v-bind:todo="item"
+      v-bind:key="item.id">
+    </todo-item>
+  </ol>
+</div>
+```
+
+``` js
+Vue.component('todo-item', {
+  props: ['todo'],
+  template: '<li>{{ todo.text }}</li>'
+})
+
+var app7 = new Vue({
+  el: '#app-7',
+  data: {
+    groceryList: [
+      { id: 0, text: '蔬菜' },
+      { id: 1, text: '奶酪' },
+      { id: 2, text: '随便其它什么人吃的东西' }
+    ]
+  }
+})
+```
+{% raw %}
+<div id="app-7" class="demo">
+  <ol>
+    <todo-item v-for="item in groceryList" v-bind:todo="item" :key="item.id"></todo-item>
+  </ol>
+</div>
+<script>
+Vue.component('todo-item', {
+  props: ['todo'],
+  template: '<li>{{ todo.text }}</li>'
+})
+var app7 = new Vue({
+  el: '#app-7',
+  data: {
+    groceryList: [
+      { id: 0, text: '蔬菜' },
+      { id: 1, text: '奶酪' },
+      { id: 2, text: '随便其它什么人吃的东西' }
+    ]
+  }
+})
+</script>
+{% endraw %}
+
+尽管这只是一个刻意设计的例子,但是我们已经设法将应用分割成了两个更小的单元。子单元通过 prop 接口与父单元进行了良好的解耦。我们现在可以进一步改进 `<todo-item>` 组件,提供更为复杂的模板和逻辑,而不会影响到父单元。
+
+在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。在[后续教程](components.html)中我们将详述组件,不过这里有一个 (假想的) 例子,以展示使用了组件的应用模板是什么样的:
+
+``` html
+<div id="app">
+  <app-nav></app-nav>
+  <app-view>
+    <app-sidebar></app-sidebar>
+    <app-content></app-content>
+  </app-view>
+</div>
+```
+
+### 与自定义元素的关系
+
+你可能已经注意到 Vue 组件非常类似于**自定义元素**——它是 [Web 组件规范](https://www.w3.org/wiki/WebComponents/)的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 [Slot API](https://github.com/w3c/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md) 与 `is` 特性。但是,还是有几个关键差别:
+
+1. Web 组件规范仍然处于草案阶段,并且未被所有浏览器原生实现。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。
+
+2. Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。
+
+## 准备好了吗?
+
+我们刚才简单介绍了 Vue 核心最基本的功能——本教程的其余部分将涵盖这些功能以及其它高级功能更详细的细节,所以请务必读完整个教程!
+
+<div id="video-modal" class="modal"><div class="video-space" style="padding: 56.25% 0 0 0; position: relative;"></div></div>
+
+
+## 创建一个 Vue 实例
+
+每个 Vue 应用都是通过用 `Vue` 函数创建一个新的 **Vue 实例**开始的:
+
+```js
+var vm = new Vue({
+  // 选项
+})
+```
+
+虽然没有完全遵循 [MVVM 模型](https://zh.wikipedia.org/wiki/MVVM),但是 Vue 的设计也受到了它的启发。因此在文档中经常会使用 `vm` (ViewModel 的缩写) 这个变量名表示 Vue 实例。
+
+当创建一个 Vue 实例时,你可以传入一个**选项对象**。这篇教程主要描述的就是如何使用这些选项来创建你想要的行为。作为参考,你也可以在 [API 文档](../api/#选项-数据) 中浏览完整的选项列表。
+
+一个 Vue 应用由一个通过 `new Vue` 创建的**根 Vue 实例**,以及可选的嵌套的、可复用的组件树组成。举个例子,一个 todo 应用的组件树可以是这样的:
+
+```
+根实例
+└─ TodoList
+   ├─ TodoItem
+   │  ├─ DeleteTodoButton
+   │  └─ EditTodoButton
+   └─ TodoListFooter
+      ├─ ClearTodosButton
+      └─ TodoListStatistics
+```
+
+我们会在稍后的[组件系统](components.html)章节具体展开。不过现在,你只需要明白所有的 Vue 组件都是 Vue 实例,并且接受相同的选项对象 (一些根实例特有的选项除外)。
+
+## 数据与方法
+
+当一个 Vue 实例被创建时,它向 Vue 的**响应式系统**中加入了其 `data` 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
+
+```js
+// 我们的数据对象
+var data = { a: 1 }
+
+// 该对象被加入到一个 Vue 实例中
+var vm = new Vue({
+  data: data
+})
+
+// 它们引用相同的对象!
+vm.a === data.a // => true
+
+// 设置属性也会影响到原始数据
+vm.a = 2
+data.a // => 2
+
+// ……反之亦然
+data.a = 3
+vm.a // => 3
+```
+
+当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时 `data` 中存在的属性才是**响应式**的。也就是说如果你添加一个新的属性,比如:
+
+```js
+vm.b = 'hi'
+```
+
+那么对 `b` 的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。比如:
+
+```js
+data: {
+  newTodoText: '',
+  visitCount: 0,
+  hideCompletedTodos: false,
+  todos: [],
+  error: null
+}
+```
+
+这里唯一的例外是使用 `Object.freeze()`,这会阻止修改现有的属性,也意味着响应系统无法再_追踪_变化。
+
+```js
+var obj = {
+  foo: 'bar'
+}
+
+Object.freeze(obj)
+
+new Vue({
+  el: '#app',
+  data () {
+    return {
+      obj
+    }
+  }
+})
+```
+
+```html
+<div id="app">
+  <p>{{ obj.foo }}</p>
+  <!-- 这里的 `obj.foo` 不会更新! -->
+  <button @click="obj.foo = 'baz'">Change it</button>
+</div>
+```
+
+除了数据属性,Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 `$`,以便与用户定义的属性区分开来。例如:
+
+```js
+var data = { a: 1 }
+var vm = new Vue({
+  el: '#example',
+  data: data
+})
+
+vm.$data === data // => true
+vm.$el === document.getElementById('example') // => true
+
+// $watch 是一个实例方法
+vm.$watch('a', function (newValue, oldValue) {
+  // 这个回调将在 `vm.a` 改变后调用
+})
+```
+
+以后你可以在 [API 参考](../api/#实例属性)中查阅到完整的实例属性和方法的列表。
+
+## 实例生命周期钩子
+
+每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做**生命周期钩子**的函数,这给了用户在不同阶段添加自己的代码的机会。
+
+比如 [`created`](../api/#created) 钩子可以用来在一个实例被创建之后执行代码:
+
+```js
+new Vue({
+  data: {
+    a: 1
+  },
+  created: function () {
+    // `this` 指向 vm 实例
+    console.log('a is: ' + this.a)
+  }
+})
+// => "a is: 1"
+```
+
+也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 [`mounted`](../api/#mounted)、[`updated`](../api/#updated) 和 [`destroyed`](../api/#destroyed)。生命周期钩子的 `this` 上下文指向调用它的 Vue 实例。
+
+<p class="tip">不要在选项属性或回调上使用[箭头函数](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions),比如 `created: () => console.log(this.a)` 或 `vm.$watch('a', newValue => this.myMethod())`。因为箭头函数是和父级上下文绑定在一起的,`this` 不会是如你所预期的 Vue 实例,经常导致 `Uncaught TypeError: Cannot read property of undefined` 或 `Uncaught TypeError: this.myMethod is not a function` 之类的错误。</p>
+
+## 生命周期图示
+
+下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
+
+![Vue 实例生命周期](/images/lifecycle.png)
+
+
+
+Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
+
+在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。
+
+如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,[直接写渲染 (render) 函数](render-function.html),使用可选的 JSX 语法。
+
+## 插值
+
+### 文本
+
+数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
+
+``` html
+<span>Message: {{ msg }}</span>
+```
+
+Mustache 标签将会被替代为对应数据对象上 `msg` 属性的值。无论何时,绑定的数据对象上 `msg` 属性发生了改变,插值处的内容都会更新。
+
+通过使用 [v-once 指令](../api/#v-once),你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
+
+``` html
+<span v-once>这个将不会改变: {{ msg }}</span>
+```
+
+### 原始 HTML
+
+双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 `v-html` 指令:
+
+``` html
+<p>Using mustaches: {{ rawHtml }}</p>
+<p>Using v-html directive: <span v-html="rawHtml"></span></p>
+```
+
+{% raw %}
+<div id="example1" class="demo">
+  <p>Using mustaches: {{ rawHtml }}</p>
+  <p>Using v-html directive: <span v-html="rawHtml"></span></p>
+</div>
+<script>
+new Vue({
+  el: '#example1',
+  data: function () {
+   return {
+     rawHtml: '<span style="color: red">This should be red.</span>'
+   }
+  }
+})
+</script>
+{% endraw %}
+
+这个 `span` 的内容将会被替换成为属性值 `rawHtml`,直接作为 HTML——会忽略解析属性值中的数据绑定。注意,你不能使用 `v-html` 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。
+
+<p class="tip">你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 [XSS 攻击](https://en.wikipedia.org/wiki/Cross-site_scripting)。请只对可信内容使用 HTML 插值,**绝不要**对用户提供的内容使用插值。</p>
+
+### 特性
+
+Mustache 语法不能作用在 HTML 特性上,遇到这种情况应该使用 [v-bind 指令](../api/#v-bind):
+
+``` html
+<div v-bind:id="dynamicId"></div>
+```
+
+在布尔特性的情况下,它们的存在即暗示为 `true`,`v-bind` 工作起来略有不同,在这个例子中:
+
+``` html
+<button v-bind:disabled="isButtonDisabled">Button</button>
+```
+
+如果 `isButtonDisabled` 的值是 `null`、`undefined` 或 `false`,则 `disabled` 特性甚至不会被包含在渲染出来的 `<button>` 元素中。
+
+### 使用 JavaScript 表达式
+
+迄今为止,在我们的模板中,我们一直都只绑定简单的属性键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
+
+``` html
+{{ number + 1 }}
+
+{{ ok ? 'YES' : 'NO' }}
+
+{{ message.split('').reverse().join('') }}
+
+<div v-bind:id="'list-' + id"></div>
+```
+
+这些表达式会在所属 Vue 实例的数据作用域下作为 JavaScript 被解析。有个限制就是,每个绑定都只能包含**单个表达式**,所以下面的例子都**不会**生效。
+
+``` html
+<!-- 这是语句,不是表达式 -->
+{{ var a = 1 }}
+
+<!-- 流控制也不会生效,请使用三元表达式 -->
+{{ if (ok) { return message } }}
+```
+
+<p class="tip">模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 `Math` 和 `Date` 。你不应该在模板表达式中试图访问用户定义的全局变量。</p>
+
+## 指令
+
+指令 (Directives) 是带有 `v-` 前缀的特殊属性。指令属性的值预期是**单个 JavaScript 表达式** (`v-for` 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。回顾我们在介绍中看到的例子:
+
+``` html
+<p v-if="seen">现在你看到我了</p>
+```
+
+这里,`v-if` 指令将根据表达式 `seen` 的值的真假来插入/移除 `<p>` 元素。
+
+### 参数
+
+一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,`v-bind` 指令可以用于响应式地更新 HTML 属性:
+
+``` html
+<a v-bind:href="url">...</a>
+```
+
+在这里 `href` 是参数,告知 `v-bind` 指令将该元素的 `href` 属性与表达式 `url` 的值绑定。
+
+另一个例子是 `v-on` 指令,它用于监听 DOM 事件:
+
+``` html
+<a v-on:click="doSomething">...</a>
+```
+
+在这里参数是监听的事件名。我们也会更详细地讨论事件处理。
+
+### 修饰符
+
+修饰符 (Modifiers) 是以半角句号 `.` 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,`.prevent` 修饰符告诉 `v-on` 指令对于触发的事件调用 `event.preventDefault()`:
+
+``` html
+<form v-on:submit.prevent="onSubmit">...</form>
+```
+
+在接下来对 [`v-on`](events.html#事件修饰符) 和 [`v-for`](forms.html#修饰符) 等功能的探索中,你会看到修饰符的其它例子。
+
+## 缩写
+
+`v-` 前缀作为一种视觉提示,用来识别模板中 Vue 特定的特性。当你在使用 Vue.js 为现有标签添加动态行为 (dynamic behavior) 时,`v-` 前缀很有帮助,然而,对于一些频繁用到的指令来说,就会感到使用繁琐。同时,在构建由 Vue.js 管理所有模板的[单页面应用程序 (SPA - single page application)](https://en.wikipedia.org/wiki/Single-page_application) 时,`v-` 前缀也变得没那么重要了。因此,Vue.js 为 `v-bind` 和 `v-on` 这两个最常用的指令,提供了特定简写:
+
+### `v-bind` 缩写
+
+``` html
+<!-- 完整语法 -->
+<a v-bind:href="url">...</a>
+
+<!-- 缩写 -->
+<a :href="url">...</a>
+```
+
+### `v-on` 缩写
+
+``` html
+<!-- 完整语法 -->
+<a v-on:click="doSomething">...</a>
+
+<!-- 缩写 -->
+<a @click="doSomething">...</a>
+```
+
+它们看起来可能与普通的 HTML 略有不同,但 `:` 与 `@` 对于特性名来说都是合法字符,在所有支持 Vue.js 的浏览器都能被正确地解析。而且,它们不会出现在最终渲染的标记中。缩写语法是完全可选的,但随着你更深入地了解它们的作用,你会庆幸拥有它们。
+
+## 计算属性
+
+模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
+
+```html
+<div id="example">
+  {{ message.split('').reverse().join('') }}
+</div>
+```
+
+在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 `message` 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。
+
+所以,对于任何复杂逻辑,你都应当使用**计算属性**。
+
+### 基础例子
+
+``` html
+<div id="example">
+  <p>Original message: "{{ message }}"</p>
+  <p>Computed reversed message: "{{ reversedMessage }}"</p>
+</div>
+```
+
+``` js
+var vm = new Vue({
+  el: '#example',
+  data: {
+    message: 'Hello'
+  },
+  computed: {
+    // 计算属性的 getter
+    reversedMessage: function () {
+      // `this` 指向 vm 实例
+      return this.message.split('').reverse().join('')
+    }
+  }
+})
+```
+
+结果:
+
+{% raw %}
+<div id="example">
+  <p>Original message: "{{ message }}"</p>
+  <p>Computed reversed message: "{{ reversedMessage }}"</p>
+</div>
+<script>
+var vm = new Vue({
+  el: '#example',
+  data: {
+    message: 'Hello'
+  },
+  computed: {
+    reversedMessage: function () {
+      return this.message.split('').reverse().join('')
+    }
+  }
+})
+</script>
+{% endraw %}
+
+这里我们声明了一个计算属性 `reversedMessage`。我们提供的函数将用作属性 `vm.reversedMessage` 的 getter 函数:
+
+``` js
+console.log(vm.reversedMessage) // => 'olleH'
+vm.message = 'Goodbye'
+console.log(vm.reversedMessage) // => 'eybdooG'
+```
+
+你可以打开浏览器的控制台,自行修改例子中的 vm。`vm.reversedMessage` 的值始终取决于 `vm.message` 的值。
+
+你可以像绑定普通属性一样在模板中绑定计算属性。Vue 知道 `vm.reversedMessage` 依赖于 `vm.message`,因此当 `vm.message` 发生改变时,所有依赖 `vm.reversedMessage` 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。
+
+### 计算属性缓存 vs 方法
+
+你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:
+
+``` html
+<p>Reversed message: "{{ reversedMessage() }}"</p>
+```
+
+``` js
+// 在组件中
+methods: {
+  reversedMessage: function () {
+    return this.message.split('').reverse().join('')
+  }
+}
+```
+
+我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是**计算属性是基于它们的依赖进行缓存的**。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 `message` 还没有发生改变,多次访问 `reversedMessage` 计算属性会立即返回之前的计算结果,而不必再次执行函数。
+
+这也同样意味着下面的计算属性将不再更新,因为 `Date.now()` 不是响应式依赖:
+
+``` js
+computed: {
+  now: function () {
+    return Date.now()
+  }
+}
+```
+
+相比之下,每当触发重新渲染时,调用方法将**总会**再次执行函数。
+
+我们为什么需要缓存?假设我们有一个性能开销比较大的的计算属性 **A**,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 **A** 。如果没有缓存,我们将不可避免的多次执行 **A** 的 getter!如果你不希望有缓存,请用方法来替代。
+
+### 计算属性 vs 侦听属性
+
+Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:**侦听属性**。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 `watch`——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 `watch` 回调。细想一下这个例子:
+
+``` html
+<div id="demo">{{ fullName }}</div>
+```
+
+``` js
+var vm = new Vue({
+  el: '#demo',
+  data: {
+    firstName: 'Foo',
+    lastName: 'Bar',
+    fullName: 'Foo Bar'
+  },
+  watch: {
+    firstName: function (val) {
+      this.fullName = val + ' ' + this.lastName
+    },
+    lastName: function (val) {
+      this.fullName = this.firstName + ' ' + val
+    }
+  }
+})
+```
+
+上面代码是命令式且重复的。将它与计算属性的版本进行比较:
+
+``` js
+var vm = new Vue({
+  el: '#demo',
+  data: {
+    firstName: 'Foo',
+    lastName: 'Bar'
+  },
+  computed: {
+    fullName: function () {
+      return this.firstName + ' ' + this.lastName
+    }
+  }
+})
+```
+
+好得多了,不是吗?
+
+### 计算属性的 setter
+
+计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
+
+``` js
+// ...
+computed: {
+  fullName: {
+    // getter
+    get: function () {
+      return this.firstName + ' ' + this.lastName
+    },
+    // setter
+    set: function (newValue) {
+      var names = newValue.split(' ')
+      this.firstName = names[0]
+      this.lastName = names[names.length - 1]
+    }
+  }
+}
+// ...
+```
+
+现在再运行 `vm.fullName = 'John Doe'` 时,setter 会被调用,`vm.firstName` 和 `vm.lastName` 也会相应地被更新。
+
+## 侦听器
+
+虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 `watch` 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
+
+例如:
+
+```html
+<div id="watch-example">
+  <p>
+    Ask a yes/no question:
+    <input v-model="question">
+  </p>
+  <p>{{ answer }}</p>
+</div>
+```
+
+```html
+<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
+<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
+<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
+<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
+<script>
+var watchExampleVM = new Vue({
+  el: '#watch-example',
+  data: {
+    question: '',
+    answer: 'I cannot give you an answer until you ask a question!'
+  },
+  watch: {
+    // 如果 `question` 发生改变,这个函数就会运行
+    question: function (newQuestion, oldQuestion) {
+      this.answer = 'Waiting for you to stop typing...'
+      this.getAnswer()
+    }
+  },
+  methods: {
+    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
+    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
+    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
+    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
+    // 请参考:https://lodash.com/docs#debounce
+    getAnswer: _.debounce(
+      function () {
+        if (this.question.indexOf('?') === -1) {
+          this.answer = 'Questions usually contain a question mark. ;-)'
+          return
+        }
+        this.answer = 'Thinking...'
+        var vm = this
+        axios.get('https://yesno.wtf/api')
+          .then(function (response) {
+            vm.answer = _.capitalize(response.data.answer)
+          })
+          .catch(function (error) {
+            vm.answer = 'Error! Could not reach the API. ' + error
+          })
+      },
+      // 这是我们为判定用户停止输入等待的毫秒数
+      500
+    )
+  }
+})
+</script>
+```
+
+结果:
+
+{% raw %}
+<div id="watch-example">
+  <p>
+    Ask a yes/no question:
+    <input v-model="question">
+  </p>
+  <p>{{ answer }}</p>
+</div>
+<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
+<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
+<script>
+var watchExampleVM = new Vue({
+  el: '#watch-example',
+  data: {
+    question: '',
+    answer: 'I cannot give you an answer until you ask a question!'
+  },
+  watch: {
+    question: function (newQuestion, oldQuestion) {
+      this.answer = 'Waiting for you to stop typing...'
+      this.getAnswer()
+    }
+  },
+  methods: {
+    getAnswer: _.debounce(
+      function () {
+        var vm = this
+        if (this.question.indexOf('?') === -1) {
+          vm.answer = 'Questions usually contain a question mark. ;-)'
+          return
+        }
+        vm.answer = 'Thinking...'
+        axios.get('https://yesno.wtf/api')
+          .then(function (response) {
+            vm.answer = _.capitalize(response.data.answer)
+          })
+          .catch(function (error) {
+            vm.answer = 'Error! Could not reach the API. ' + error
+          })
+      },
+      500
+    )
+  }
+})
+</script>
+{% endraw %}
+
+在这个示例中,使用 `watch` 选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
+
+除了 `watch` 选项之外,您还可以使用命令式的 [vm.$watch API](../api/#vm-watch)。
+
+
+操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性,所以我们可以用 `v-bind` 处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 `v-bind` 用于 `class` 和 `style` 时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
+
+## 绑定 HTML Class
+
+### 对象语法
+
+我们可以传给 `v-bind:class` 一个对象,以动态地切换 class:
+
+``` html
+<div v-bind:class="{ active: isActive }"></div>
+```
+上面的语法表示 `active` 这个 class 存在与否将取决于数据属性 `isActive` 的 [truthiness](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy)。
+
+你可以在对象中传入更多属性来动态切换多个 class。此外,`v-bind:class` 指令也可以与普通的 class 属性共存。当有如下模板:
+
+``` html
+<div class="static"
+     v-bind:class="{ active: isActive, 'text-danger': hasError }">
+</div>
+```
+
+和如下 data:
+
+``` js
+data: {
+  isActive: true,
+  hasError: false
+}
+```
+
+结果渲染为:
+
+``` html
+<div class="static active"></div>
+```
+
+当 `isActive` 或者 `hasError` 变化时,class 列表将相应地更新。例如,如果 `hasError` 的值为 `true`,class 列表将变为 `"static active text-danger"`。
+
+绑定的数据对象不必内联定义在模板里:
+
+``` html
+<div v-bind:class="classObject"></div>
+```
+
+``` js
+data: {
+  classObject: {
+    active: true,
+    'text-danger': false
+  }
+}
+```
+
+渲染的结果和上面一样。我们也可以在这里绑定一个返回对象的[计算属性](computed.html)。这是一个常用且强大的模式:
+
+``` html
+<div v-bind:class="classObject"></div>
+```
+
+``` js
+data: {
+  isActive: true,
+  error: null
+},
+computed: {
+  classObject: function () {
+    return {
+      active: this.isActive && !this.error,
+      'text-danger': this.error && this.error.type === 'fatal'
+    }
+  }
+}
+```
+
+### 数组语法
+
+我们可以把一个数组传给 `v-bind:class`,以应用一个 class 列表:
+
+``` html
+<div v-bind:class="[activeClass, errorClass]"></div>
+```
+
+``` js
+data: {
+  activeClass: 'active',
+  errorClass: 'text-danger'
+}
+```
+
+渲染为:
+
+``` html
+<div class="active text-danger"></div>
+```
+
+如果你也想根据条件切换列表中的 class,可以用三元表达式:
+
+``` html
+<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
+```
+
+这样写将始终添加 `errorClass`,但是只有在 `isActive` 是 truthy<sup>[[1]](#footnote-1)</sup> 时才添加 `activeClass`。
+
+不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法:
+
+``` html
+<div v-bind:class="[{ active: isActive }, errorClass]"></div>
+```
+
+### 用在组件上
+
+> 这个章节假设你已经对 [Vue 组件](components.html)有一定的了解。当然你也可以先跳过这里,稍后再回过头来看。
+
+当在一个自定义组件上使用 `class` 属性时,这些类将被添加到该组件的根元素上面。这个元素上已经存在的类不会被覆盖。
+
+例如,如果你声明了这个组件:
+
+``` js
+Vue.component('my-component', {
+  template: '<p class="foo bar">Hi</p>'
+})
+```
+
+然后在使用它的时候添加一些 class:
+
+``` html
+<my-component class="baz boo"></my-component>
+```
+
+HTML 将被渲染为:
+
+``` html
+<p class="foo bar baz boo">Hi</p>
+```
+
+对于带数据绑定 class 也同样适用:
+
+``` html
+<my-component v-bind:class="{ active: isActive }"></my-component>
+```
+
+当 `isActive` 为 truthy<sup>[[1]](#footnote-1)</sup> 时,HTML 将被渲染成为:
+
+``` html
+<p class="foo bar active">Hi</p>
+```
+
+## 绑定内联样式
+
+### 对象语法
+
+`v-bind:style` 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用单引号括起来) 来命名:
+
+
+``` html
+<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
+```
+
+``` js
+data: {
+  activeColor: 'red',
+  fontSize: 30
+}
+```
+
+直接绑定到一个样式对象通常更好,这会让模板更清晰:
+
+``` html
+<div v-bind:style="styleObject"></div>
+```
+
+``` js
+data: {
+  styleObject: {
+    color: 'red',
+    fontSize: '13px'
+  }
+}
+```
+
+同样的,对象语法常常结合返回对象的计算属性使用。
+
+### 数组语法
+
+`v-bind:style` 的数组语法可以将多个样式对象应用到同一个元素上:
+
+``` html
+<div v-bind:style="[baseStyles, overridingStyles]"></div>
+```
+
+### 自动添加前缀
+
+当 `v-bind:style` 使用需要添加[浏览器引擎前缀](https://developer.mozilla.org/zh-CN/docs/Glossary/Vendor_Prefix)的 CSS 属性时,如 `transform`,Vue.js 会自动侦测并添加相应的前缀。
+
+### 多重值
+
+> 2.3.0+
+
+从 2.3.0 起你可以为 `style` 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
+
+``` html
+<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
+```
+
+这样写只会渲染数组中最后一个被浏览器支持的值。在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 `display: flex`。
+
+<small>
+__译者注__
+<a id="footnote-1"></a>[1] truthy 不是 `true`,详见 [MDN](https://developer.mozilla.org/zh-CN/docs/Glossary/Truthy) 的解释。
+</small>
+

+ 20 - 0
doc/代码规范.md

@@ -0,0 +1,20 @@
+# vue-client
+
+- 前后端共同遵守
+
+ > 1. 4个空格缩进。
+ > 2. 变量名必修使用constantCase格式(首个单词小写,之后每个单词首字母大写)。
+ > 3. 每个功能完成后,进行白盒测试。
+ > 4. 白盒测试通过后,提交到git库。
+ > 5. 每次提交必须填写描述。
+ > 6. 每次提交前更新代码。
+ > 7. 每天下班前push代码。
+ > 8. css类名以 - 相连。
+ > 9. 全局类名用 _ 相连。
+ > 10. 压缩文档统一采用zip格式。
+
+- 前端遵守
+
+ > 1. 尽可能使用现有组件。
+ > 2. 公共部分必须抽出组件。
+ > 3. 值数据判断要使用三等号"==="。

+ 29 - 0
doc/前端开发规范.md

@@ -0,0 +1,29 @@
+- 前端开发规范
+
+>.  目录结构介绍
+
+    - /assets   静态资源
+      - /assets/icon   图标
+      - /assets/images 图片
+      - /assets/styles 公共样式
+      
+    - /mock     模拟数据(后面会删除)
+    - /packages 模块
+      - /packages/components   公用组件
+      - /packages/ui           公用布局
+    - /router     路由
+      - /router/admin.js  后台管理系统路由表
+      - /router/client.js 前台页面路由表
+    - /store    vuex存储数据
+    - /tools    工具
+    - /view     页面
+      - /view/admin  后台管理页面
+      - /view/client 前台页面
+
+>.  命名
+
+    - 文件命名
+      - 当前业务的 模块ID + 子模块ID + 业务ID, 字母以小写命名,开头不能为数字
+      - 每个文件夹下应有一个index.vue文件, 一个api.js文件。index.vue为当前页面的入口文件,api.js为当前页面所有api接口
+    - class命名
+      单词间以 - 链接,语意清晰

+ 45 - 0
doc/常见错误.md

@@ -0,0 +1,45 @@
+- 常见错误
+>. 一
+
+```
+ 94% asset optimization ERROR  Failed to compile with 7 errors16:55:29
+
+ error  in ./src/assets/styles/index.scss
+
+Module build failed: Error: Missing binding C:\work\oak\vue-client\node_modules\node-sass\vendor\win32-x64-48\binding.node
+Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 6.x
+```
+解决办法
+ - 把doc/node-sass-lib里面的文件放到 node_modules/node-sass/vendor中,如果没有vendor文件,那么需手动创建一个
+
+>. 二
+```vue
+[Vue warn]: Error in event handler for "click": "TypeError: Cannot read property 'Add' of undefined"
+
+found in
+
+---> <ElButton>
+       <CompForm> at src/view/admin/new-vuex/form.test.vue
+         <ElDialog>
+           <ElCard>
+             <NewVuex> at src/view/admin/new-vuex/index.vue
+               <ElMain>
+                 <ElContainer>... (1 recursive calls)
+                   <Container> at src/packages/ui/container.vue
+                     <Router> at src/packages/ui/router.vue
+                       <App> at src/App.vue
+                         <Root>
+```
+解决办法
+ ```vue
+  重要信息 'Add' of undefined
+  请检查你的导包方式是否与应对导出方式相匹配
+  例:一
+      export Demo { xxx ... }
+      使用 import {Demo} from '../xxx'
+      导出的名字要和导入的名字一样
+     二
+     export default Demo { xxx ... }
+     使用 import Demo from '../xxx';  Demo 这个名字可以自由取名,建议与导出之相对应
+```
+

+ 8 - 0
docker-compose.yml

@@ -0,0 +1,8 @@
+version: "3"
+
+services:
+  stage:
+    build:
+      context: ./
+      dockerfile: Dockerfile
+    image: inner.registry.cn-su.net/bazhong/web:stage-${DATE_VERSION}

+ 9 - 0
index.pug

@@ -0,0 +1,9 @@
+doctype
+html(lang="zh-CN")
+  head
+    base(href="/")
+    meta(charset="utf-8")
+    meta(name="viewport", content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0,height=device-height")
+    title #{htmlWebpackPlugin.options.title}
+  body
+    #app

+ 113 - 0
package.json

@@ -0,0 +1,113 @@
+{
+  "name": "vue-client",
+  "version": "0.0.1",
+  "description": "vue-client",
+  "private": true,
+  "scripts": {
+    "start": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
+    "build": "node build/build.js",
+    "clean": "gulp --gulpfile=build/gulpfile.babel.js clean",
+    "unit": "jest --config test/unit/jest.conf.js --coverage",
+    "e2e": "node test/e2e/runner.js",
+    "test": "npm run unit && npm run e2e",
+    "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
+    "precommit": "lint-staged"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://git.singularitychina.com/frame-client/vue-client.git"
+  },
+  "lint-staged": {
+    "src/**/*.{js,vue}": [
+      "eslint --fix",
+      "git add"
+    ]
+  },
+  "author": "modan <1072110269@qq.com>",
+  "license": "UNLICENSED",
+  "dependencies": {
+    "axios": "^0.18.0",
+    "css-element-queries": "^1.2.0",
+    "echarts": "^4.2.0-rc.2",
+    "element-ui": "^2.2.0",
+    "js-cookie": "^2.2.0",
+    "nprogress": "^0.2.0",
+    "qs": "^6.5.1",
+    "request": "^2.83.0",
+    "vue": "^2.5.2",
+    "vue-router": "^3.0.1",
+    "vuex": "^3.0.1"
+  },
+  "devDependencies": {
+    "autoprefixer": "^7.1.2",
+    "babel-core": "^6.22.1",
+    "babel-eslint": "^8.2.1",
+    "babel-helper-vue-jsx-merge-props": "^2.0.3",
+    "babel-jest": "^21.0.2",
+    "babel-loader": "^7.1.1",
+    "babel-plugin-dynamic-import-node": "^1.2.0",
+    "babel-plugin-syntax-jsx": "^6.18.0",
+    "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
+    "babel-plugin-transform-runtime": "^6.22.0",
+    "babel-plugin-transform-vue-jsx": "^3.5.0",
+    "babel-preset-env": "^1.3.2",
+    "babel-preset-stage-2": "^6.22.0",
+    "chalk": "^2.0.1",
+    "copy-webpack-plugin": "^4.0.1",
+    "cross-spawn": "^5.0.1",
+    "css-loader": "^0.28.0",
+    "eslint": "^4.18.1",
+    "eslint-config-standard": "^10.2.1",
+    "eslint-friendly-formatter": "^3.0.0",
+    "eslint-loader": "^1.7.1",
+    "eslint-plugin-import": "^2.7.0",
+    "eslint-plugin-node": "^5.2.0",
+    "eslint-plugin-promise": "^3.4.0",
+    "eslint-plugin-standard": "^3.0.1",
+    "eslint-plugin-vue": "^4.0.0",
+    "extract-text-webpack-plugin": "^3.0.0",
+    "file-loader": "^1.1.4",
+    "friendly-errors-webpack-plugin": "^1.6.1",
+    "gulp": "^3.9.1",
+    "html-webpack-plugin": "^2.30.1",
+    "jest": "^22.0.4",
+    "jest-serializer-vue": "^0.3.0",
+    "lint-staged": "^6.1.0",
+    "nightwatch": "^0.9.12",
+    "node-notifier": "^5.1.2",
+    "node-sass": "^4.7.2",
+    "optimize-css-assets-webpack-plugin": "^3.2.0",
+    "ora": "^1.2.0",
+    "portfinder": "^1.0.13",
+    "postcss-import": "^11.0.0",
+    "postcss-loader": "^2.0.8",
+    "postcss-url": "^7.2.1",
+    "pug": "^2.0.0-rc.2",
+    "pug-loader": "^2.3.0",
+    "rimraf": "^2.6.0",
+    "sass-loader": "^6.0.6",
+    "selenium-server": "^3.0.1",
+    "semver": "^5.3.0",
+    "shelljs": "^0.7.6",
+    "uglifyjs-webpack-plugin": "^1.1.1",
+    "url-loader": "^0.5.8",
+    "vue-jest": "^1.0.2",
+    "vue-loader": "^13.3.0",
+    "vue-style-loader": "^3.0.1",
+    "vue-template-compiler": "^2.5.2",
+    "vue2-editor": "^2.4.2",
+    "webpack": "^3.6.0",
+    "webpack-bundle-analyzer": "^2.11.0",
+    "webpack-dev-server": "^2.11.5",
+    "webpack-merge": "^4.1.0"
+  },
+  "engines": {
+    "node": ">= 6.0.0",
+    "npm": ">= 3.0.0"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not ie <= 8"
+  ]
+}

+ 12 - 0
src/App.vue

@@ -0,0 +1,12 @@
+<template>
+  <div id="app" style="width: 100%;height: 100%;">
+    <router-view style="width: 100%;height: 100%;">
+    </router-view>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'app',
+  }
+</script>

Fichier diff supprimé car celui-ci est trop grand
+ 4 - 0
src/assets/icon/iconfont.css


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
src/assets/icon/iconfont.js


BIN
src/assets/images/1077.png


BIN
src/assets/images/123.png


BIN
src/assets/images/12345-大.png


BIN
src/assets/images/12345-小.png


BIN
src/assets/images/12345.png


BIN
src/assets/images/12345logo.png


BIN
src/assets/images/app.png


BIN
src/assets/images/back.png


BIN
src/assets/images/background.png


BIN
src/assets/images/clipboard.png


BIN
src/assets/images/earth.png


BIN
src/assets/images/earthCircle.png


BIN
src/assets/images/edit.png


BIN
src/assets/images/exitImg.png


BIN
src/assets/images/favicon.ico


BIN
src/assets/images/governmentCenter1.png


BIN
src/assets/images/governmentCenter11.png


BIN
src/assets/images/governmentCenter2.png


BIN
src/assets/images/governmentCenter22.png


BIN
src/assets/images/governmentHead.png


BIN
src/assets/images/governmentLeft1.png


BIN
src/assets/images/governmentLeft11.png


BIN
src/assets/images/governmentLeft2.png


BIN
src/assets/images/governmentLeft22.png


BIN
src/assets/images/governmentRight1.png


BIN
src/assets/images/governmentRight11.png


BIN
src/assets/images/governmentRight2.png


BIN
src/assets/images/governmentRight22.png


BIN
src/assets/images/inter.png


BIN
src/assets/images/left2.png


BIN
src/assets/images/leftB.png


BIN
src/assets/images/leftT.png


BIN
src/assets/images/leftTopBackgroundPicture.png


BIN
src/assets/images/lightPoint.png


BIN
src/assets/images/line.png


BIN
src/assets/images/loginBack.png


BIN
src/assets/images/loginBackground.png


BIN
src/assets/images/logo.png


BIN
src/assets/images/middle2.png


BIN
src/assets/images/middle_center.png


BIN
src/assets/images/peopleLine.png


BIN
src/assets/images/phone.png


BIN
src/assets/images/publicBig.png


BIN
src/assets/images/publicBig1.png


BIN
src/assets/images/publicHead.png


BIN
src/assets/images/publicSmall.png


BIN
src/assets/images/publicSmall1.png


BIN
src/assets/images/rate.png


BIN
src/assets/images/rectangle1.png


BIN
src/assets/images/rectangle2.png


BIN
src/assets/images/rectangle3.png


BIN
src/assets/images/rectangle4.png


BIN
src/assets/images/rectangle5.png


BIN
src/assets/images/rectangle6.png


BIN
src/assets/images/rectangle7.png


BIN
src/assets/images/rectangle8.png


BIN
src/assets/images/right.png


BIN
src/assets/images/right2.png


Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff