Vue CLI 2.x搭建vue(目录最全分析)


Posted in Javascript onFebruary 27, 2019

一、vue-cli介绍

vue-cli是一个用于快速搭建vue项目的 脚手架。

二、vue-cli安装、更新

安装过nodeJs 、cnpm 后,全局安装vue-cli(以后其他项目可直接使用):

cnpm install -g vue-cli

更新:

cnpm update vue-cli

查看安装成功否(有版本号就是成功,V大写)

vue -V

查看npm注册表里vue-cli版本号:

cnpm view vue-cli

三、vue-cli 使用

安装过webpack 、vue-cli后,可以开始搭建vue项目:

vue init webpack <Project Name>

eg:右击Git Base Here(如果你没有用git ,你也可以按住shift键右击选择“在此处打开命令窗口”,或者 cmd :cd \project/lfxProject),如图:

Vue CLI 2.x搭建vue(目录最全分析)or

ps:ESLint(一个javascript代码检测工具)、unit tests(单元测试)、Nightwatch(一个e2e用户界面测试工具)。

四、项目完成

项目结构如下:

Vue CLI 2.x搭建vue(目录最全分析)

各文件作用解析,如下:

1、build文件夹:

build文件夹的结构:

Vue CLI 2.x搭建vue(目录最全分析)

(1)build.js

'use strict'
require('./check-versions')() //调用版本检查

process.env.NODE_ENV = 'production' //将环境配置为生产环境
const ora = require('ora') //npm包 loading插件
const rm = require('rimraf') //npm包 用于删除文件
const path = require('path')//npm包 文件路径工具
const chalk = require('chalk')//npm包 在终端输出带颜色的文字
const webpack = require('webpack')//引入webpack.js
const config = require('../config')//引入配置文件
const webpackConfig = require('./webpack.prod.conf')//引入生产环境配置文件
// 在终端显示loading效果,并输出提示
const spinner = ora('building for production...')
spinner.start()
//先递归删除dist文件再生成新文件,避免冗余
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, 
   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'
  ))
 })
})

ps:require/export是一种nodeJs(commonJs规范)的依赖注入的方法,import/export是ES6语法,用于引入模块,在nodeJs中使用的ES6语法最终会使用babel工具(babel-loader)转化为ES5

(2)check-version.js:检测node和npm的版本,实现版本依赖

'use strict'
const chalk = require('chalk')
const semver = require('semver')//检查版本
const packageConfig = require('../package.json')
const shell = require('shelljs')//shelljs 模块重新包装了 child_process,调用系统命令更加方便

function exec (cmd) {//返回通过child_process模块的新建子进程,执行 Unix 系统命令后转成没有空格的字符串
 return require('child_process').execSync(cmd).toString().trim()
}

const versionRequirements = [
 {
  name: 'node',
  currentVersion: semver.clean(process.version),//使用semver格式化版本
  versionRequirement: packageConfig.engines.node //获取package.json中设置的node版本
 }
]

if (shell.which('npm')) {
 versionRequirements.push({
  name: 'npm',
  currentVersion: exec('npm --version'),// 自动调用npm --version命令,并且把参数返回给exec函数,从而获取纯净的版本号
  versionRequirement: packageConfig.engines.npm
 })
}

module.exports = function () {
 const warnings = []
 for (let i = 0; i < versionRequirements.length; i++) {
  const mod = versionRequirements[i]
  //若版本号不符合package.json文件中指定的版本号,就报错
  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)
 }
}

(3)utils.js:utils是工具的意思,是一个用来处理css的文件,这个文件包含了三个工具函数:

  • 生成静态资源的路径
  • 生成 ExtractTextPlugin对象或loader字符串
  • 生成 style-loader的配置
var path = require('path')// node自带的文件路径工具
var config = require('../config')// 配置文件
var ExtractTextPlugin = require('extract-text-webpack-plugin')// 提取css的插件

