Vue命令行工具Vue-CLI圖文詳解(推薦!)
闡述
vue-cli 構(gòu)建一個(gè)工程的時(shí)候,發(fā)現(xiàn)官方文檔還是不夠用,需要熟練掌握 es6,而 vue 的全家桶還是都要上的。
Vue CLI 的包名稱由vue-cli改成了@vue/cli。 如果你已經(jīng)全局安裝了舊版本的vue-cli(1.x 或 2.x),你需要先通過 npm uninstall vue-cli -g 或 yarn global remove vue-cli
卸載它。
安裝新版的腳手 node 也有版本要求,Vue CLI 4.x 需要Node.jsv8.9 或更高版本 (推薦 v10 以上)。
vue全家桶
vue全家桶是基于vue開發(fā)必備的也是必學(xué)的東西,概括起來就是:
1.vue-cli項(xiàng)目構(gòu)建工具
2.vue-router路由管理
3.vuex狀態(tài)管理全局變量
4.axios,http請(qǐng)求工具。
5.UI 框架 element,iview,vant
最常見常用的 vue 全家桶簡(jiǎn)單的介紹一下,希望可以幫助你了解認(rèn)識(shí)學(xué)會(huì) vue 全家桶!
vue-cli
vue-cli 就是快速搭建一個(gè) vue 項(xiàng)目的腳手架工具。
VueCLI是一個(gè)官方發(fā)布vue.js項(xiàng)目腳手架,使用 VueCLI 可以快速搭建 vue 開發(fā)環(huán)境,以及對(duì)應(yīng)的 webpack 配置。
1、CLI 是 Command-Line Interface, 翻譯為命令行界面, 但是俗稱腳手架
2、Vue CLI是一個(gè)官方發(fā)布 vue.js 項(xiàng)目腳手架
3、使用 vue-cli 可以快速搭建 Vue 開發(fā)環(huán)境以及對(duì)應(yīng)的 webpack 配置.
關(guān)于舊版本
Vue CLI 的包名稱由 vue-cli 改成了 @vue/cli
。 如果你已經(jīng)全局安裝了舊版本的 vue-cli (1.x 或 2.x)
,你需要先通過 npm uninstall vue-cli -g
或 yarn global remove vue-cli
卸載它。
腳手架依賴于 node.js
和 webpack
。
Vue CLI 需要 Node.js 8.9 或更高版本 (推薦 8.11.0+)。你可以使用 nvm 或 nvm-windows 在同一臺(tái)電腦中管理多個(gè) Node 版本。
Vue CLI 的安裝
Vue CLI2初始化項(xiàng)目:vue init webpack my-project
Vue CLI3初始化項(xiàng)目:vue create my-project
注意: 下面的默認(rèn)安裝的是 Vue CLI3 的版本,如果需要想按照 Vue CLI2 的方式初始化項(xiàng)目時(shí)不可以的。
由于博主的版本過低出現(xiàn)了切換 node 版本、反復(fù)安裝操作,第二步查看 Vue Cli 需要的node 版本。版本一直請(qǐng)?jiān)竭^反復(fù)安裝過程。
① 默認(rèn)安裝 vue/cli 腳手架 3
PS C:\Windows\system32> npm install -g @vue/cli npm WARN deprecated subscriptions-transport-ws@0.9.19: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md npm WARN deprecated graphql-tools@4.0.8: This package has been deprecated and now it only exports makeExecutableSchema.\nAnd it will no longer receive updates.\nWe recommend you to migrate to scoped packages such as @graphql-tools/schema, @graphql-tools/utils and etc.\nCheck out https://www.graphql-tools.com to learn what package you should use instead npm WARN deprecated apollo-cache-control@0.14.0: The functionality provided by the `apollo-cache-control` package is built in to `apollo-server-core` starting with Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#cachecontrol for details. npm WARN deprecated apollo-tracing@0.15.0: The `apollo-tracing` package is no longer part of Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#tracing for details npm WARN deprecated graphql-extensions@0.15.0: The `graphql-extensions` API has been removed from Apollo Server 3. Use the plugin API instead: https://www.apollographql.com/docs/apollo-server/integrations/plugins/ npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated C:\Program Files\nodejs\vue -> C:\Program Files\nodejs\node_modules\@vue\cli\bin\vue.js > core-js-pure@3.22.0 postinstall C:\Program Files\nodejs\node_modules\@vue\cli\node_modules\core-js-pure > node -e "try{require('./postinstall')}catch(e){}" Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library! The project needs your help! Please consider supporting of core-js: > https://opencollective.com/core-js > https://patreon.com/zloirock > bitcoin: bc1qlea7544qtsmj2rayg0lthvza9fau63ux0fstcz Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -) > @apollo/protobufjs@1.2.2 postinstall C:\Program Files\nodejs\node_modules\@vue\cli\node_modules\@apollo\protobufjs > node scripts/postinstall npm WARN node-fetch@2.6.7 requires a peer of encoding@^0.1.0 but none is installed. You must install peer dependencies yourself. npm WARN ws@7.5.7 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself. npm WARN ws@7.5.7 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself. + @vue/cli@5.0.4 added 880 packages from 531 contributors in 130.475s 結(jié)束
② 默認(rèn)安裝失敗,解決mode版本問題
安裝之后,你就可以在命令行中訪問 vue 命令。
檢查其版本是否正確:
PS C:\Windows\system32> vue --version You are using Node v11.15.0, but this version of @vue/cli requires Node ^12.0.0 || >= 14.0.0. Please upgrade your Node version. 您使用的是 Node v11.15.0,但是這個(gè)版本的 @vue/cli 需要 Node ^12.0.0 || >= 14.0.0。 請(qǐng)升級(jí)您的節(jié)點(diǎn)版本。 PS C:\Windows\system32>
③ nvm下載太慢問題解決
由于 nvm 默認(rèn)的下載地址 http://nodejs.org/dist/ 是外國(guó)外服務(wù)器,國(guó)內(nèi)很慢可以使用淘寶的鏡像。
where nvm 找到 nvm 安裝路徑
找到 settings.txt 文件
將下面這兩句話復(fù)制到settings.txt,并保存
node_mirror: https://npm.taobao.org/mirrors/node/ npm_mirror: https://npm.taobao.org/mirrors/npm/
④ 安裝 Node ^12.0.0
PS C:\Windows\system32> nvm install 12.0.0 Downloading node.js version 12.0.0 (64-bit)... Complete Creating C:\Users\ASUS\AppData\Roaming\nvm\temp Downloading npm version 6.9.0... Complete Installing npm v6.9.0... Installation complete. If you want to use this version, type nvm use 12.0.0 PS C:\Windows\system32> nvm use 12.0.0 Now using node v12.0.0 (64-bit) PS C:\Windows\system32> nvm list 14.17.6 * 12.0.0 (Currently using 64-bit executable) 11.15.0 此版本主項(xiàng)目 PS C:\Windows\system32>
⑤ 從新安裝 VueCli 腳手架 3
PS C:\Windows\system32> npm install -g @vue/cli npm WARN deprecated subscriptions-transport-ws@0.9.19: The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md npm WARN deprecated graphql-tools@4.0.8: This package has been deprecated and now it only exports makeExecutableSchema.\nAnd it will no longer receive updates.\nWe recommend you to migrate to scoped packages such as @graphql-tools/schema, @graphql-tools/utils and etc.\nCheck out https://www.graphql-tools.com to learn what package you should use instead npm WARN deprecated apollo-cache-control@0.14.0: The functionality provided by the `apollo-cache-control` package is built in to `apollo-server-core` starting with Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#cachecontrol for details. npm WARN deprecated apollo-tracing@0.15.0: The `apollo-tracing` package is no longer part of Apollo Server 3. See https://www.apollographql.com/docs/apollo-server/migration/#tracing for details npm WARN deprecated graphql-extensions@0.15.0: The `graphql-extensions` API has been removed from Apollo Server 3. Use the plugin API instead: https://www.apollographql.com/docs/apollo-server/integrations/plugins/ npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated C:\Program Files\nodejs\vue -> C:\Program Files\nodejs\node_modules\@vue\cli\bin\vue.js > core-js-pure@3.22.0 postinstall C:\Program Files\nodejs\node_modules\@vue\cli\node_modules\core-js-pure > node -e "try{require('./postinstall')}catch(e){}" Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library! The project needs your help! Please consider supporting of core-js: > https://opencollective.com/core-js > https://patreon.com/zloirock > bitcoin: bc1qlea7544qtsmj2rayg0lthvza9fau63ux0fstcz Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -) > @apollo/protobufjs@1.2.2 postinstall C:\Program Files\nodejs\node_modules\@vue\cli\node_modules\@apollo\protobufjs > node scripts/postinstall npm WARN node-fetch@2.6.7 requires a peer of encoding@^0.1.0 but none is installed. You must install peer dependencies yourself. npm WARN ws@7.5.7 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself. npm WARN ws@7.5.7 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself. + @vue/cli@5.0.4 added 880 packages from 531 contributors in 81.975s 安裝結(jié)束
查看 vue 版本,及驗(yàn)證是否安裝正確。
PS C:\Windows\system32> vue --version @vue/cli 5.0.4 PS C:\Windows\system32>
④ 拉取 2.x 模板 (舊版本)
Vue CLI >= 3 和舊版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆蓋了。
如果你仍然需要使用舊版本的 vue init 功能,你可以全局安裝一個(gè)橋接工具:
PS C:\Windows\system32> npm install -g @vue/cli-init npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + @vue/cli-init@5.0.4 added 259 packages from 231 contributors in 38.328s PS C:\Windows\system32>
vue init
的運(yùn)行效果將會(huì)跟 vue-cli@2.x
相同。
創(chuàng)建項(xiàng)目提示,原因上面安裝已經(jīng)提示命令都為棄用狀態(tài)。
PS E:\node> vue init webpack vue-cli2-test Command vue init requires a global addon to be installed. Please run undefined @vue/cli-init and try again. 命令 vue init 需要安裝全局插件。 請(qǐng)運(yùn)行 undefined @vue/cli-init 并重試。 PS E:\node>
⑤ 安裝vue指定版本
【前端開發(fā)】Vue-CLI4 &Vue-CLI3 與Vue-CLI2 的區(qū)別
1、安裝:
Vue-CLI2:
npm install -g vue-cli 或 cnpm install -g vue-cli
Vue-CLI最新版本:
npm install -g @vue/cli 或 cnpm install -g @vue/cli
2、卸載
Vue-CLI2:
npm uninstall -g vue-cli 或 cnpm uninstall -g vue-cli
Vue-CLI最新版本:
npm uninstall -g @vue/cli 或 cnpm uninstall -g @vue/cli
指定版本安裝
可以安裝:2.6.0 版本 npm install -g vue-cli@2.6 可以安裝:2.6.0 版本 cnpm install -g vue-cli@v2.6.* 卸載vue cnpm uninstall -g vue-cli
cdn 鏈接
<title>Vue 測(cè)試實(shí)例 - 菜鳥教程(runoob.com)</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> https://unpkg.com/browse/vue@2.6.14/dist/ 選擇vue版本 https://unpkg.com/browse/vue@2.6.14/dist/vue.min.js
⑥ 博主node版本
改 vue 版本
PS C:\WINDOWS\system32> npm install vue-cli -g npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. C:\Program Files\nodejs\vue-init -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue-init C:\Program Files\nodejs\vue-list -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue-list C:\Program Files\nodejs\vue -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue + vue-cli@2.9.6 added 244 packages from 229 contributors and updated 1 package in 22.77s PS C:\WINDOWS\system32> vue -V 2.9.6 PS C:\WINDOWS\system32>
如何查看 Vue項(xiàng) 目 vue 的版本號(hào):
如果是用 vue-cli 創(chuàng)建的項(xiàng)目,則找到項(xiàng)目根目錄下的 "package.json"
文件。
初始化項(xiàng)目
① vue init命令講解
用 vue init 命令來初始化項(xiàng)目,具體使用方法如下:
vue init <template-name> <project-name>
init:表示要用 vue-cli 來初始化項(xiàng)目
<template-name>
:表示模板名稱,vue-cli 官方提供的 5 種模板:
1、webpack:
一個(gè)全面的 webpack+vue-loader 的模板,功能包括熱加載,linting,檢測(cè)和CSS擴(kuò)展。
2、webpack-simple:
一個(gè)簡(jiǎn)單 webpack+vue-loader 的模板,不包含其他功能,讓你快速的搭建 vue 的開發(fā)環(huán)境。
3、browserify:
一個(gè)全面的 Browserify+vueify 的模板,功能包括熱加載,linting,單元檢測(cè)。
4、browserify-simple:
一個(gè)簡(jiǎn)單 Browserify+vueify 的模板,不包含其他功能,讓你快速的搭建 vue 的開發(fā)環(huán)境。
5、simple:
一個(gè)最簡(jiǎn)單的單頁應(yīng)用模板。
<project-name>
:標(biāo)識(shí)項(xiàng)目名稱,用戶根據(jù)自己的項(xiàng)目來起名字。
② 項(xiàng)目初始化
在實(shí)際開發(fā)中,一般都會(huì)使用 webpack 這個(gè)模板,命令使用如下:
第一步操作:
PS E:\node> vue init webpack vue-cli296 ? Project name (vue-cli296)
Project name:項(xiàng)目名稱 ,默認(rèn)為初始化建項(xiàng)目的名稱 vue-cli296,不需要直接回車
第二步操作:
Project description (A Vue.js project)
Project description:項(xiàng)目描述,默認(rèn)為A Vue.js project,不需要直接回車
Author (cwgqmxy <1157818690@qq.com>)
Author:作者,如果有配置 git 的作者,自動(dòng)會(huì)讀取。直接回車
第三步操作:
兩個(gè)選項(xiàng),Runtime + Compiler 和 Runtime-only:
· Runtime + Compiler: recommended for most users (運(yùn)行程序+編譯器:推薦給大多數(shù)用戶) · Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specificHTML) are ONLY allowed in .vue files - render functions are required elsewhere (僅運(yùn)行程序: 比上面那種模式輕大約 6KB min+gzip,但是 template (或任何特定于vue的html)只允許在.vue文件中使用——其他地方用需要 render 函數(shù))
區(qū)別
1、runtime-only 比 runtime-compiler 輕 6kb
2、runtime-only 運(yùn)行更快
3、runtime-only 其實(shí)只能識(shí)別 render 函數(shù),不能識(shí)別 template,.vue 文件中的也是被 vue-template-compiler 翻譯成了 render 函數(shù),所以只能在 .vue
里寫 template。
兩種模式生成的 腳手架 即(代碼模板)其實(shí)區(qū)別只有在 main.js 中,其他都是一樣的:
可以發(fā)現(xiàn)一個(gè) 是用 template + component 而另一個(gè) 則是 用 render 函數(shù)。
第四步操作:
Install vue-router? (Y/n)
Install vue-router?
是否安裝vue的路由插件,需要安裝,選擇Y
第五步操作:
Use ESLint to lint your code? (Y/n) 輸入 Y Pick an ESLint preset:選擇分支風(fēng)格 選項(xiàng)有三個(gè)(博主選了第一個(gè)) 1.standard(https://github.com/feross/standard) js的標(biāo)準(zhǔn)風(fēng)格 2.Airbnb(https://github.com/airbnb/javascript) JavaScript最合理的方法,這個(gè)github地址說是JavaScript最合理的方法 3.none (configure it yourself) 自己配置
Use ESLint to lint your code?
是否用 ESLint 來限制你的代碼錯(cuò)誤和風(fēng)格。不需要輸入n,需要選擇y,如果是大型團(tuán)隊(duì)開發(fā),最好是進(jìn)行配置。
第六步操作:
Set up unit tests (Y/n)
是否需要安裝單元測(cè)試工具,不需要輸入n,需要選擇y
第七步操作:
Setup e2e tests with Nightwatch? (Y/n)
是否安裝E2E測(cè)試框架NightWatch(E2E,也就是End To End,就是所謂的“用戶真實(shí)場(chǎng)景”。
第八步操作:
Should we run `npm install` for you after the project has been created? (recommended) (Use arrow keys)
(譯:項(xiàng)目創(chuàng)建后是否要為你運(yùn)行 “npm install”? 這里選擇包管理工具)
選項(xiàng)有三個(gè)
yes,use npm(使用npm)
yes,use yarn(使用yarn)
no,I will handle that myself(自己配置安裝包)
開始創(chuàng)建了項(xiàng)目,初始化完成之后會(huì)出現(xiàn)以下信息,表示操作成功。
PS E:\node> vue init webpack vue-cli296 ? Project name vue-cli296 ? Project description A Vue.js project ? Author cwgqmxy <1157818690@qq.com> ? Vue build runtime ? Install vue-router? Yes ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npm vue-cli · Generated "vue-cli296". # Installing project dependencies ... # ======================== npm WARN deprecated babel-eslint@8.2.6: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. npm WARN deprecated eslint-loader@1.9.0: This loader has been deprecated. Please use eslint-webpack-plugin npm WARN deprecated extract-text-webpack-plugin@3.0.2: Deprecated. Please use https://github.com/webpack-contrib/mini-css-extract-plugin npm WARN deprecated html-webpack-plugin@2.30.1: out of support npm WARN deprecated browserslist@2.11.3: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. npm WARN deprecated uglify-es@3.3.9: support for ECMAScript is superseded by `uglify-js` as of v3.13.0 npm WARN deprecated bfj-node4@5.3.1: Switch to the `bfj` package for fixes and new features! npm WARN deprecated core-js@2.6.12: core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js. npm WARN deprecated chokidar@2.1.8: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated flatten@1.0.3: flatten is deprecated in favor of utility frameworks such as lodash. npm WARN deprecated browserslist@1.7.7: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. npm WARN deprecated svgo@0.7.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm WARN deprecated circular-json@0.3.3: CircularJSON is in maintenance only, flatted is its successor. npm WARN deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated > core-js@2.6.12 postinstall E:\node\vue-cli296\node_modules\core-js > node -e "try{require('./postinstall')}catch(e){}" Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library! The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: > https://opencollective.com/core-js > https://www.patreon.com/zloirock Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -) > ejs@2.7.4 postinstall E:\node\vue-cli296\node_modules\ejs > node ./postinstall.js Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/) > es5-ext@0.10.60 postinstall E:\node\vue-cli296\node_modules\es5-ext > node -e "try{require('./_postinstall')}catch(e){}" # # Fatal error in , line 0 # Check failed: U_SUCCESS(status). # # # #FailureMessage Object: 000000E8857BCE10[ ......] / postinstall: info lifecycle es5-ext@0.10.60~postinstall: npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\watchpack-chokidar2\node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\webpack-dev-server\node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm ERR! Maximum call stack size exceeded npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\Administrator\AppData\Roaming\npm-cache\_logs\2022-04-19T08_59_35_781Z-debug.log Running eslint --fix to comply with chosen preset rules... # ======================== > vue-cli296@1.0.0 lint E:\node\vue-cli296 > eslint --ext .js,.vue src "--fix" # Project initialization finished! # ======================== To get started: cd vue-cli296 npm run dev Documentation can be found at https://vuejs-templates.github.io/webpack PS E:\node>
③ 目錄結(jié)構(gòu)詳解
④ 運(yùn)行項(xiàng)目
環(huán)境崩潰了,從新裝node環(huán)境。
npm 是什么東東?
npm其實(shí)是Node.js的包管理工具(package manager)。
為啥我們需要一個(gè)包管理工具呢?
因?yàn)槲覀冊(cè)贜ode.js上開發(fā)時(shí),會(huì)用到很多別人寫的JavaScript代碼。
(http://caibaojian.com/npm/all.html)
講了這么多,npm究竟在哪?
其實(shí)npm已經(jīng)在Node.js安裝的時(shí)候順帶裝好了。我們?cè)诿钐崾痉蛘呓K端輸入npm -v,
node 安裝適合小白
1 去node官網(wǎng)下載
中文官方網(wǎng)址:http://nodejs.cn/
下載網(wǎng)址:http://nodejs.cn/download/
官方網(wǎng)址:https://nodejs.org/en/
2 下載完成后雙擊安裝包,跳出安裝彈窗,點(diǎn)擊Next
以下一路 Next
node.js runtime:node 運(yùn)行環(huán)境
orepack manager:npm 包管理
Online documentation shortcuts:在線文件快捷方式
Add to Path:添加路徑
corepack manager:核心包管理
不用打鉤,如果打了 √ 會(huì)把 node 所有的工具都下載,需要很久,以后要什么工具,直接npm下載。
安裝好啦
環(huán)境路徑已經(jīng)自動(dòng)設(shè)置好了
可以去 cmd 窗口中查看安裝 node 和 npm 的版本號(hào)。
從新來過
上面環(huán)境崩潰了,從新搭建的環(huán)境。
PS E:\node> node -v v11.15.0 PS E:\node>
vue-cli 安裝
vue-cli是vue官方出品的快速構(gòu)建單頁應(yīng)用的腳手架,里面集成了webpack,npm,nodejs,babel,vue,vue-router。
PS E:\node> npm install vue-cli -g npm WARN deprecated vue-cli@2.9.6: This package has been deprecated in favour of @vue/cli npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 npm WARN deprecated coffee-script@1.12.7: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) npm WARN deprecated har-validator@5.1.5: this library is no longer supported npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. C:\Program Files\nodejs\vue-init -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue-init C:\Program Files\nodejs\vue -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue C:\Program Files\nodejs\vue-list -> C:\Program Files\nodejs\node_modules\vue-cli\bin\vue-list + vue-cli@2.9.6 added 245 packages from 230 contributors in 27.375s PS E:\node>
PS E:\node> vue --version 2.9.6 PS E:\node>
vue-cli 項(xiàng)目初始化
PS E:\node> vue init webpack vue296 ? Project name vue296 ? Project description A Vue.js project ? Author cwgqmxy <1157818690@qq.com> ? Vue build standalone ? Install vue-router? Yes ? Use ESLint to lint your code? Yes ? Pick an ESLint preset Standard ? Set up unit tests No ? Setup e2e tests with Nightwatch? No ? Should we run `npm install` for you after the project has been created? (recommended) npm vue-cli · Generated "vue296". # Installing project dependencies ... # ======================== npm WARN deprecated babel-eslint@8.2.6: babel-eslint is now @babel/eslint-parser. This package will no longer receive updates. npm WARN deprecated eslint-loader@1.9.0: This loader has been deprecated. Please use eslint-webpack-plugin npm WARN deprecated extract-text-webpack-plugin@3.0.2: Deprecated. Please use https://github.com/webpack-contrib/mini-css-extract-plugin npm WARN deprecated html-webpack-plugin@2.30.1: out of support npm WARN deprecated browserslist@2.11.3: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. npm WARN deprecated uglify-es@3.3.9: support for ECMAScript is superseded by `uglify-js` as of v3.13.0 npm WARN deprecated bfj-node4@5.3.1: Switch to the `bfj` package for fixes and new features! npm WARN deprecated chokidar@2.1.8: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies npm WARN deprecated core-js@2.6.12: core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js. npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. npm WARN deprecated flatten@1.0.3: flatten is deprecated in favor of utility frameworks such as lodash. npm WARN deprecated browserslist@1.7.7: Browserslist 2 could fail on reading Browserslist >3.0 config used in other tools. npm WARN deprecated svgo@0.7.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm WARN deprecated circular-json@0.3.3: CircularJSON is in maintenance only, flatted is its successor. npm WARN deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead. npm WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x. npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated > core-js@2.6.12 postinstall E:\node\vue296\node_modules\core-js > node -e "try{require('./postinstall')}catch(e){}" Thank you for using core-js ( https://github.com/zloirock/core-js ) for polyfilling JavaScript standard library! The project needs your help! Please consider supporting of core-js on Open Collective or Patreon: > https://opencollective.com/core-js > https://www.patreon.com/zloirock Also, the author of core-js ( https://github.com/zloirock ) is looking for a good job -) > ejs@2.7.4 postinstall E:\node\vue296\node_modules\ejs > node ./postinstall.js Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/) > es5-ext@0.10.60 postinstall E:\node\vue296\node_modules\es5-ext > node -e "try{require('./_postinstall')}catch(e){}" > uglifyjs-webpack-plugin@0.4.6 postinstall E:\node\vue296\node_modules\webpack\node_modules\uglifyjs-webpack-plugin > node lib/post_install.js npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.3.2 (node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\watchpack-chokidar2\node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\webpack-dev-server\node_modules\chokidar\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) added 1395 packages from 715 contributors in 76.245s Running eslint --fix to comply with chosen preset rules... # ======================== > vue296@1.0.0 lint E:\node\vue296 > eslint --ext .js,.vue src "--fix" # Project initialization finished! # ======================== To get started: cd vue296 npm run dev Documentation can be found at https://vuejs-templates.github.io/webpack PS E:\node>
cd 命令進(jìn)入到項(xiàng)目目錄
npm run dev
成功頁面
package.json
{ "name": "vue296", "version": "1.0.0", "description": "A Vue.js project", "author": "cwgqmxy <1157818690@qq.com>", "private": true, "scripts": { "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "lint": "eslint --ext .js,.vue src", "build": "node build/build.js" }, "dependencies": { "vue": "^2.5.2", "vue-router": "^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-loader": "^7.1.1", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "chalk": "^2.0.1", "copy-webpack-plugin": "^4.0.1", "css-loader": "^0.28.0", "eslint": "^4.15.0", "eslint-config-standard": "^10.2.1", "eslint-friendly-formatter": "^3.0.0", "eslint-loader": "^1.7.1", "eslint-plugin-import": "^2.7.0", "eslint-plugin-node": "^5.2.0", "eslint-plugin-promise": "^3.4.0", "eslint-plugin-standard": "^3.0.1", "eslint-plugin-vue": "^4.0.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^1.1.4", "friendly-errors-webpack-plugin": "^1.6.1", "html-webpack-plugin": "^2.30.1", "node-notifier": "^5.1.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", "rimraf": "^2.6.0", "semver": "^5.3.0", "shelljs": "^0.7.6", "uglifyjs-webpack-plugin": "^1.1.1", "url-loader": "^0.5.8", "vue-loader": "^13.3.0", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] }
項(xiàng)目結(jié)構(gòu)
一個(gè) vue-cli 的項(xiàng)目結(jié)構(gòu)如下,其中 src 文件夾是需要掌握,其余了解即可。
文件夾目錄如下:
1、build目錄(webpack配置)
build 文件主要是 webpack 的配置,目錄詳情如下:
2、config目錄(vue項(xiàng)目配置目錄)
config 文件主要是項(xiàng)目相關(guān)配置,常用的就是當(dāng)端口沖突時(shí)配置監(jiān)聽端口,打包輸出路徑及命名等,目錄詳情如下:
3、node_modules(項(xiàng)目依賴包)
node_modules 里面是項(xiàng)目依賴包,其中包括很多基礎(chǔ)依賴,自己也可以根據(jù)需要安裝其他依賴。安裝方法打開命令工具,進(jìn)入項(xiàng)目目錄,輸入 npm install [依賴包名稱]
,回車。
安裝依賴:npm i
在兩種情況下我們會(huì)自己去安裝依賴:
》項(xiàng)目運(yùn)行缺少該依賴包
》安裝插件:如 vuex
PS:有時(shí)會(huì)安裝指定依賴版本,需在依賴包名稱后加上版本號(hào)信息,
如 npm install vue-loader@11.1.4
src 項(xiàng)目核心文件講解
核心文件目錄前面已經(jīng)說明了,下面重點(diǎn)講解 index.html,main.js,App.vue,router
的 index.js,HelloWorld.vue
。
1、index.html(主頁)
index.html 為項(xiàng)目的主頁,跟其他 html 一樣,但一般只定義一個(gè)空的根節(jié)點(diǎn),在 main.js 里面定義的實(shí)例將掛載在根節(jié)點(diǎn)下,內(nèi)容都通過 vue 組件來填充。
說明如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>my-vue-demo</title> </head> <body> <!-- 定義的vue實(shí)例將掛載在#app節(jié)點(diǎn)下 --> <div id="app"></div> </body> </html>
2、main.js(入口文件)
main.js 為項(xiàng)目的入口文件,即單入口,主要是引入 vue 框架,根組件及路由設(shè)置,并且定義 vue 實(shí)例,說明如下:
// 引入vue框架 import Vue from 'vue' // 引入根組件 import App from './App' // 引入路由配置 import router from './router' // 關(guān)閉生產(chǎn)模式下給出的提示 Vue.config.productionTip = false // 定義實(shí)例 new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
3、App.vue(根組件)
一個(gè) vue 頁面通常由三部分組成:
模板 (template)
js (script)
樣式 (style)
說明如下:
<!-- 模板 --><template> <div id="app"> <img src="./assets/logo.png"> <router-view/> </div></template><!-- js代碼 --><script>export default {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> name: 'App'}</script><!-- css樣式 --><style>#app {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style>
[ template-模板 ]
(1) 模板只能包含一個(gè)父節(jié)點(diǎn),也就是說頂層的 div 只能有一個(gè)
(如上圖,父節(jié)點(diǎn)為 #app
的 div,其沒有兄弟節(jié)點(diǎn))
(2)是子路由視圖插槽,后面的路由頁面都顯示在此處,相當(dāng)于 iframe
【script-JS代碼】
vue 通常用 es6 來寫,用 export default 導(dǎo)出,其下面可以包含數(shù)據(jù) data,生命周期 ( mounted 等),方法( methods )等。
【style-CSS樣式】
樣式通過 style 標(biāo)簽 <style></style>
包裹,默認(rèn)是影響全局的,如需定義作用域只在該組件下起作用,需在標(biāo)簽上加 scoped,<style scoped></style>
。
引入外部CSS示例:
<style> import './assets/css/public.css' </style>
4、router(路由配置)
router文件夾下,有一個(gè) index,js 的路由配置文件,
說明如下:
// 引入vue框架 import Vue from 'vue' // 引入vue-router路由依賴 import Router from 'vue-router' // 引入頁面組件,命名為HelloWorld import HelloWorld from '@/components/HelloWorld' // 使用路由依賴 Vue.use(Router) // 定義路由配置 export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: HelloWorld } ] })
5、HelloWorld.vue(頁面組件)
最熟悉的 HelloWorld 輸出,說明如下:
<template> <div> <!-- 輸出變量 --> <h1>{{ msg }}</h1> </div> </template> <script> export default { // 定義頁面名稱,可以不要 name: 'HelloWorld', data () { return { // 定義變量 msg: 'HelloWorld' } } } </script> <style scoped> h1 { font-size: 16px; font-weight: normal; } </style>
網(wǎng)頁 CDN 引入 vue@2.6.14 示例
<title>Vue 測(cè)試實(shí)例 - 菜鳥教程(runoob.com)</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> https://unpkg.com/browse/vue@2.6.14/dist/ 選擇vue版本 https://unpkg.com/browse/vue@2.6.14/dist/vue.min.js
<!--第一步:創(chuàng)建文件夾及html文件--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之Helloworld</title> <!--第二步:引入Vue庫--> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <!--第三步:創(chuàng)建一個(gè)Div--> <div id="app"> <!--Vue的模板的綁定數(shù)據(jù)的方法,用兩對(duì)花括號(hào)進(jìn)行綁定Vue中的數(shù)據(jù)對(duì)象的屬性 --> {{message}} </div> <!--第四步:創(chuàng)建Vue的對(duì)象,并把數(shù)據(jù)綁定到上面創(chuàng)建好的div上去。--> <script type="text/javascript"> var app=new Vue({ // 創(chuàng)建Vue對(duì)象。Vue的核心對(duì)象。 el:'#app', // el屬性:把當(dāng)前Vue對(duì)象掛載到 div標(biāo)簽上,#app是id選擇器 data:{ // data: 是Vue對(duì)象中綁定的數(shù)據(jù) message:'hello Vue!' // message 自定義的數(shù)據(jù) } }) </script> </body> </html>
內(nèi)部指令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之Helloworld</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> <style type="text/css"> [v-cloak] { display: none; } </style> </head> <body> <div id="app"> <!-- v-if --> <div v-if="isLogin">你好</div> <!-- v-else --> <div v-else>請(qǐng)登錄后操作</div> <!-- v-show --> <div v-show="isLogin">你好</div> <!-- v-else-if --> <div v-if="type === 'A'">A</div> <div v-else-if="type === 'B'">B</div> <div v-else-if="type === 'C'">C</div> <div v-else>Not A/B/C</div> <!-- v-for基本使用 --> <ul> <li v-for="item in items"> {{item}} </li> </ul> <!-- v-for高級(jí)使用 --> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} - {{ value }} </li> </ul> <!-- v-text --> <div v-text="message"></div> <!-- v-html --> <div v-html="msgHtml"></div> <!-- v-on部分 --> <div>本場(chǎng)比賽得分:{{count}}</div> <!-- 常規(guī)寫法 --> <button v-on:click="add">加分</button> <!-- @縮寫 --> <button @click="add">加分</button><br/> <!-- v-model input --> <input type="text" v-model="message"> <br/> <!-- v-model textarea --> <textarea cols="30" rows="10" v-model="message"></textarea> <br/> <!-- v-model checkbox --> <input type="checkbox" id="first" value="1" v-model="status"> <label for="first">有效</label> <input type="checkbox" id="second" value="2" v-model="status"> <label for="second">無效</label> <div>狀態(tài):{{status}}</div> <!-- v-model radio --> <input type="radio" id="one" value="男" v-model="sex"> <label for="one">男</label> <input type="radio" id="two" value="女" v-model="sex"> <label for="one">女</label> <div>性別:{{sex}}</div> <!-- v-model select --> <select v-model="selected"> <option disabled value="">請(qǐng)選擇</option> <option>A</option> <option>B</option> <option>C</option> </select> <div>Selected: {{ selected }}</div> <!-- v-model select --> <img v-bind:src="imgSrc" width="200px"><br/> <img :src="imgSrc" width="200px"><br/> <!-- v-pre --> <div v-pre>{{message}}</div> <!-- v-cloak --> <div v-cloak>{{message}}</div> <!-- v-pre --> <div v-once>第一次綁定的值:{{message}}</div> </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ isLogin: false, type: 'A', items:[20,23,18,65], object: { firstName: 'John', lastName: 'Doe' }, message: 'hello Vue', msgHtml: '<h2>hello Vue!</h2>', count: 1, status: [], sex: '男', selected: '', imgSrc:'http://liangxinghua.com/uploads/image/20180709/1531106987.png' }, methods: { add() { this.count++; } } }) </script> </body> </html>
(1)v-if
<div v-if="isLogin">你好</div>
(2)v-else
<div v-else>請(qǐng)登錄后操作</div>
(3)v-show
<div v-show="isLogin">你好</div>
(4)v-else-if
<div v-if="type === 'A'">A</div> <div v-else-if="type === 'B'">B</div> <div v-else-if="type === 'C'">C</div> <div v-else>Not A/B/C</div>
(5)v-if 與 v-show 的區(qū)別
v-if: 在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建,開銷較高,在運(yùn)行時(shí)條件很少改變時(shí)使用。
v-show:調(diào)整css dispaly屬性,開銷較小,在常頻繁地切換時(shí)使用。
(6)v-for
(1)基本用法
<!-- 模板 --> <div id="app"> <ul> <li v-for="item in items"> {{item}} </li> </ul> </div> <!--JS代碼 --> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ items:[20,23,18,65] } }) </script>
(2)對(duì)象遍歷
參數(shù): 第一個(gè)為值,第二個(gè)為鍵名,第三個(gè)為索引
<!-- 模板 --> <div id="app"> <ul> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} - {{ value }} </li> </ul> </div> <!--JS代碼 --> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ object: { firstName: 'John', lastName: 'Doe' } } }) </script>
(7)v-text
{{xxx}}
取值有個(gè)弊端,當(dāng)網(wǎng)速很慢或 javascript 出錯(cuò)時(shí),會(huì)在頁面顯示 {{xxx}}
,Vue 提供的 v-text 可以解決這個(gè)問題。
<div>{{ message }}</div> <!-- 和下面的一樣 --> <div v-text="message"></div>
(8)v-html
用于輸出 html 代碼
<span v-html="msgHtml"></span><span v-html="msgHtml"></span>
(9)v-on
(1)常規(guī)用法
// html <div>本場(chǎng)比賽得分:{{count}}</div> <button v-on:click="add">加分</button> // JS data:{ count: 1 }, methods: { add() { this.count++; } }
(2)縮寫
<button @click="add">加分</button>
指令詳情的更多用法參照 v-on 官方 API
(10)v-model
以下的 model 都需要在 data 中聲明初始值:
data: { message: 'hello Vue', count: 1, status: [], sex: '男', selected: '' }
(1)input
(2)textarea
<input type="text" v-model="message"> <textarea cols="30" rows="10" v-model="message"></textarea>
(3)checkbox
<input type="checkbox" id="first" value="1" v-model="status"> <label for="first">有效</label> <input type="checkbox" id="second" value="2" v-model="status"> <label for="second">無效</label> <div>狀態(tài):{{status}}</div>
(4)radio
<input type="radio" id="one" value="男" v-model="sex"> <label for="one">男</label> <input type="radio" id="two" value="女" v-model="sex"> <label for="one">女</label> <div>性別:{{sex}}</div>
(5)select
<select v-model="selected"> <option disabled value="">請(qǐng)選擇</option> <option>A</option> <option>B</option> <option>C</option> </select> <div>Selected: {{ selected }}</div>
(11)v-bind
用于處理 html 標(biāo)簽的動(dòng)態(tài)屬性,即動(dòng)態(tài)賦值。
(1)常規(guī)用法
// html <img v-bind:src="imgSrc" width="200px"> // js data: { imgSrc:'http://liangxinghua.com/uploads/image/20180709/1531106987.png' }
(2)縮寫
<img :src="imgSrc" width="200px">
指令詳情的更多用法參照 v-bind 官方 API
(12)v-pre
在模板中跳過 vue 的編譯,直接輸出原始值,如果在標(biāo)簽中加入 v-pre 就不會(huì)輸出 vue 中的data 值了。
<div v-pre>{{message}}</div>
(13)v-cloak
在 vue 渲染完指定的整個(gè) DOM 后才進(jìn)行顯示。它必須和 CSS 樣式一起使用。
// css [v-cloak] { display: none; } // html <div v-cloak>{{message}}</div>
(14)v-once
只顯示 DOM 第一次渲染的值,以后不改變了
<div v-once>第一次綁定的值:{{message}}</div>
生命周期
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之Helloworld</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> {{message}} </div> <script type="text/javascript"> var app=new Vue({ el:'#app', data:{ message:'hello Vue!' }, beforeCreate: function () { console.group('beforeCreate 創(chuàng)建前狀態(tài)===============》'); console.log("%c%s", "color:red" , "el : " + this.$el); //undefined console.log("%c%s", "color:red","data : " + this.$data); //undefined console.log("%c%s", "color:red","message: " + this.message) }, created: function () { console.group('created 創(chuàng)建完畢狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); //undefined console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, beforeMount: function () { console.group('beforeMount 掛載前狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + (this.$el)); //已被初始化 console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, mounted: function () { console.group('mounted 掛載結(jié)束狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); //已被初始化 console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); //已被初始化 console.log("%c%s", "color:red","message: " + this.message); //已被初始化 }, beforeUpdate: function () { console.group('beforeUpdate 更新前狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, updated: function () { console.group('updated 更新完成狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, beforeDestroy: function () { console.group('beforeDestroy 銷毀前狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message); }, destroyed: function () { console.group('destroyed 銷毀完成狀態(tài)===============》'); console.log("%c%s", "color:red","el : " + this.$el); console.log(this.$el); console.log("%c%s", "color:red","data : " + this.$data); console.log("%c%s", "color:red","message: " + this.message) } }) </script> </body> </html>
生命周期表格
周期 | 說明 |
---|---|
beforeCreate | 在實(shí)例初始化之后,數(shù)據(jù)觀測(cè)和事件配置之前被調(diào)用 |
created | 在實(shí)例創(chuàng)建完成后被立即調(diào)用,完成數(shù)據(jù)觀測(cè),屬性和方法的運(yùn)算,初始化事件,$el屬性未見 |
beforeMount | 在掛載開始之前被調(diào)用:相關(guān)的 render 函數(shù)首次被調(diào)用,只在虛擬DOM生成HTML |
mounted | 在el 被新創(chuàng)建的 vm.$el 替換,并掛載到實(shí)例上去之后調(diào)用。實(shí)例已完成以下的配置:用上面編譯好的html內(nèi)容替換el屬性指向的DOM對(duì)象。完成模板中的html渲染到html頁面中。此過程中進(jìn)行ajax交互 |
beforeUpdate | 在數(shù)據(jù)更新之前調(diào)用,發(fā)生在虛擬DOM重新渲染和打補(bǔ)丁之前??梢栽谠撱^子中進(jìn)一步地更改狀態(tài),不會(huì)觸發(fā)附加的重渲染過程 |
updated | 在由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁之后調(diào)用。調(diào)用時(shí),組件DOM已經(jīng)更新,所以可以執(zhí)行依賴于DOM的操作。然而在大多數(shù)情況下,應(yīng)該避免在此期間更改狀態(tài),因?yàn)檫@可能會(huì)導(dǎo)致更新無限循環(huán)。該鉤子在服務(wù)器端渲染期間不被調(diào)用 |
activated | keep-alive 組件激活時(shí)調(diào)用 |
deactivated | keep-alive 組件停用時(shí)調(diào)用 |
beforeDestroy | 在實(shí)例銷毀之前調(diào)用。實(shí)例仍然完全可用 |
destroyed | 在實(shí)例銷毀之后調(diào)用。調(diào)用后,所有的事件監(jiān)聽器會(huì)被移除,所有的子實(shí)例也會(huì)被銷毀。該鉤子在服務(wù)器端渲染期間不被調(diào)用 |
生命周期圖解
階段一:創(chuàng)建和掛載
beforecreated:el 和 data 并未初始化 created:完成了 data 數(shù)據(jù)的初始化,el沒有 beforeMount:完成了 el 和 data 初始化 mounted :完成掛載
階段二:更新
在 chrome console 執(zhí)行以下命令:
app.message= 'yes !! I do';
beforeUpdate:虛擬 DOM 中根據(jù) data 變化去更新 html
updated:將虛擬 DOM 更新完成的 HTML 更新到頁面中
階段三:銷毀
在 chrome console 執(zhí)行以下命令:
app.$destroy();
beforeDestroy:銷毀之前調(diào)用
destroyed:銷毀之后調(diào)用,之后再執(zhí)行app.message= ‘hello vue’,頁面不會(huì)同步更新。
常用選項(xiàng)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之Helloworld</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> {{message}} <div>價(jià)格: {{newPrice}}</div> <div>數(shù)字: {{count}}</div> <div><button @click="add(2)">add</button></div> <div><input v-model="question"></div> <div>過濾: {{filtera | filterA}}</div> </div> <script type="text/javascript"> // 額外臨時(shí)加入時(shí),用于顯示日志 var addLog={ updated:function(){ console.log("數(shù)據(jù)放生變化,變化成"+this.count+"."); } } // 擴(kuò)展 var extendObj ={ created: function(){ console.log("我是被擴(kuò)展出來的"); } } // 實(shí)例化vue var app = new Vue({ // 掛載實(shí)例 el:'#app', // 頁面數(shù)據(jù)初始化,字符,對(duì)象、數(shù)組 data:{ message: 'hello Vue!', price: 100, count: 100, question: '', filtera: 'abc' }, // 計(jì)算屬性:主要是對(duì)原數(shù)據(jù)進(jìn)行改造輸出。 // 改造輸出:包括格式化數(shù)據(jù)(價(jià)格,日期),大小寫轉(zhuǎn)換,排序,添加符號(hào) computed: { newPrice () { return '¥' + this.price + '元'; } }, // 方法聲明:用于綁定html中的方法 methods:{ add (num) { this.count += num; } }, // data屬性監(jiān)聽器, 作用v-model watch: { question(val, oldVal) { console.log('new: %s, old: %s', val, oldVal); } }, // 過濾器,通常格式化字符,使用傳值 filters: { filterA(value) { return value.toUpperCase(); } }, // 混入,作用:減少代碼污染、減少代碼量、實(shí)現(xiàn)代碼重用 mixins: [addLog], // 擴(kuò)展 extends: extendObj }) </script> </body> </html>
1、computed 計(jì)算屬性、改造輸出
計(jì)算屬性:主要是對(duì)原數(shù)據(jù)進(jìn)行改造輸出。
改造輸出:包括格式化數(shù)據(jù)(價(jià)格,日期),大小寫轉(zhuǎn)換,排序,添加符號(hào)。
computed: { newPrice () { return '¥' + this.price + '元'; } }
2、methods 用于綁定 html 中的事件對(duì)應(yīng)的方法
方法屬性:用于綁定 html 中的事件對(duì)應(yīng)的方法
methods:{ add (num) { this.count += num; } }
3、watch 數(shù)據(jù)變化監(jiān)聽器
數(shù)據(jù)變化監(jiān)聽器:主要用于監(jiān)測(cè) data 中的數(shù)據(jù)變化, v-model 生效
watch: { question(val, oldVal) { console.log('new: %s, old: %s', val, oldVal); } }
4、filters 過濾器:通常格式化字符,使用傳值
filters: { filterA(value) { return value.toUpperCase(); } }
5、mixins 實(shí)現(xiàn)代碼重用
混入:用于減少代碼污染、減少代碼量、實(shí)現(xiàn)代碼重用
// 額外臨時(shí)加入時(shí),用于顯示日志 var addLog={ updated:function(){ console.log("數(shù)據(jù)放生變化,變化成"+this.count+"."); } } // 實(shí)例化vue var app = new Vue({ // 掛載實(shí)例 el:'#app', // 頁面數(shù)據(jù)初始化,字符,對(duì)象、數(shù)組 data:{ count: 100 }, // 混入 mixins: [addLog] })
6、extends 擴(kuò)展:對(duì)構(gòu)造器進(jìn)行擴(kuò)展
// 擴(kuò)展 var extendObj ={ created: function(){ console.log("我是被擴(kuò)展出來的"); } } // 實(shí)例化vue var app = new Vue({ // 掛載實(shí)例 el:'#app', // 頁面數(shù)據(jù)初始化,字符,對(duì)象、數(shù)組 data:{ }, // 擴(kuò)展 extends: extendObj })
實(shí)例事件
vue 有實(shí)例屬性,實(shí)例方法,實(shí)例事件,前兩個(gè)跟選項(xiàng)類似,不是很常用,這次只講實(shí)例事件。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之Helloworld</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> <div>數(shù)字:{{count}}</div> <button onclick="reduce()">on調(diào)用</button> <button onclick="reduceOnce()">once調(diào)用</button> <button onclick="off()">off調(diào)用</button> </div> <script type="text/javascript"> var app = new Vue({ el:'#app', data:{ count: 1 } }) // $on 在構(gòu)造器外部添加事件 app.$on('reduce',function(){ console.log('執(zhí)行了reduce()'); this.count--; }); // 調(diào)用 function reduce() { // 事件調(diào)用 console.log('emit事件調(diào)用'); app.$emit('reduce'); } // $once執(zhí)行一次的事件 app.$once('reduceOnce',function(){ console.log('只執(zhí)行一次的方法'); this.count--; }); // 調(diào)用 function reduceOnce() { app.$emit('reduceOnce'); } // 關(guān)閉事件 function off(){ console.log('關(guān)閉事件'); app.$off('reduce'); } </script> </body> </html>
1、$on(在構(gòu)造器外部添加事件)
$on 接收兩個(gè)參數(shù),第一個(gè)參數(shù)是調(diào)用時(shí)的事件名稱,第二個(gè)參數(shù)是一個(gè)匿名方法
app.$on('reduce',function(){ console.log('執(zhí)行了reduce()'); this.count--; });
2、$once(執(zhí)行一次的事件)
app.$once('reduceOnce',function(){ console.log('只執(zhí)行一次的方法'); this.count--; });
3、$off(關(guān)閉事件)
function off(){ console.log('關(guān)閉事件'); app.$off('reduce'); }
4、$emit(事件調(diào)用)
function reduce() { // 事件調(diào)用 console.log('emit事件調(diào)用'); app.$emit('reduce'); }
自定義指令
vue 中的自定義指令通過 Vue.directive
來實(shí)現(xiàn),主要完成內(nèi)置指令不能完成的一些事情。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之自定義指令</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> <div v-test="color"> {{num}} </div> </div> <button onclick="unbindApp()">解綁</button> <script type="text/javascript"> // 解綁 function unbindApp() { app.$destroy(); } // 自定義指令 Vue.directive("test",{ //1-被綁定 bind:function (el, binding, vnode) { console.log("1-bind 被綁定"); console.log("el:",el); console.log("binding:",binding); console.log("vnode:",vnode); el.style.color = binding.value; }, //2-被插入 inserted:function (el, binding, vnode) { console.log("2-inserted 被插入"); }, //3-更新 update:function (el, binding, vnode) { console.log("3-update 更新"); }, //4-更新完成 componentUpdated:function (el, binding, vnode) { console.log("4-componentUpdated 更新完成"); }, //5-解綁 unbind:function (el, binding, vnode) { console.log("5-unbind 解綁"); } }); var app = new Vue({ el:'#app', data:{ num: 123, color:'red' } }) </script> </body> </html>
1、調(diào)試步驟
(1)chrome打開控制器查看
(2)控制臺(tái)輸入“ app.num='通過控制臺(tái)設(shè)置的新name'
”
(3)點(diǎn)擊解綁按鈕
2、參數(shù)說明
el:指令所綁定的元素,可以用來直接操作 DOM
binding: 一個(gè)對(duì)象,包含指令的很多信息
vnode::Vue編譯生成的虛擬節(jié)點(diǎn)
3、生命周期
自定義指令有五個(gè)生命周期(也叫鉤子函數(shù)),分別是 bind、inserted、update、componentUpdated、unbind
,說明如下:
1、bind:
只調(diào)用一次,指令第一次綁定到元素時(shí)調(diào)用,用這個(gè)鉤子函數(shù)可以定義一個(gè)綁定時(shí)執(zhí)行一次的初始化動(dòng)作。
2、inserted:
被綁定元素插入父節(jié)點(diǎn)時(shí)調(diào)用(父節(jié)點(diǎn)存在即可調(diào)用,不必存在于document中)
3、update:
被綁定于元素所在的模板更新時(shí)調(diào)用,而無論綁定值是否變化。
通過比較更新前后的綁定值,可以忽略不必要的模板更新。
4、componentUpdated:被綁定元素所在模板完成一次更新周期時(shí)調(diào)用。
5、unbind:只調(diào)用一次,指令與元素解綁時(shí)調(diào)用
組件基礎(chǔ)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之組件</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> <!-- 全局組件 --> <div><button-counter></button-counter></div> <!-- 局部組件 --> <div><button-inner></button-inner></div> <!-- 常規(guī)屬性傳值 --> <div><button-props here="hello" from-here="world"></button-props></div> <!-- v-bind傳值 --> <div><button-props v-bind:here="message" :from-here="message"></button-props></div> <!-- 父子組件調(diào)用 --> <div><parent></parent></div> </div> <script type="text/javascript"> // 定義全局組件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">全局組件顯示: {{ count }}</button>' }); // 子組件 var city = { template:`<div>Sichuan of China</div>` } // 父組件 var parent = { template: `<div> <p> Panda from China!</p> <city></city> </div>`, components:{ "city": city } } // 實(shí)例化 new Vue({ el: '#app', data: { message: 'hello' }, // 定義局部組件 components:{ "button-inner":{ data: function() { return { inner: 0 } }, template: '<button v-on:click="inner++">局部組件顯示: {{ inner }}</button>' }, // 取值 "button-props":{ template:`<div style="color:red;">參數(shù)1: {{ here }}:---參數(shù)2: {{fromHere}}</div>`, props:['here', 'fromHere'] }, // 組件注冊(cè) "parent": parent } }); </script> </body> </html>
1、組件注冊(cè) component
(1)全局注冊(cè)
// script Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">全局組件顯示: {{ count }}</button>' }); new Vue({ el: '#app' }); // html使用 <button-counter></button-counter>
(2)局部注冊(cè)
// script new Vue({ el: '#app', components:{ "button-inner":{ data: function() { return { inner: 0 } }, template: '<button v-on:click="inner++">局部組件顯示: {{ inner }}</button>' } } }); // html使用 <button-inner></button-inner>
2、props 屬性傳值
(1)屬性取值
// script new Vue({ el: '#app', components:{ "button-props":{ template:`<div style="color:red;">參數(shù)1: {{ here }}:---參數(shù)2: {{fromHere}}</div>`, props:['here', 'fromHere'] } } }); // html使用 <button-props here="hello" from-here="world"></button-props>
PS:如果屬性帶 “-”,props
中需要駝峰取值
(2)在構(gòu)造器向組件傳值(v-bind)
// script new Vue({ el: '#app', data: { message: 'hello' }, components:{ "button-props":{ template:`<div style="color:red;">參數(shù)1: {{ here }}:---參數(shù)2: {{fromHere}}</div>`, props:['here', 'fromHere'] } } }); // html使用 <button-props v-bind:here="message" :from-here="message"></button-props>
3、父子組件
// script // 子組件 var city = { template:`<div>Sichuan of China</div>` } // 父組件 var parent = { template: `<div> <p> Panda from China!</p> <city></city> </div>`, components:{ "city": city } } // 實(shí)例化 new Vue({ el: '#app', // 定義局部組件 components:{ // 組件注冊(cè) "parent": parent } }); // html使用 <parent></parent>
制作模板
vue 中的模板使用 template 來實(shí)現(xiàn)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入門之組件</title> <script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script> </head> <body> <div id="app"> <!-- template標(biāo)簽?zāi)0?--> <template id="demo2"> <h2 style="color:red">我是template標(biāo)簽?zāi)0?lt;/h2> </template> </div> <!-- script標(biāo)簽?zāi)0?--> <script type="x-template" id="demo3"> <h2 style="color:red">我是script標(biāo)簽?zāi)0?lt;/h2> </script> <script type="text/javascript"> // 實(shí)例化 new Vue({ el: '#app', data: { message: 'hello' }, // 選項(xiàng)模板 //template:`<h1 style="color:red">我是選項(xiàng)模板</h1>` //template:'#demo2' template:'#demo3' }); </script> </body> </html>
1、選項(xiàng)模板
<div id="app"> </div> <script type="text/javascript"> // 實(shí)例化 new Vue({ el: '#app', data: { message: 'hello' }, template:`<h1 style="color:red">我是選項(xiàng)模板</h1>` }); </script>
2、標(biāo)簽?zāi)0?/strong>
<div id="app"> <template id="demo2"> <h2 style="color:red">我是template標(biāo)簽?zāi)0?lt;/h2> </template> </div> <script type="text/javascript"> // 實(shí)例化 new Vue({ el: '#app', data: { message: 'hello' }, template:'#demo2' }); </script>
3、<script> 標(biāo)簽?zāi)0?/strong>
<div id="app"> </div> <script type="x-template" id="demo3"> <h2 style="color:red">我是script標(biāo)簽?zāi)0?lt;/h2> </script> <script type="text/javascript"> // 實(shí)例化 new Vue({ el: '#app', data: { message: 'hello' }, template:'#demo3' }); </script>
插槽 slot
插槽,也就是 slot,是組件的一塊HTML模板,一個(gè) slot 最核心的兩個(gè)問題是顯示不顯示和怎樣顯示。
1、單個(gè) slot
單個(gè)插槽,別名默認(rèn)插槽、匿名插槽,不用設(shè)置 name 屬性。
<div id="app"> <children1> <span>12345</span> </children1> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', components: { children1: { template: "<button><slot></slot>單個(gè)插槽</button>" } } }); </script>
2、具名 slot
插槽加了 name 屬性,就變成了具名插槽。
具名插槽可以在一個(gè)組件中出現(xiàn) N 次,出現(xiàn)在不同的位置。
<div id="app"> <children2> <span slot="first" @click="tobeknow">12345</span> <span slot="second">56789</span> </children2> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', methods: { tobeknow: function () { console.log("It is the parent's method"); } }, components: { children2: {//這個(gè)無返回值,不會(huì)繼續(xù)派發(fā) template: "<button><slot name='first'></slot>具名插槽,<slot name='second'></slot></button>" } } }); </script>
3、作用域 slot
vue2.5 版本中 slot-scope 取代了 scope,來實(shí)現(xiàn)作用域插槽,主要用在組件調(diào)用中,具體在 template 標(biāo)簽上面使用 slot-scope 來獲取插槽 slot 上面的屬性值,獲取值的為一個(gè)對(duì)象,slot-scope=”它可以取任意字符串”,在 element-ui 的組件中經(jīng)??吹?。
<div id="app"> <!-- 將數(shù)據(jù)傳遞給組件 --> <tb-list :data="data"> <!-- 獲取slot上面的值 --> <template slot-scope="scope"> <p>索引:{{JSON.stringify(scope)}}</p> <p>索引:{{scope.$index}}</p> <p>姓名:{{scope.row.name}}</p> <p>年齡: {{scope.row.age}}</p> <p>性別: {{scope.row.sex}}</p> </template> </tb-list> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { data: [{ name: 'kongzhi1', age: '29', sex: 'man' }] }, components: { // 作用域slot 'tb-list': { template: `<ul> <li v-for="(item, index) in data"> <slot :row="item" :$index="index"></slot> </li> </ul>`, // 獲取值 props: ['data'] } } }); </script>
Vue 項(xiàng)目中應(yīng)用 vue-router
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構(gòu)建單頁面應(yīng)用變得易如反掌。
包含的功能有:
- 嵌套的路由/視圖表、
- 模塊化的、基于組件的路由配置、
- 路由參數(shù)、查詢、通配符、
- 基于 Vue.js 過渡系統(tǒng)的視圖過渡效果、
- 細(xì)粒度的導(dǎo)航控制、
- 帶有自動(dòng)激活的 CSS class 的鏈接、
- HTML5 歷史模式或 hash 模式,在 IE9 中自動(dòng)降級(jí)、
- 自定義的滾動(dòng)條行為
快速入門
vue-router 是 vue 官方的路由解決方案,簡(jiǎn)單易用,中文官方地址如下:vue-router 中文手冊(cè)
安裝
vue-router 是一個(gè)插件包,需要用 npm 來進(jìn)行安裝的。如果采用 vue-cli 構(gòu)建初始化項(xiàng)目會(huì)提示安裝,也可以自己使用命令安裝:
npm install vue-router --save
解讀核心文件
用 vue-cli 構(gòu)建項(xiàng)目之后,在 src/router/index.js
文件中,看到以下的路由核心文件:
// 引入vue框架 import Vue from 'vue' // 引入vue-router路由依賴 import Router from 'vue-router' // 引入頁面組件,命名為 HelloWorld import HelloWorld from '@/components/HelloWorld' // Vue全局使用Router Vue.use(Router) // 定義路由配置 export default new Router({ routes: [ //配置路由,這里是個(gè)數(shù)組 { //每一個(gè)鏈接都是一個(gè)對(duì)象 path: '/', //鏈接路徑 name: 'HelloWorld', //路由名稱, component: HelloWorld //對(duì)應(yīng)的組件模板 } ] })
使用
在系統(tǒng)入口文件 main.js
中注入 router
,代碼如下:
// 引入vue框架 import Vue from 'vue' // 引入根組件 import App from './App' // 引入路由配置 import router from './router' // 關(guān)閉生產(chǎn)模式下給出的提示 Vue.config.productionTip = false // 定義實(shí)例 new Vue({ el: '#app', router, // 注入框架中 components: { App }, template: '<App/>' })
路由屬性配置說明
代碼如下:
export default new Router({ mode: 'history', //路由模式,取值為history與hash base: '/', //打包路徑,默認(rèn)為/,可以修改 routes: [ { path: string, //路徑 ccomponent: Component; //頁面組件 name: string; // 命名路由-路由名稱 components: { [name: string]: Component }; // 命名視圖組件 redirect: string | Location | Function; // 重定向 props: boolean | string | Function; // 路由組件傳遞參數(shù) alias: string | Array<string>; // 路由別名 children: Array<RouteConfig>; // 嵌套子路由 beforeEnter?: (to: Route, from: Route, next: Function) => void; // 路由單獨(dú)鉤子 meta: any; // 自定義標(biāo)簽屬性,比如:是否需要登錄 icon: any; // 圖標(biāo) // 2.6.0+ caseSensitive: boolean; // 匹配規(guī)則是否大小寫敏感?(默認(rèn)值:false) pathToRegexpOptions: Object; // 編譯正則的選項(xiàng) } ] })
頁面跳轉(zhuǎn)
一、router-link 標(biāo)簽跳轉(zhuǎn)
在 html 標(biāo)簽內(nèi)使用 router-link 跳轉(zhuǎn),相應(yīng)于超鏈接 a 標(biāo)簽,使用方式如下:
<router-link to="/">[顯示字段]</router-link>
to:導(dǎo)航路徑
使用示例如下:
<p>導(dǎo)航 : <router-link to="/">首頁</router-link> <router-link to="/hello">hello</router-link> </p>
二、編程式導(dǎo)航-JS代碼內(nèi)部跳轉(zhuǎn)
實(shí)際項(xiàng)目中,很多時(shí)候都是通過在JS代碼內(nèi)部進(jìn)行導(dǎo)航的跳轉(zhuǎn),使用方式如下:
this.$router.push('/xxx')
具體的簡(jiǎn)單用法:
(1)先編寫一個(gè)按鈕,在按鈕上綁定 goHome( ) 方法。
<button @click="goHome">回到首頁</button>
(2)在 <script>
模塊里加入 goHome 方法,并用 this.$router.push(‘/’)
導(dǎo)航到首頁
export default { name: 'app', methods: { goHome(){ this.$router.push('/home'); } } }
三、其他常用方法
// 后退一步記錄,等同于 history.back() this.$router.go(-1) // 在瀏覽器記錄中前進(jìn)一步,等同于 history.forward() this.$router.go(1)
子路由-路由嵌套
子路由,也叫路由嵌套,采用在 children
后跟路由數(shù)組來實(shí)現(xiàn),數(shù)組里和其他配置路由基本相同,需要配置 path
和 component
,然后在相應(yīng)部分添加 <router-view/>
來展現(xiàn)子頁面信息,相當(dāng)于嵌入 iframe
。
1、src/components/Home.vue(父頁面)
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 添加子路由導(dǎo)航 --> <p>導(dǎo)航 : <router-link to="/home">首頁</router-link> | <router-link to="/home/one">-子頁面1</router-link> | <router-link to="/home/two">-子頁面2</router-link> </p> <!-- 子頁面展示部分 --> <router-view/> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Home Page!' } } } </script> <style scoped> </style>
2、src/components/One.vue(子頁面1)
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'One', data () { return { msg: 'Hi, I am One Page!' } } } </script> <style scoped> </style>
3、src/components/Two.vue(子頁面2)
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'Two', data () { return { msg: 'Hi, I am Two Page!' } } } </script> <style scoped> </style>
4、src/router/index.js(路由配置)
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import One from '@/components/One' import Two from '@/components/Two' Vue.use(Router) export default new Router({ routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' }, { path: '/home', // 主頁路由 name: 'Home', component: Home, children:[ // 嵌套子路由 { path:'one', // 子頁面1 component:One }, { path:'two', // 子頁面2 component:Two }, ] } ] })
路由傳遞參數(shù)
1、通過 <router-link>
標(biāo)簽中的 to
傳參
基本語法:
<router-link :to="{name:xxx, params: {key:value}}"> valueString </router-link>
PS:上面 to
前邊是帶冒號(hào),后邊跟的是一個(gè)對(duì)象形勢(shì)的字符串
name:在路由配置文件中起的 name 值。叫做命名路由,下一節(jié)會(huì)講到。
params:要傳的參數(shù),它是對(duì)象形式,在對(duì)象里可以傳遞多個(gè)值。
具體實(shí)例如下:
(1)在 src/components/Home.vue
里面導(dǎo)航中添加如下代碼:
<router-link :to="{name: 'one', params:{username:'test123'}}"> 子頁面1 </router-link>
(2)在 src/router/indes.js
中添加如下代碼,重點(diǎn)是 name:
{ path:'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component:One }
(3)在 src/components/One.vue
里面接受參數(shù),代碼如下:
<h2>{{$route.params.username}}</h2>
2、url 中傳遞參數(shù)
(1)在路由中以冒號(hào)傳遞,在 src/router/index.js
中加入如下代碼:
{ path:'/home/two/:id/:name', // 子頁面2 component:Two },
(2)接受參數(shù),在 src/components/Two.vue
中加入如下代碼:
<p>ID:{{ $route.params.id}}</p> <p>名稱:{{ $route.params.name}}</p>
(3)路由跳轉(zhuǎn),在 src/components/Home.vue
中加入如下代碼:
<router-link to="/home/two/1/張三">子頁面2</router-link>
PS:to 前沒有冒號(hào)為字符串路由,必須全部匹配。
(4)如果路由參數(shù)需要有特定的規(guī)則,就需要加入正則表達(dá)式了,示例如下:
{ path:'/home/two/:id(\\d+)/:name', // 子頁面2 component:Two }
源碼 E:\node\vue296\src\router\index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import One from '@/components/One' import Two from '@/components/Two' Vue.use(Router) export default new Router({ routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' }, { path: '/home', // 主頁路由 name: 'Home', component: Home, children: [ // 嵌套子路由 { path: 'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component: One }, { path: '/home/two/:id/:name', // 子頁面2 component: Two }, ] } ] })
E:\node\vue296\src\components\Two.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <p>ID:{{ $route.params.id}}</p> <p>名稱:{{ $route.params.name}}</p> </div> </template> <script> export default { name: 'Two', data () { return { msg: 'Hi, I am Two Page!' } } } </script> <style scoped> </style>
E:\node\vue296\src\components\Home.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 添加子路由導(dǎo)航 --> <p>導(dǎo)航 : <router-link to="/home">首頁</router-link> | <router-link to="/home/one">-子頁面1</router-link> | <router-link to="/home/two">-子頁面2</router-link> <br> <router-link :to="{name: 'one', params:{username:'test123'}}">子頁面1傳遞參數(shù)</router-link> <br> <router-link to="/home/two/1/張三">子頁面2</router-link> </p> <!-- 子頁面展示部分 --> <router-view/> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Home Page!' } } } </script> <style scoped> </style>
編程式導(dǎo)航 -params 傳遞參數(shù)
(1)在 src/router/index.js
頁面加入如下代碼:
{ path:'/home/three', // 子頁面3 name: 'three', component:Three }
(2)在 src/components/Three.vue
頁面加入如下代碼:
<p>ID:{{ $route.params.id}}</p> <p>名稱:{{ $route.params.name}}</p>
(3)在 src/components/Home.vue
中加入如下代碼:
// template <button @click="toThreePage">頁面3-params傳參</button> // script methods: { toThreePage() { this.$router.push({name: 'three', params: {id: 1, name: 'zhangsan'}}) } }
說明:
A、動(dòng)態(tài)路由使用 params 傳遞參數(shù),在 this.$router.push()
方法中 path
不能和 params
一起使用,否則 params
將無效。需要用 name
來指定頁面。
B、以上方式參數(shù)不會(huì)顯示到瀏覽器的地址欄中,如果刷新一次頁面,就獲取不到參數(shù)了,改進(jìn)方式將第一部中的代碼改成如下:
{ path:'/home/three/:id/:name', // 子頁面3 name: 'three', component:Three }
源碼 E:\node\vue296\src\router\index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import One from '@/components/One' import Two from '@/components/Two' import Three from '@/components/Three' Vue.use(Router) export default new Router({ routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' }, { path: '/home', // 主頁路由 name: 'Home', component: Home, children: [ // 嵌套子路由 { path: 'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component: One }, { path: '/home/two/:id/:name', // 子頁面2 component: Two }, { path:'/home/three/:id/:name', // 子頁面3 name: 'three', component:Three } ] } ] })
E:\node\vue296\src\components\Three.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <p>ID:{{ $route.params.id}}</p> <p>名稱:{{ $route.params.name}}</p> </div> </template> <script> export default { name: 'Three', data () { return { msg: 'Hi, I am Three Page!' } } } </script> <style scoped> </style>
E:\node\vue296\src\components\Home.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 添加子路由導(dǎo)航 --> <p>導(dǎo)航 : <router-link to="/home">首頁</router-link> | <router-link to="/home/one">-子頁面1</router-link> | <router-link to="/home/two">-子頁面2</router-link> <br> <router-link :to="{name: 'one', params:{username:'test123'}}">子頁面1傳遞參數(shù)</router-link> <br> <router-link to="/home/two/1/張三">子頁面2</router-link> <br> <button @click="toThreePage">頁面3-params傳參</button> </p> <!-- 子頁面展示部分 --> <router-view/> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Home Page!' } }, methods: { toThreePage() { this.$router.push({name: 'three', params: {id: 1, name: 'zhangsan'}}) } } } </script> <style scoped> </style>
編程式導(dǎo)航 -query 傳遞參數(shù)
(1)在 src/router/index.js
頁面加入如下代碼:
{ path:'/home/three', // 子頁面3 name: 'three', component:Three }
(2)在 src/components/Three.vue
頁面加入如下代碼:
<p>ID:{{ $route.query.id}}</p> <p>名稱:{{ $route.query.name}}</p>
(3)在 src/components/Home.vue
中加入如下代碼:
// template <button @click="toThreePage">頁面3-params傳參</button> // script methods: { toThreePage() { this.$router.push({path: '/home/three', query: {id: 1, name: 'zhangsan'}}) } }
PS:動(dòng)態(tài)路由使用 query 傳遞參數(shù),會(huì)顯示到瀏覽器地址欄中,
以上鏈接為 /home/three?id=1&name=zhangsan
。
源碼
E:\node\vue296\src\router\index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import One from '@/components/One' import Two from '@/components/Two' import Three from '@/components/Three' Vue.use(Router) export default new Router({ routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' }, { path: '/home', // 主頁路由 name: 'Home', component: Home, children: [ // 嵌套子路由 { path: 'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component: One }, { path: '/home/two/:id/:name', // 子頁面2 component: Two }, { path:'/home/three', // 子頁面3 name: 'three', component:Three } ] } ] })
E:\node\vue296\src\components\Three.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <p>ID:{{ $route.query.id}}</p> <p>名稱:{{ $route.query.name}}</p> </div> </template> <script> export default { name: 'Three', data () { return { msg: 'Hi, I am Three Page!' } } } </script> <style scoped> </style>
E:\node\vue296\src\components\Home.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- 添加子路由導(dǎo)航 --> <p>導(dǎo)航 : <router-link to="/home">首頁</router-link> | <router-link to="/home/one">-子頁面1</router-link> | <router-link to="/home/two">-子頁面2</router-link> <br> <router-link :to="{name: 'one', params:{username:'test123'}}">子頁面1傳遞參數(shù)</router-link> <br> <router-link to="/home/two/1/張三">子頁面2</router-link> <br> <button @click="toThreePage">頁面3-params傳參</button> </p> <!-- 子頁面展示部分 --> <router-view/> </div> </template> <script> export default { name: 'Home', data () { return { msg: 'Home Page!' } }, methods: { toThreePage() { this.$router.push({path: '/home/three', query: {id: 1, name: 'zhangsan'}}) } } } </script> <style scoped> </style>
命名路由-命名視圖-重定向-別名
1、命名路由
給一個(gè)路由命一個(gè)唯一的名稱,然后跳轉(zhuǎn)調(diào)用這個(gè)名稱即可。
(1)在 src/router/index.js
中加一個(gè)帶 name
的路由,代碼如下:
{ path: 'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component: One // 頁面組件 }
(2)在 src/component/Home.vue
頁面中調(diào)用,代碼如下:
// template跳轉(zhuǎn)調(diào)用 <router-link :to="{name: 'one'}">子頁面1</router-link> // router.push函數(shù)跳轉(zhuǎn)調(diào)用 router.push({ name: 'user'}})
2、命名視圖
在同一個(gè)頁面展示多個(gè)視圖,如果不用嵌套,只能采用命名視圖來實(shí)現(xiàn)了。
代碼如下:
(1)在 src/router/index.js
中,代碼如下:
import Vue from 'vue' import Router from 'vue-router' // 創(chuàng)建頁面組件 const Header = { template: '<div>Header</div>' } const Left = { template: '<div>Left</div>' } const Right = { template: '<div>Right</div>' } Vue.use(Router) export default new Router({ routes: [ { path: '/', // 主頁路由 components: { default: Header, a: Left, b: Right } } ] })
(2)在 src/App.vue
中,代碼如下:
<template> <div id="app"> <router-view /> <router-view name="a" class="left" /> <router-view name="b" class="right" /> </div> </template> <script> export default { name: 'App' } </script> <style> #app { text-align: center; color: #2c3e50; width: 500px; border: 1px solid red; margin: 0 auto; } .left,.right{ float: left; width:48%; text-align: center; border:1px solid red } </style>
PS:經(jīng)過實(shí)踐,命名視圖只能放在最頂級(jí)的頁面中,即第一步中的代碼不能放在其他頁面中。
3、重定向
重定向是通過 route 的配置中關(guān)鍵詞 redirect 來實(shí)現(xiàn)的,具體代碼如下:
(1)在 src/router/index.js
中,代碼如下:
export default new Router({ routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' // 重定向 }, { path: '/home', // 主頁路由 component: Home, children:[ // 嵌套子路由 { path:'/home/two/:id/:name', // 子頁面2 component:Two }, { path:'/home/three/:id/:name', // 子頁面3 name: 'three', // 路由名稱-命名路由 redirect: '/home/two/:id/:name' // 重定向-傳遞參數(shù) }, ] } ] })
(2)在 src/components/Home.vue
中,代碼如下:
<router-link to="/">首頁</router-link> | <router-link to="/home/two/1/lisi">子頁面2</router-link> | <router-link :to="{name: 'three', params: {id: 1, name: 'zhangsan'}}"> 子頁面3 </router-link>
說明1-不帶參數(shù)的重定向:
redirect: '/home' // 重定向-不帶參數(shù)
說明2-帶參數(shù)的重定向:
redirect: '/home/two/:id/:name' // 重定向-傳遞參數(shù)
4、別名
重定向是通過 route 的配置中關(guān)鍵詞 alias 來實(shí)現(xiàn)的,具體代碼如下:
(1)在 src/router/index.js
中,代碼如下:
{ path:'/one', // 子頁面1 component:One, alias: '/oneother' }
(2)在 src/components/Home.vue
中,代碼如下:
<router-link to="/oneother">子頁面1</router-link>
說明1:redirect 和 alias 的區(qū)別
redirect:直接改變了 url 的值,把 ur l變成了真實(shí)的 path 路徑。\
alias:
url 路徑?jīng)]有別改變,這種更友好,讓用戶知道自己訪問的路徑,只是改變了 <router-view>
中的內(nèi)容。
說明2:別名請(qǐng)不要用在 path 為 ’/’
中,如下代碼的別名是不起作用的。
<router-link to="/oneother">子頁面1</router-link>
過渡動(dòng)畫
(1)在 <router-view>
標(biāo)簽的外部添加 <transition>
標(biāo)簽,標(biāo)簽還需要一個(gè) name
屬性,代碼如下:
<transition name="fade" mode="out-in"> <router-view /> </transition>
過渡模式 mode
in-out:新元素先進(jìn)入過渡,完成之后當(dāng)前元素過渡離開,默認(rèn)模式。
out-in:當(dāng)前元素先進(jìn)行過渡離開,離開完成后新元素過渡進(jìn)入。
(2)加入CSS,一共4個(gè)CSS類名,四個(gè)類名與 transition
的 name
屬性有關(guān),比如name=”fade”
,相應(yīng)的 css 如下:
/*頁面切換動(dòng)畫*/ /*進(jìn)入過渡的結(jié)束狀態(tài),元素被插入時(shí)就生效,在過渡過程完成后移除*/ .fade-enter-active { transition: opacity .5s; } /*進(jìn)入過渡的開始狀態(tài),元素被插入時(shí)生效,只應(yīng)用一幀后立刻刪除*/ .fade-enter { opacity: 0; } /*離開過渡的開始狀態(tài),元素被刪除時(shí)觸發(fā),只應(yīng)用一幀后立刻刪除*/ .fade-leave { opacity: 1; } /*離開過渡的結(jié)束狀態(tài),元素被刪除時(shí)生效,離開過渡完成后被刪除*/ .fade-leave-active { opacity:0; transition: opacity .5s; }
文件:E:\node\vue296\src\App.vue
<template> <div id="app"> <img src="./assets/logo.png"> <transition name="fade" mode="out-in"> <router-view /> </transition> </div> </template> <script> export default { name: 'App' } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } /*頁面切換動(dòng)畫*/ /*進(jìn)入過渡的結(jié)束狀態(tài),元素被插入時(shí)就生效,在過渡過程完成后移除*/ .fade-enter-active { transition: opacity .5s; } /*進(jìn)入過渡的開始狀態(tài),元素被插入時(shí)生效,只應(yīng)用一幀后立刻刪除*/ .fade-enter { opacity: 0; } /*離開過渡的開始狀態(tài),元素被刪除時(shí)觸發(fā),只應(yīng)用一幀后立刻刪除*/ .fade-leave { opacity: 1; } /*離開過渡的結(jié)束狀態(tài),元素被刪除時(shí)生效,離開過渡完成后被刪除*/ .fade-leave-active { opacity:0; transition: opacity .5s; } </style>
mode 與 404
1、mode 模式
代碼示例:
export default new Router({ mode: 'history', //mode模式 routes: [...] })
mode取值說明:
(1)histroy:URL就像正常的 url,示例:http://localhost:8080/home
(2) hash:默認(rèn)值,會(huì)多一個(gè) “#”,示例:http://localhost:8080/#/home
2、404頁面設(shè)置
如果訪問的路由不存在,或者用戶輸入錯(cuò)誤時(shí),會(huì)有一個(gè)404友好的提示頁面,配置如下:
(1)在 /src/router/index.js
中加入如下代碼:
// 404 { path: '*', component: () => import('@/components/404') }
(2)在 src/components/404.vue
中編寫如下代碼:
<template> <div class="hello"> <h1>404 not found</h1> </div> </template> <script> export default { data () { return { } } } </script> <style scoped> </style>
路由鉤子
路由鉤子,即導(dǎo)航鉤子,其實(shí)就是路由攔截器,vue-router 一共有三類:
1、全局鉤子:最常用
2、路由單獨(dú)鉤子
3、組件內(nèi)鉤子
1、全局鉤子
在 src/router/index.js
中使用,代碼如下:
// 定義路由配置 const router = new VueRouter({ ... }) // 全局路由攔截-進(jìn)入頁面前執(zhí)行 router.beforeEach((to, from, next) => { // 這里可以加入全局登陸判斷 // 繼續(xù)執(zhí)行 next(); }); // 全局后置鉤子-常用于結(jié)束動(dòng)畫等 router.afterEach(() => { //不接受next }); export default router;
每個(gè)鉤子方法接收三個(gè)參數(shù):
to: Route : 即將要進(jìn)入的目標(biāo) [路由對(duì)象]
from: Route : 當(dāng)前導(dǎo)航正要離開的路由
next: Function : 繼續(xù)執(zhí)行函數(shù)
next():繼續(xù)執(zhí)行 next(false):中斷當(dāng)前的導(dǎo)航。 next(‘/‘) 或 next({ path: ‘/‘ }):跳轉(zhuǎn)新頁面,常用于登陸失效跳轉(zhuǎn)登陸
2、路由單獨(dú)鉤子
使用:在路由配置中單獨(dú)加入鉤子,在 src/router/index.js
中使用,代碼如下:
{ path:'/home/one', // 子頁面1 component: One, // 路由內(nèi)鉤子 beforeEnter: (to, from, next) => { console.log('進(jìn)入前執(zhí)行'); next(); } }
3、組件內(nèi)鉤子
使用:在路由組件內(nèi)定義鉤子函數(shù):
beforeRouteEnter:進(jìn)入頁面前調(diào)用 beforeRouteUpdate (2.2 新增):頁面路由改變時(shí)調(diào)用,一般需要帶參數(shù) beforeRouteLeave:離開頁面調(diào)用
任意找一頁面,編寫如下代碼:
<script> export default { name: 'Two', data () { return { msg: 'Hi, I am Two Page!' } }, // 進(jìn)入頁面前調(diào)用 beforeRouteEnter(to, from, next) { console.log('進(jìn)入enter路由鉤子') next() }, // 離開頁面調(diào)用 beforeRouteLeave(to,from, next){ console.log('進(jìn)入leave路由鉤子') next() }, // 頁面路由改變時(shí)調(diào)用 beforeRouteUpdate(to, from, next) { console.log('進(jìn)入update路由鉤子') console.log(to.params.id) next() } } </script>
路由懶加載
1、路由正常模式:
// 1、先引入頁面組件 import Home from '@/components/Home' // 2、使用組件 { path: '/home', component: Home }
2、懶加載模式
大項(xiàng)目中,為了提高初始化頁面的效率,路由一般使用懶加載模式,一共三種實(shí)現(xiàn)方式。
(1)第一種寫法:
component: (resolve) => require(['@/components/One'], resolve)
(2)第二種寫法:
component: () => import('@/components/Two')
(3)第三種寫法:
components: r => require.ensure([], () => r(require('@/components/Three')), 'group-home')
PS:
一般常用第二種簡(jiǎn)寫
第三種中,’group-home’
是把組件按組分塊打包, 可以將多個(gè)組件放入這個(gè)組中,在打包的時(shí)候 Webpack 會(huì)將相同 chunk 下的所有異步模塊打包到一個(gè)異步塊里面。
路由懶加載用法:E:\node\vue296\src\router\index.js
import Vue from 'vue' import Router from 'vue-router' import Home from '@/components/Home' import One from '@/components/One' import Two from '@/components/Two' import Three from '@/components/Three' Vue.use(Router) export default new Router({ mode: 'history', //mode模式 routes: [ { path: '/', // 默認(rèn)頁面重定向到主頁 redirect: '/home' }, { path: '/home', // 主頁路由 name: 'Home', component: Home, children: [ // 嵌套子路由 { path: 'one', // 子頁面1 name: 'one', // 路由名稱-命名路由 component: One }, { path: '/home/two/:id/:name', // 子頁面2 component: Two }, { path:'/home/three', // 子頁面3 name: 'three', component:Three } ] }, { path: '*', component: () => import('@/components/404') } ] })
vuex 背景引言
1、vuex是什么?
vuex是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的 狀態(tài)管理模式
。
它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
chrome 安裝調(diào)試工具 devtools extension
。
2、單向數(shù)據(jù)流
示意圖說明:
State:驅(qū)動(dòng)應(yīng)用的數(shù)據(jù)源(單向數(shù)據(jù)流)
View:以聲明方式將 state 映射到視圖(靜態(tài)顯示出來的數(shù)據(jù)源)
Actions:處理用戶在 view 上面操作而導(dǎo)致的狀態(tài)變化(數(shù)據(jù)源變化追蹤)
一個(gè)簡(jiǎn)單的 demo 案例:E:\node\vue296\src\router\index.js
// 引入組件 import HelloWorld from '@/components/HelloWorld' // 添加路由 { path: '/hello', name: 'HelloWorld', component: HelloWorld, }
E:\node\vue296\src\components\Home.vue
首頁
<!-- 添加跳轉(zhuǎn) --> <router-link to="/hello">Hello頁</router-link>
E:\node\vue296\src\components\HelloWorld.vue
案例頁
<template> <div> <!-- view --> <div>{{ count }}</div> <button @click="increment">increment</button> </div> </template> <script> export default { // state data () { return { count: 0 } }, // actions methods: { increment () { this.count++ } } } </script> <style scoped> </style>
3、vuex 解決的問題
多個(gè)視圖組件,包括父子組件,兄弟組件之間的狀態(tài)共享。
不同視圖組件的行為需要變更同一個(gè)狀態(tài)。
4、vuex 使用場(chǎng)景
中大型單頁應(yīng)用,需要考慮如何更好地在組件外部管理狀態(tài),簡(jiǎn)單應(yīng)用不建議使用。
5、vuex 與全局變量的區(qū)別
響應(yīng)式:
vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的,當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)得到高效更新。
不能直接改變store:
不能直接改變 store 的變化,改變 store 中狀態(tài)的唯一途徑是 commit mutation,方便于跟蹤每一個(gè)狀態(tài)的變化。
6、vuex 核心流程
示意圖說明:
1、Vue Components Vue組件:
HTML頁面上,負(fù)責(zé)接收用戶操作等交互行為,執(zhí)行 dispatch 方法觸發(fā)對(duì)應(yīng) action 進(jìn)行回應(yīng)。
2、Dispatch:操作行為觸發(fā)方法,是唯一能執(zhí)行 action 的方法。
3、Actions 操作行為處理模塊:
負(fù)責(zé)處理 Vue Components 接收到的所有交互行為。
包含同步/異步操作,支持多個(gè)同名方法,按照注冊(cè)的順序依次觸發(fā)。
向后臺(tái)API請(qǐng)求的操作就在這個(gè)模塊中進(jìn)行,包括觸發(fā)其他 action 以及提交 mutation 的操作。該模塊提供了 Promise 的封裝,以支持 action 的鏈?zhǔn)接|發(fā)。
4、Commit 態(tài)改變提交操作方法:
狀對(duì) mutation 進(jìn)行提交,是唯一能執(zhí)行 mutation 的方法。
5、Mutations 狀態(tài)改變操作方法:
是 Vuex 修改 state 的唯一推薦方法,其他修改方式在嚴(yán)格模式下將會(huì)報(bào)錯(cuò)。
該方法只能進(jìn)行同步操作,且方法名只能全局唯一。
操作之中會(huì)有一些 hook 暴露出來,以進(jìn)行 state 的監(jiān)控等。
6、State 頁面狀態(tài)管理容器對(duì)象:
集中存儲(chǔ) Vue components 中 data 對(duì)象的零散數(shù)據(jù),全局唯一,以進(jìn)行統(tǒng)一的狀態(tài)管理。頁面顯示所需的數(shù)據(jù)從該對(duì)象中進(jìn)行讀取,利用Vue的細(xì)粒度數(shù)據(jù)響應(yīng)機(jī)制來進(jìn)行高效的狀態(tài)更新。
7、Getters:state對(duì)象讀取方法。
圖中沒有單獨(dú)列出該模塊,應(yīng)該被包含在了render 中,Vue Components 通過該方法讀取全局 state 對(duì)象。
總結(jié)說明:
Vue 組件接收交互行為,調(diào)用 dispatch 方法觸發(fā) action 相關(guān)處理,若頁面狀態(tài)需要改變,則調(diào)用 commit 方法提交 mutation 修改 state,通過 getters 獲取到 state 新值,重新渲染Vue Components,界面隨之更新。
入門示例
安裝
PS E:\node\vue296> npm install --save vuex@3.6.2 npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"}) + vuex@3.6.2 removed 1 package and updated 1 package in 8.474s PS E:\node\vue296>
(1)新建 src/vuex/store.js 中寫入以下代碼:
// 引入vue import Vue from 'vue' // 引入vuex import Vuex from 'vuex' // 使用vuex Vue.use(Vuex) // 1、state:創(chuàng)建初始化狀態(tài) const state = { // 放置初始狀態(tài) count: 1 } // 2、mutations:創(chuàng)建改變狀態(tài)的方法 const mutations = { // 狀態(tài)變更函數(shù)-一般大寫 ADD (state, n) { state.count += n; } } // 3、getters:提供外部獲取state const getters = { count: function(state){ return state.count; } } // 4、actions:創(chuàng)建驅(qū)動(dòng)方法改變mutations const actions ={ // 觸發(fā)mutations中相應(yīng)的方法-一般小寫 add ({commit}, data) { commit('ADD', data) } } // 5、全部注入Store中 const store = new Vuex.Store({ state, mutations, getters, actions }); // 6、輸出store export default store;
代碼說明:
state - mutations - getters - actions - store,以上寫法基本固定。
小型項(xiàng)目用上面的簡(jiǎn)單管理狀態(tài)即可。
(2)src/main.js 代碼中添加
import Vue from 'vue' import App from './App' import router from './router' // 引入store import store from './vuex/store' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, store, // 全局注入 components: { App }, template: '<App/>' })
(3)src/compontent/Count.vue 頁面組件中代碼如下:
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{count}}</h2> <button @click="clickAdd">新增</button> </div> </template> <script> export default { data () { return { msg: 'Vuex test!' } }, computed: { // 獲取 state 值 count() { return this.$store.state.count; } }, methods: { clickAdd() { //分發(fā)action中的add方法 this.$store.dispatch('add', 1); } } } </script> <style scoped> </style>
state-狀態(tài)對(duì)象的獲取方法
1、在組件的 template 中直接使用
<h2>{{ $store.state.count }}</h2>
2、在計(jì)算屬性 computed 中直接賦值
// 方式1:直接獲取 computed: { count() { // this指的是main.js中的vue實(shí)例對(duì)象 return this.$store.state.count; } }
3、通過 mapState 的對(duì)象來賦值
// 方式2:利用mapState computed: mapState({ // es5寫法 count: function (state) { return state.count; }, // es6寫法 count: state => state.count })
4、通過 mapState 的數(shù)組來賦值
// 方式3:數(shù)組獲取 computed: mapState(['count'])
5、通過 mapState 的 JSON 來賦值
// 方式4:JSON獲取 computed: mapState({ count: 'count' })
PS:一般 4 和 5 兩種比較常用
完整示例代碼:E:\node\vue296\src\components\Count.vue
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{ $store.state.count }}</h2> <h2>{{count}}</h2> <button @click="clickAdd">新增</button> </div> </template> <script> import {mapState} from 'vuex' export default { data () { return { msg: 'Vuex test!' } }, // 方式1:在計(jì)算屬性computed中直接賦值 // computed: { // count() { // // this指的是main.js中的vue實(shí)例對(duì)象 // return this.$store.state.count; // } // }, // 方式2:通過mapState的對(duì)象來賦值 // computed: mapState({ // // es5 // // count: function (state) { // // return state.count; // // }, // // es6 // count: state => state.count // }), // 方式3:通過mapState的對(duì)象來賦值 // computed: mapState(['count']), // 方式4:通過mapState的JSON來賦值 computed: mapState({ count: 'count' }), methods: { clickAdd() { //分發(fā)action中的add方法 this.$store.dispatch('add', 1); } } } </script> <style scoped> </style>
mutations - getters - actions 異步 1、mutations(修改狀態(tài))
(1)template 中直接使用 $store.commit( )
觸發(fā)
// template <button @click="$store.commit('ADD')">+</button> // src/vuex/store.js const mutations = { // 狀態(tài)變更函數(shù) ADD (state) { state.count++; } }
(2)利用 mapMutations
引入觸發(fā)
<template> <div class="hello"> <h1>{{ msg }}</h1> <h2>{{count}}</h2> <!-- 3、、直接調(diào)用相應(yīng)的方法 --> <button @click="ADD">+</button> </div> </template> <script> // 1、引入mapMutations import {mapState, mapMutations} from 'vuex' export default { data () { return { msg: 'Vuex test!' } }, // 通過mapState的JSON來賦值 computed: mapState({ count: 'count' }), // 2、methods中加入mapMutations methods: mapMutations([ 'ADD' ]) } </script> <style scoped> </style>
2、getters(獲取state和過濾)
(1)基本用法
// src/vuex/store.js const getters = { count: function(state){ // 返回加上100 return state.count + 100; } }
(2)常規(guī)獲取值
computed: { // 獲取getters count(){ return this.$store.getters.count; } }
(3)mapGetters 獲取值
// 1、引入mapMutations import {mapState, mapMutations, mapGetters} from 'vuex' // 2、使用 computed: { // 獲取getters ...mapGetters(["count"]) }
3、actions(異步狀態(tài)修改)
actions 和 mutations 功能基本一樣,不同點(diǎn)是,actions 是異步的改變 state 狀態(tài),而mutations 是同步改變狀態(tài)。
不過實(shí)際項(xiàng)目中一般都是通過 actions 改變 mutations 中的值。
(1)store.js 中增加異步代碼
// src/vuex/store.js const actions ={ // 觸發(fā)mutations中相應(yīng)的方法 add ({commit}) { // 增加異步 setTimeout(()=>{ commit('ADD') },3000); console.log('我比reduce提前執(zhí)行'); } }
(2)常規(guī)使用
// template <button @click="add">+</button> // script methods: { add() { //分發(fā)action this.$store.dispatch('add'); } }
(3)mapActions 的使用
// template <button @click="add">+</button> // script // 引入mapActions import {mapState, mapActions} from 'vuex' // 使用mapActions methods: { ...mapActions(['add']) }
傳遞參數(shù)
在 vuex 的方法調(diào)用傳遞參數(shù),只需要在 mutations 和 actions 相應(yīng)的地方加上參數(shù),然后調(diào)用的時(shí)候傳入即可。
(1)src/vuex/store.js
中
// actions中傳遞參數(shù) const mutations = { ADD (state, n) { state.count += n; } } // actions中傳遞參數(shù) const actions ={ // 觸發(fā)mutations中相應(yīng)的方法 add ({commit}, n) { // 增加異步 setTimeout(()=>{ commit('ADD', n); },3000); console.log('我比reduce提前執(zhí)行'); } }
(2)頁面組件常規(guī)調(diào)用傳遞
// template <button @click="add">+</button> // script methods: { add() { // 分發(fā)action this.$store.dispatch('add', 99); } }
(3)頁面組件使用 mapActions 調(diào)用傳遞
// template <button @click="add(99)">+</button> // script methods: { ...mapActions(['add']) }
module-模塊組
當(dāng)應(yīng)用非常復(fù)雜,狀態(tài)非常多的時(shí)候,需要將 store 分割成模塊(module)。
每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊,從上至下進(jìn)行同樣方式的分割。
1、大致的結(jié)構(gòu)
// 模塊A const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } // 模塊B const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } // 組裝 const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) // 取值 store.state.a // -> moduleA 的狀態(tài) store.state.b // -> moduleB 的狀態(tài)
2、詳細(xì)示例
實(shí)際開發(fā)中建議把 module 分開編寫。
(1)src/vuex/module1.js
// 模塊1 const module1 = { // 初始化狀態(tài) state: { module1: { name: '模塊1' } }, // 編寫動(dòng)作 mutations: { CHANGE1 (state, data) { state.module1 = data; } }, // 取值 getters: { module1: function(state){ return state.module1; } }, // 創(chuàng)建驅(qū)動(dòng),可異步 actions: { change1 ({commit}, data) { commit('CHANGE1', data) } } } export default module1;
(2)src/vuex/module2.js
// 模塊2 const module2 = { // 初始化狀態(tài) state: { module2: { name: '模塊2' } }, // 編寫動(dòng)作 mutations: { CHANGE2 (state, data) { state.module2 = data; } }, // 取值 getters: { module2: function(state){ return state.module2; } }, // 創(chuàng)建驅(qū)動(dòng),可異步 actions: { change2 ({commit}, data) { commit('CHANGE2', data) } } } export default module2;
(3)src/vuex/store.js
// 引入vue import Vue from 'vue' // 引入vuex import Vuex from 'vuex' // 引入module1 import module1 from '@/vuex/module1' // 引入module2 import module2 from '@/vuex/module2' // 使用vuex Vue.use(Vuex) // 模塊注入 const store = new Vuex.Store({ modules: { a: module1, b: module2 } }) // 輸出store export default store;
(4)組件中使用,src/compontent/one.vue
<template> <div id="app"> <!-- module1 --> <h2>{{ module1.name }}</h2> <button @click="change1({'name': 'change1'})">module1改變</button> <!-- module2 --> <h2>{{ module2.name }}</h2> <button @click="change2({'name': 'change2'})">module2改變</button> </div> </template> <script> // 引入快捷方法 import {mapState, mapGetters, mapActions} from 'vuex' export default { name: 'app', data () { return { } }, computed:{ // mapState取值 // ...mapState({ // module1: state => state.a.module1.name, // module2: state => state.b.module2.name // }) // mapGetter取值 ...mapGetters(['module1', 'module2']) }, methods: { // mapAction取方法 ...mapActions([ 'change1', 'change2' ]) } } </script> <style> </style>
PS:module 中命名要唯一,不然獲取值和改變值的時(shí)候會(huì)沖突,目前親測(cè) mapGetters 只能獲取對(duì)象。
總結(jié)
到此這篇關(guān)于Vue命令行工具Vue-CLI圖文的文章就介紹到這了,更多相關(guān)Vue命令行工具Vue-CLI內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vant遇到van-sidebar數(shù)據(jù)超出不能滑動(dòng)的問題
這篇文章主要介紹了vant遇到van-sidebar數(shù)據(jù)超出不能滑動(dòng)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue中Class和Style實(shí)現(xiàn)v-bind綁定的幾種用法
項(xiàng)目開發(fā)中給元素添加/刪除 class 是非常常見的行為之一, 例如網(wǎng)站導(dǎo)航都會(huì)給選中項(xiàng)添加一個(gè) active 類用來區(qū)別選與未選中的樣式,那么在 vue 中 我們?nèi)绾翁幚磉@類的效果呢?下面我們就一起來了解一下2021-05-05vue.js高德地圖實(shí)現(xiàn)熱點(diǎn)圖代碼實(shí)例
這篇文章主要介紹了vue.js高德地圖實(shí)現(xiàn)熱點(diǎn)圖,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04vue3中Fragment特性的一個(gè)bug需要注意事項(xiàng)
這篇文章主要介紹了vue3中Fragment特性的一個(gè)bug,需要留意的注意事項(xiàng)示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01vscode中vue-cli項(xiàng)目es-lint的配置方法
本文主要介紹vscode中 vue項(xiàng)目es-lint的配置方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的的朋友參考下吧2018-07-07Vue項(xiàng)目打包問題詳解(生產(chǎn)環(huán)境樣式失效)
在Vue開發(fā)過程中,項(xiàng)目的打包是一個(gè)非常重要的步驟,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目打包問題(生產(chǎn)環(huán)境樣式失效)的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12Vue學(xué)習(xí)筆記進(jìn)階篇之過渡狀態(tài)詳解
本篇文章主要介紹了Vue學(xué)習(xí)筆記進(jìn)階篇之過渡狀態(tài)詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-07-07