/** @method assertsPath 生成静态资源的路径(判断开发环境和生产环境,为config文件中index.js文件中定义assetsSubDirectory)
 * @param {String}  _path 相对于静态资源文件夹的文件路径
 * @return {String}     静态资源完整路径
 */
exports.assetsPath = function (_path) {
 var assetsSubDirectory = process.env.NODE_ENV === 'production'
  ? config.build.assetsSubDirectory
  : config.dev.assetsSubDirectory
 //nodeJs path提供用于处理文件路径的工具;path.posix提供对路径方法的POSIX(可移植性操作系统接口)特定实现的访问(可跨平台); path.posix.join与path.join一样,不过总是以 posix 兼容的方式交互
 return path.posix.join(assetsSubDirectory, _path)
}

/**@method cssLoaders 生成处理css的loaders配置,使用css-loader和postcssLoader,通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法
 * @param {Object} option = {sourceMap: true,// 是否开启 sourceMapextract: true // 是否提取css}生成配置
 * @return {Object} 处理css的loaders配置对象
 */
exports.cssLoaders = function (options) {
 options = options || {}

 var cssLoader = {
  loader: 'css-loader',
  options: {
   minimize: process.env.NODE_ENV === 'production',
   sourceMap: options.sourceMap
  }
 }
 /**@method generateLoaders 生成 ExtractTextPlugin对象或loader字符串
  * @param {Array}    loaders loader名称数组
  * @return {String|Object}    ExtractTextPlugin对象或loader字符串
  */
 function generateLoaders (loader, loaderOptions) {
  var loaders = [cssLoader]
  if (loader) {
   loaders.push({  
    loader: loader + '-loader',
    options: Object.assign({}, loaderOptions, {
     sourceMap: options.sourceMap
    })
   })
  }
  // ExtractTextPlugin提取css(当上面的loaders未能正确引入时,使用vue-style-loader)
  if (options.extract) {// 生产环境中,默认为true
   return ExtractTextPlugin.extract({
    use: loaders,
    fallback: 'vue-style-loader'
   })
  } else {//返回vue-style-loader连接loaders的最终值
   return ['vue-style-loader'].concat(loaders)
  }
 }

 return {
  css: generateLoaders(),//需要css-loader 和 vue-style-loader
  postcss: generateLoaders(),//需要css-loader、postcssLoader 和 vue-style-loader
  less: generateLoaders('less'),//需要less-loader 和 vue-style-loader
  sass: generateLoaders('sass', { indentedSyntax: true }),//需要sass-loader 和 vue-style-loader
  scss: generateLoaders('sass'),//需要sass-loader 和 vue-style-loader
  stylus: generateLoaders('stylus'),//需要stylus-loader 和 vue-style-loader
  styl: generateLoaders('stylus')//需要stylus-loader 和 vue-style-loader
 }
}
 
/**@method styleLoaders 生成 style-loader的配置
 * @param {Object}   options 生成配置
 * @return {Array}   style-loader的配置
 */
exports.styleLoaders = function (options) {
 var output = []
 var loaders = exports.cssLoaders(options)
 //将各种css,less,sass等综合在一起得出结果输出output
 for (var extension in loaders) {
  var loader = loaders[extension]
  output.push({
   test: new RegExp('\\.' + extension + '$'),
   use: loader
  })
 }
 return output
}

(4)vue-loader.conf.js:处理.vue文件,解析这个文件中的每个语言块(template、script、style),转换成js可用的js模块。

'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
//生产环境,提取css样式到单独文件
const sourceMapEnabled = isProduction
 ? config.build.productionSourceMap
 : config.dev.cssSourceMap
module.exports = {
 loaders: utils.cssLoaders({
  sourceMap: sourceMapEnabled,
  extract: isProduction
 }),
 cssSourceMap: sourceMapEnabled,
 cacheBusting: config.dev.cacheBusting,
 //编译时将“引入路径”转换为require调用,使其可由webpack处理
 transformToRequire: {
  video: ['src', 'poster'],
  source: 'src',
  img: 'src',
  image: 'xlink:href'
 }
}

(5)webpack.base.conf.js:开发、测试、生产环境的公共基础配置文件,配置输出环境,配置模块resolve和插件等

'use strict'
const path = require('path')// node自带的文件路径工具
const utils = require('./utils')// 工具函数集合
const config = require('../config')// 配置文件
const vueLoaderConfig = require('./vue-loader.conf')// 工具函数集合
/**
 * 获取"绝对路径"
 * @method resolve
 * @param {String} dir 相对于本文件的路径
 * @return {String}   绝对路径
 */
function resolve(dir) {
 return path.join(__dirname, '..', dir)
}

module.exports = {
 context: path.resolve(__dirname, '../'),
 //入口js文件(默认为单页面所以只有app一个入口)
 entry: {
  app: './src/main.js'
 },
 //配置出口
 output: {
  path: config.build.assetsRoot,//打包编译的根路径(dist)
  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'),// eg:"src/components" => "@/components"
  }
 },
 module: {
  rules: [
   //使用vue-loader将vue文件编译转换为js
   {
    test: /\.vue$/,
    loader: 'vue-loader',
    options: vueLoaderConfig
   },
   //通过babel-loader将ES6编译压缩成ES5
   {
    test: /\.js$/,
    loader: 'babel-loader',
    include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
   },
   //使用url-loader处理(图片、音像、字体),超过10000编译成base64
   {
    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]')
    }
   }
  ]
 },
 //nodeJs全局变量/模块,防止webpack注入一些nodeJs的东西到vue中
 node: {
  setImmediate: false,
  dgram: 'empty',
  fs: 'empty',
  net: 'empty',
  tls: 'empty',
  child_process: 'empty'
 }
}

(6)webpack.dev.conf.js:webpack配置开发环境中的入口

'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')//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')//webpack的提示错误和日志信息的插件
const portfinder = require('portfinder')// 查看空闲端口位置,默认情况下搜索8000这个端口

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 })
 },
 devtool: config.dev.devtool,//调试模式
 devServer: {
  clientLogLevel: 'warning',
  historyApiFallback: {//使用 HTML5 History API 时, 404 响应替代为 index.html
   rewrites: [
    { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
   ],
  },
  hot: true,//热重载
  contentBase: false, // 提供静态文件访问
  compress: true,//压缩
  host: HOST || config.dev.host,
  port: PORT || config.dev.port,
  open: config.dev.autoOpenBrowser,//npm run dev 时自动打开浏览器
  overlay: config.dev.errorOverlay
   ? { warnings: false, errors: true }
   : false,// 显示warning 和 error 信息
  publicPath: config.dev.assetsPublicPath,
  proxy: config.dev.proxyTable,//api代理
  quiet: true, //控制台打印警告和错误(用FriendlyErrorsPlugin 为 true)
  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(),//webpack编译错误的时候,中断打包进程,防止错误代码打包到文件中
  // 将打包编译好的代码插入index.html
  new HtmlWebpackPlugin({
   filename: 'index.html',
   template: 'index.html',
   inject: true
  }),
  // 提取static assets 中css 复制到dist/static文件
  new CopyWebpackPlugin([
   {
    from: path.resolve(__dirname, '../static'),
    to: config.dev.assetsSubDirectory,
    ignore: ['.*']//忽略.*的文件
   }
  ])
 ]
})

module.exports = new Promise((resolve, reject) => {
 portfinder.basePort = process.env.PORT || config.dev.port
 portfinder.getPort((err, port) => { //查找端口号
  if (err) {
   reject(err)
  } else {
   //端口被占用时就重新设置evn和devServer的端口
   process.env.PORT = port
   devWebpackConfig.devServer.port = port
   // npm run dev成功的友情提示
   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)
  }
 })
})

(7)webpack.dev.prod.js:webpack配置生产环境中的入口

'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 = 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].js'),
  chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
 },
 plugins: [
  new webpack.DefinePlugin({
   'process.env': env
  }),
  new UglifyJsPlugin({//压缩js
   uglifyOptions: {
    compress: {
     warnings: false
    }
   },
   sourceMap: config.build.productionSourceMap,
   parallel: true
  }),
  new ExtractTextPlugin({//提取静态文件,减少请求
   filename: utils.assetsPath('css/[name].[contenthash].css'),
   allChunks: true,
  }),
  new OptimizeCSSPlugin({//提取优化压缩后(删除来自不同组件的冗余代码)的css
   cssProcessorOptions: config.build.productionSourceMap
    ? { safe: true, map: { inline: false } }
    : { safe: true }
  }),
  new HtmlWebpackPlugin({ //html打包压缩到index.html
   filename: config.build.index,
   template: 'index.html',
   inject: true,
   minify: {
    removeComments: true,//删除注释
    collapseWhitespace: true,//删除空格
    removeAttributeQuotes: true//删除属性的引号
   },
   chunksSortMode: 'dependency'//模块排序,按照我们需要的顺序排序
  }),

  new webpack.HashedModuleIdsPlugin(),
  new webpack.optimize.ModuleConcatenationPlugin(),
  new webpack.optimize.CommonsChunkPlugin({  // node_modules中的任何所需模块都提取到vendor
   name: 'vendor',
   minChunks (module) {
    return (
     module.resource &&
     /\.js$/.test(module.resource) &&
     module.resource.indexOf(
      path.join(__dirname, '../node_modules')
     ) === 0
    )
   }
  }),
  new webpack.optimize.CommonsChunkPlugin({
   name: 'manifest',
   minChunks: Infinity
  }),
  new webpack.optimize.CommonsChunkPlugin({
   name: 'app',
   async: 'vendor-async',
   children: true,
   minChunks: 3
  }),
  new CopyWebpackPlugin([//复制static中的静态资源(默认到dist里面)
   {
    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

2、config文件夹:

config文件夹的结构:

Vue CLI 2.x搭建vue(目录最全分析)

(1) dev.env.js和prod.env.js:分别配置:开发环境和生产环境。这个可以根据公司业务结合后端需求配置需要区分开发环境和测试环境的属性

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
 NODE_ENV: '"development"'
})

ps:webpack-merge用于实现合并类似于ES6的Object.assign()

'use strict'
module.exports = {
 NODE_ENV: '"production"'
}

(*注意属性值要用“‘'”双层引住),访问(获取值)时直接用:

process.env.属性名

ps:process(进程)是nodejs的一个全局变量,process.env 属性返回一个用户环境信息的对象

(2)index.js配置解析:

'use strict';
const path = require('path');

module.exports = {

 // ===================开发环境配置

 dev: {
  assetsSubDirectory: 'static',//静态资源文件夹(一般存放css、js、image等文件)
  assetsPublicPath: '/',//根目录
  proxyTable: {},//配置API代理,可利用该属性解决跨域的问题
  host: 'localhost', // 可以被 process.env.HOST 覆盖
  port: 3030, // 可以被 process.env.PORT 覆盖
  autoOpenBrowser: true,//编译后自动打开浏览器页面 http://localhost:3030/("port + host",默认"false"),设置路由重定向自动打开您的默认页面
  errorOverlay: true,//浏览器错误提示
  notifyOnErrors: true,//跨平台错误提示
  poll: false, //webpack提供的使用文件系统(file system)获取文件改动的通知devServer.watchOptions(监控文件改动)
  devtool: 'cheap-module-eval-source-map',//webpack提供的用来调试的模式,有多个不同值代表不同的调试模式
  cacheBusting: true,// 配合devtool的配置,当给文件名插入新的hash导致清除缓存时是否生成source-map
  cssSourceMap: true //记录代码压缩前的位置信息,当产生错误时直接定位到未压缩前的位置,方便调试
 },

// ========================生产环境配置

 build: {
  index: path.resolve(__dirname, '../dist/index.html'),//编译后"首页面"生成的绝对路径和名字
  assetsRoot: path.resolve(__dirname, '../dist'),//打包编译的根路径(默认dist,存放打包压缩后的代码)
  assetsSubDirectory: 'static',//静态资源文件夹(一般存放css、js、image等文件)
  assetsPublicPath: '/',//发布的根目录(dist文件夹所在路径)
  productionSourceMap: true,//是否开启source-map
  devtool: '#source-map',//(详细参见:https://webpack.docschina.org/configuration/devtool)
  productionGzip: false,//是否压缩
  productionGzipExtensions: ['js', 'css'],//unit的gzip命令用来压缩文件(gzip模式下需要压缩的文件的扩展名有js和css)
  bundleAnalyzerReport: process.env.npm_config_report //是否开启打包后的分析报告
 }
};

3、node_modules文件夹:

存放npm install时根据package.json配置生成的npm安装包的文件夹

4、src文件夹:

我们需要在src文件夹中开发代码,打包时webpack会根据build中的规则(build规则依赖于config中的配置)将src打包压缩到dist文件夹在浏览器中运行

(1)assets文件:用于存放静态资源(css、image),assets打包时路径会经过webpack中的file-loader编译(因此,assets需要使用绝对路径)成js

(2)components文件夹:用来存放 .vue 组件(实现复用等功能,如:过滤器,列表项等)

(3)router文件夹:在router/index.js文件中配置页面路由

(4)App.vue:是整个项目的主组件,所有页面都是通过使用<router-view/>开放入口在App.vue下进行切换的(所有的路由都是App.vue的子组件)

(5)main.js:入口js文件(全局js,你可以在这里:初始化vue实例、require/import需要的插件、注入router路由、引入store状态管理)

5、static文件夹:

webpack默认存放静态资源(css、image)的文件夹,与assets不同的是:static在打包时会直接复制一个同名文件夹到dist文件夹里(不会经过编译,可使用相对路径)

6、其他文件:

(1).babelrc:浏览器解析的兼容配置,该文件主要是对预设(presets)和插件(plugins)进行配置,因此不同的转译器作用不同的配置项,大致可分为:语法转义器、补丁转义器、sx和flow插件

(2).editorconfig:用于配置代码格式(配合代码检查工具使用,如:ESLint,团队开发时可统一代码风格),这里配置的代码规范规则优先级高于编辑器默认的代码格式化规则 。

3).gitignore:配置git提交时需要忽略的文件

(4)postcssrc.js: autoprefixer(自动补全css样式的浏览器前缀);postcss-import(@import引入语法)、CSS Modules(规定样式作用域)

(5)index.html:项目入口页面,编译之后所有代码将插入到这来

6)package.json:npm的配置文件(npm install根据package.json下载对应版本的安装包)

(7)package.lock.json:npm install(安装)时锁定各包的版本号

(8)README.md:项目使用说明

五、运行项目

在webStorm中打开项目,首先赶紧右击Project进行如下操作(否则会卡死,还有各种其他方法参见:

Vue CLI 2.x搭建vue(目录最全分析)

1、启动安装:cnpm install

Vue CLI 2.x搭建vue(目录最全分析)

2、然后npm run dev:跑起来~

Vue CLI 2.x搭建vue(目录最全分析)

3、生成打包文件 :npm run build 

然后你会发现项目多了个dist文件夹(用于部署到生产环境用,是打包压缩之后的src文件夹)

Vue CLI 2.x搭建vue(目录最全分析)

了解 vue cli 3 参见本人博客:https://3water.com/article/148100.htm

了解 node 、npm 安装/更新/使用,参见本人博客 :https://3water.com/article/157050.htm

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js监听表单value的修改同步问题,跨浏览器支持
Dec 31 Javascript
document.getElementById获取控件对象为空的解决方法
Nov 20 Javascript
详解Node.js中的事件机制
Sep 22 Javascript
jQuery视差滚动效果网页实现方法经验总结
Sep 29 Javascript
鼠标点击input,显示瞬间的边框颜色,对之修改与隐藏实例
Dec 26 Javascript
微信小程序 合法域名校验出错详解及解决办法
Mar 09 Javascript
深入浅析javascript继承体系
Oct 23 Javascript
Node层模拟实现multipart表单的文件上传示例
Jan 02 Javascript
Vue组件和Route的生命周期实例详解
Feb 10 Javascript
Vue.js中使用iView日期选择器并设置开始时间结束时间校验功能
Aug 12 Javascript
小试小程序云开发(小结)
Jun 06 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
Sep 25 Javascript
JavaScript中filter的用法实例分析
Feb 27 #Javascript
jQuery中each和js中forEach的区别分析
Feb 27 #jQuery
简单了解node npm cnpm的具体使用方法
Feb 27 #Javascript
js中对象与对象创建方法的各种方法
Feb 27 #Javascript
vue router带参数页面刷新或回退参数消失的解决方法
Feb 27 #Javascript
react的滑动图片验证码组件的示例代码
Feb 27 #Javascript
原生JS forEach()和map()遍历的区别、兼容写法及jQuery $.each、$.map遍历操作
Feb 27 #jQuery
You might like
php $_SERVER[&quot;REQUEST_URI&quot;]获取值的通用解决方法
2010/06/21 PHP
解析wamp5下虚拟机配置文档
2013/06/27 PHP
PHP中使用TCPDF生成PDF文档实例
2014/07/01 PHP
前淘宝前端开发工程师阿当的PPT中有JS技术理念问题
2010/01/15 Javascript
js新闻滚动 js如何实现新闻滚动效果
2013/01/07 Javascript
node.js中的path.resolve方法使用说明
2014/12/08 Javascript
js图片跟随鼠标移动代码
2015/11/26 Javascript
深入剖析JavaScript:Object类型
2016/05/10 Javascript
JS关闭窗口时产生的事件及用法示例
2016/08/20 Javascript
利用jquery实现下拉框的禁用与启用
2016/12/07 Javascript
js脚本编写简单刷票投票系统
2017/06/27 Javascript
深入理解vue2.0路由如何配置问题
2017/07/18 Javascript
安装vue-cli报错 -4058 的解决方法
2017/10/19 Javascript
webpack中的热刷新与热加载的区别
2018/04/09 Javascript
如何为vuex实现带参数的 getter和state.commit
2019/01/04 Javascript
Vue单文件组件开发实现过程详解
2020/07/30 Javascript
vue实现动态给id赋值,点击事件获取当前点击的元素的id操作
2020/11/09 Javascript
JS实现百度搜索框
2021/02/25 Javascript
[02:09]EHOME夺得首届辉夜杯冠军—现场颁奖仪式
2015/12/28 DOTA
[00:13]天涯墨客二技能展示
2018/08/25 DOTA
python执行get提交的方法
2015/04/29 Python
儿童编程python入门
2018/05/08 Python
解决seaborn在pycharm中绘图不出图的问题
2018/05/24 Python
kafka-python批量发送数据的实例
2018/12/27 Python
pyqt5实现俄罗斯方块游戏
2019/01/11 Python
matlab、python中矩阵的互相导入导出方式
2020/06/01 Python
Python+Opencv身份证号码区域提取及识别实现
2020/08/25 Python
python制作抽奖程序代码详解
2021/01/15 Python
CSS3 :not()选择器实现最后一行li去除某种css样式
2016/10/19 HTML / CSS
美国网上鞋城:Shoeline.com
2016/11/17 全球购物
法律专业自我鉴定
2013/10/03 职场文书
生物化学研究助理员求职信
2013/10/09 职场文书
求职信写作要突出重点
2014/01/01 职场文书
食品销售计划书
2014/04/26 职场文书
2014年计生协会工作总结
2014/11/21 职场文书
redis缓存存储Session原理机制
2021/11/20 Redis