Vue學習總結(Vue基礎,VueCli3,VueRouter,Vuex)
目錄
-
vue基礎知識(1-13)
- vue 引入,實例化
- vue 數據 & 方法
- vue 綁定(:)
- vue 事件(@)
- vue 事件修飾符(.once.prevent.stop等)
- vue 按鍵修飾符(@keyup.alt.enter)
- vue 數據雙向綁定(ref,v-model)
- vue 計算屬性computed
- vue 動態綁定css樣式
- vue v-if & v-show
- vue v-for
- vue 實例化多個Vue對象
- vue 初識組件的應用
-
運用腳手架及組件知識(14-21)
- 腳手架初識
- SRC文件
- 組件嵌套
- 組件CSS作用域
- 屬性傳值Props(父組件向子組件傳值)
- 傳值和傳引用
- 事件傳值(子組件to父組件)
- Vue生命周期(鉤子函數)
-
vue路由知識點(22-32)
- Vue 路由和HTTP
- Vue 只用 Bootstrap4 中的樣式
- 路由跳轉
- 路由小細節(redirect和tag)
- 路由name屬性及跳轉方法
- 路由嵌套
- 導航守衛(全局守衛)
- 導航守衛(路由獨享-組件內守衛)
- 復用router-view
- 路由控制滾動行為
- 跨域
-
vue-cli3新特性(33-37)
- 項目搭建及介紹
- 新出的添加插件方法
- 全局環境變量的使用
- 獨立運行.vue文件
- 圖形頁面構建項目
-
vuex基礎知識(38-43)
- State
- Getter
- Mutation
- Action
- mapMutations & mapActions
- Module
basics
1.vue引入,實例化
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
let vue-app = new Vue({
...
})
2.vue數據 & 方法
// 數據
data(){
data1:'xxx'
},
// 方法
methods: {
methodName(){
return this.data1;
}
}
<button @click='methodName'>點擊</button>
<!-- 或者 -->
<div>{{ methodName() }}</div>
方法中用data中的屬性,直接使用this.*
,不用this.data.*
3.vue綁定(v-bind:
, :
, v-html:
)
(1)屬性綁定(用 v-bind:
或 :
)
website: 'https://github.com/'
<a v-bind:href="website">websit</a>
<!-- 或者簡寫 -->
<a :href="website">websit</a>
(2)標簽綁定(用v-html:
)
websiteTag: "<a
<!-- 正確 -->
<p v-html="websiteTag">websit</a>
<!-- 錯誤 -->
{{ websiteTag }}
<!-- 顯示如下 -->
<!-- <a >websit</a> -->
4.vue事件(用 v-on:
或 @
)
? 綁定事件里方法不傳參可以不加括號仍然識別為方法,但在{{}}里一定要寫括號才會識別為方法
eg: 傳參單擊雙擊事件
methods: {
add: function(val){
this.age += val;
},
dec: function(val){
this.age -= val;
},
}
<button v-on:click='add(1)'>加一歲</button>
<button @click='dec(1)'>減一歲</button>
<button v-on:dblclick='add(10)'>加十歲</button>
<button @dblclick='dec(10)'>減十歲</button>
5.vue事件修飾符(.once.prevent.stop等)
在事件處理程序中調用 event.preventDefault()
或 event.stopPropagation()
是非常常見的需求。盡管我們可以在方法中輕松實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。
為了解決這個問題,Vue.js 為 v-on 提供了事件修飾符。之前提過,修飾符是由點開頭的指令后綴來表示的。
- .stop
- .prevent
- .capture
- .self
- .once
- .passive
<!-- 阻止單擊事件繼續傳播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重載頁面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修飾符可以串聯 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修飾符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件監聽器時使用事件捕獲模式 -->
<!-- 即元素自身觸發的事件先在此處理,然后才交由內部元素進行處理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只當在 event.target 是當前元素自身時觸發處理函數 -->
<!-- 即事件不是從內部元素觸發的 -->
<div v-on:click.self="doThat">...</div>
? 使用修飾符時,順序很重要;相應的代碼會以同樣的順序產生。因此,用 v-on:click.prevent.self 會阻止所有的點擊,而 v-on:click.self.prevent 只會阻止對元素自身的點擊。
6.vue按鍵修飾符(@keyup.alt.enter)
在監聽鍵盤事件時,我們經常需要檢查詳細的按鍵。Vue 允許為 v-on 在監聽鍵盤事件時添加按鍵修飾符:
<!-- 只有在 `key` 是 `Enter` 時調用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
你可以直接將 KeyboardEvent.key 暴露的任意有效按鍵名轉換為 kebab-case 來作為修飾符。
<input v-on:keyup.page-down="onPageDown">
在上述示例中,處理函數只會在 $event.key 等于 PageDown 時被調用。
? 按鍵碼 keyCode 的事件用法已經被廢棄了并可能不會被最新的瀏覽器支持。
使用 keyCode 特性也是允許的:
<input v-on:keyup.13="submit">
為了在必要的情況下支持舊瀏覽器,Vue 提供了絕大多數常用的按鍵碼的別名:
- .enter
- .tab
- .delete (捕獲“刪除”和“退格”鍵)
- .esc
- .space
- .up
- .down
- .left
- .right
7.vue數據雙向綁定(ref,v-model)
方法一
<input ref='name' type="text" @keyup='logName'>
this.name = this.$refs.name.value;
方法二
<input v-model='age' type="text">
8.vue計算屬性computed
methods
中的每個方法每次渲染dom都會執行 調用 {{xxx()}}
computed
中的每個方法只會在自己觸發時執行 調用 {{xxx}}
,案例中拷貝的值與虛擬dom不同,就執行。
9.vue動態綁定css樣式
<!-- active類名,isActive類值 -->
<div v-bind:class="{ active: isActive }"></div>
10.v-if & v-show
條件不成立時:v-if在dom中直接刪除元素;v-show改變class為display:none
eg:
<button @click='err=!err'>err</button>
<button @click='success=!success'>success</button>
<p v-if='err'>err</p>
<p v-else-if='success'>200</p>
<p v-show='err'>err</p>
<p v-show='success'>200</p>
11.v-for
? 記得綁定key值
data: {
users:[
{name:'hurry',age:20},
{name:'luccy',age:25},
{name:'zero',age:18},
]
},
<ul v-for='(item,index) in users' :key='index'>
<li>{{index+1}} - {{item.name}} - {{item.age}}</li>
</ul>
<!-- 會多出3個div -->
<div v-for='(item,index) in users' :key='index'>
<h2>{{item.name}}</h2>
<p>{{index+1}} - {{item.age}}</p>
</div>
<!-- 不會多出3個template -->
<template v-for='(item,index) in users' :key='index'>
<h2>{{item.name}}</h2>
<p>{{index+1}} - {{item.age}}</p>
</template>
12.實例化多個Vue對象
多個vue對象實例化
var one = new Vue({...})
var two = new Vue({...})
不同對象使用其他對象數據
one.data
eg:
var one = new Vue({
el: '#vue-app-one',
data: {
title: 'one 的內容'
},
methods: {
},
computed: {
greet:function(){
return 'hello app one';
}
},
});
var two = new Vue({
el: '#vue-app-two',
data: {
title: 'two 的內容'
},
methods: {
changeTitle:function(){
one.title = 'title one changed by app two!!!';
}
},
computed: {
greet:function(){
return 'hello app one';
}
},
});
13.vue初識組件的應用
js中:
// greeting 是組件名,可在 #vue-app-one,#vue-app-two 中使用
Vue.component("greeting",{
// 所有標簽必須在一個大標簽下
template:`
<div>
<p> {{name}}:大家好,給大家介紹一下我的朋友@關曉彤</p>
<button @click='changeName'>點我</button>
</div>
`,
// return一個對象則在組件內是私有的,不會暴露出去
data:function(){
return {
name:'鹿晗'
}
},
methods:{
changeName:function(){
this.name = this.name == '鹿晗'?'Hery':'鹿晗'
}
}
})
new Vue({
el: '#vue-app-one'
});
new Vue({
el: '#vue-app-two'
});
HTML中:
<greeting></greeting>
vue-cli
14.vue腳手架初識
部分特點
- 腳手架是通過webpack搭建的開發環境
- 使用es6語法
- 打包和壓縮js為一個文件
- 項目在環境中編譯,而不是瀏覽器
- 實現頁面自動刷新
- ...
vue-cli的使用
- 安裝 nodejs ,一般選擇安裝LTS(長期穩定版)版本。官網:https://nodejs.org/en/
# 在terminal、cmd、powershell 中 # 輸入 `node -v` 查看 node 版本號 node -v
# 輸入 `npm -v` 查看 npm 版本號 npm -v
- 安裝 cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
- 安裝 Vue CLI 3.x
npm install -g @vue/cli # OR yarn global add @vue/cli
# 輸入 `vue --version` 查看 npm 版本號 vue --version # OR vue -V
- 創建一個 Vue 項目
vue create projectName cd projectName npm run serve
# 創建項目相關幫助 vue create --help
- 運行相關
# Project setup npm install # Compiles and hot-reloads for development npm run serve # Compiles and minifies for production npm run build # Run your tests npm run test # Lints and fixes files npm run lint
- (PS)舊版本 Vue CLI 2.x
npm install -g @vue/cli-init # `vue init` 的運行效果將會跟 `vue-cli@2.x` 相同 vue init webpack my-project
15.介紹腳手架搭建的項目中SRC文件流程及根組件App
client
│ .gitignore
│ babel.config.js
│ package.json
│ README.md
│
├─public
│ favicon.ico
│ index.html
│
└─src
│ App.vue
│ main.js
│ router.js
│
├─assets
│ bg.jpg
│
└─components
Component1.vue
Component2.vue
index.html -> main.js -> App.vue ()
<!-- 模板 -->
<template></template>
<!-- 邏輯 -->
<script></script>
<!-- 樣式 -->
<style></style>
16.組件嵌套
可以在main.js中注冊全局組件
import Users from './component/Users'
Vue.component('users',Users);
也可以在某些組件中調用
<template>
<div id="app">
<Users></Users>
</div>
</template>
<script>
import Users from './components/Users'
export default {
components:{
'Users':Users
}
}
</script>
17.組件CSS作用域
<style scoped>
/* `scoped`該組件作用域內有效 */
/* 否則子組件相同選項樣式會覆蓋根組件的 */
</style>
18.屬性傳值Props(父組件向子組件傳值)
父組件:
在調用子組件的位置,綁定自己的屬性,第一個是子組件中的名稱,第二個是父組件中的名稱。
eg:
<Users :usersSon='users'></Users>
子組件:
子組件屬性 props:['usersSon'],
接收傳值。或者用標準寫法
props:{
users:{
type:Array;
requied:true;
},
position:{
type:Array;
requied:true;
},
},
eg:
<template>
<div class="users">
<ul>
<li v-for="(user,index) in usersSon" :key="index" @click="user.show = !user.show">
<h2>{{user.name}}</h2>
<h3 v-show="user.show">{{user.position}}</h3>
</li>
</ul>
</div>
</template>
<script>
export default {
name:'users',
props:['usersSon'],
}
</script>
19.傳值和傳引用
傳值:string number boolean,一處變,全部變
引用:array object,一處變,局部變
20.事件傳值(子組件to父組件)
子組件
<h1 @click="tofather">{{title1}} {{title}}</h1>
<script>
export default {
methods: {
tofather: function(){
this.$emit('changed','son to father') //第1個參數是事件名,第2個參數是傳遞的值
}
},
}
</script>
父組件
<Header @changed='update($event)' :title="title"></Header>
<!-- $event不能改 -->
<script>
export default {
methods: {
update:function(title){
this.title = title;
}
},
}
</script>
21.Vue生命周期(鉤子函數)
作用:可以找錯誤,可以解決需求
生命周期圖示(紅色為生命周期函數):
// 8個鉤子函數與 methods 并列。
// 創建對象之前(比如加載動畫)
beforeCreate(){}
// 創建vue對象
new Vue()
// 組件創建成功,屬性已經綁定,dom還未生成(比如獲取數據,待會兒展示到dom,結束加載)
created(){}
// 檢查 el 或者 new({...}).$mount('#app) ,都沒有則生命周期結束
// 檢查有沒 template 或者 outerHTML ,都沒有則生命周期結束
// 開始編譯模板 template 里的內容,掛載前,虛擬dom中執行,看不到
beforeMount(){}
// el 中已經放入 template ,編譯結束,此方法執行后,頁面顯示
mounted(){}
// 組件更新之前
beforeUpdate(){}
// 組件更新之后
updated(){}
// 組件銷毀之前
beforeDestroy(){}
// 組件銷毀之后
destroyed(){}
router
22.Vue路由和HTTP
(1) 安裝路由模塊及引入
npm install vue-router --save
router.js中
import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home.vue'
import HelloWorld from './components/HelloWorld.vue'
Vue.use(Router);
export default new Router({
mode: 'history', // 沒有#符號
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/helloworld',
name: '',
component: HelloWorld
}
]
})
main.js中
import router from './router';
new Vue({
router,
...
});
App.vue
<ul>
<li><a href="/">Home</a></li>
<li><a href="/helloworld">Hello</a></li>
<!-- 或者 -->
<li><router-link to="/">Home</router-link></li>
<li><router-link to="/helloworld">Hello</router-link></li>
</ul>
<router-view></router-view>
(2) HTTP
安裝依賴:
npm i vue-resource --save
使用:
main.js中
import VueResource from 'vue-resource';
Vue.use(VueResource);
Home.vue中
created(){
this.$http.get('http://jsonplaceholder.typicode.com/users')
.then((data)=>{
// console.log(data);
this.users = data.body;
})
},
23.vue中只用 Bootstrap4 中的樣式
index.html中引入
<link rel="stylesheet" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
24.路由跳轉
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/Home'
import About from './components/about/About'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{path:'/',component:Home},
{path:'/about',component:About},
]
})
Header.vue
<router-link to="/about"></router-link>
App.vue
<router-view></router-view>
25.路由小細節(redirect和tag)
Header.vue
<!-- 默認a標簽 -->
<router-link to="/about"></router-link>
<!-- 修改為div標簽 -->
<router-link tag='div' to="/about"></router-link>
<!-- 動態綁定屬性路由 -->
<router-link tag='div' :to="router"></router-link>
<script>
export default {
data(){
return{
router:'/'
}
}
}
</script>
router.js
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{path:'/',component:Home},
{path:'/about',component:About},
{path:'*',redirect:'/'}, //錯誤輸入重定向
]
})
26.路由name屬性及跳轉方法
name
{path:'/',name:'homelink',component:Home},
<!-- 注意這幾個符號 : {} " '' " -->
<li><router-link :to="{name:'homelink'}" class="nav-link">主頁</router-link></li>
跳轉
<button @click="goOlder" class='btn btn-success'>goOlder</button>
<button @click="goMenu" class='btn btn-success'>goMenu</button>
<button @click="goAdmin" class='btn btn-success'>goAdmin</button>
<script>
export default {
methods:{
goOlder(){
this.$router.go(-1); // 到前一個頁面
},
goMenu(){
// this.$router.replace('/menu'); // replace到指定路由頁面
this.$router.push('/menu'); // push到指定路由頁面
},
goAdmin(){
// this.$router.replace({name:'adminLink'}); // 到指定 name 頁面
this.$router.push({name:'adminLink'}); // 到指定 name 頁面
},
}
}
</script>
27.路由嵌套
router.js
{path:'/about',name:'aboutLink',redirect:'/about/histoey',component:About,
// 二級路由
children:[
{path:'/about/histoey',name:'historyLink',component:History},
{path:'/about/contact',name:'contactLink',redirect:'/phone',component:Contact,children:[
// 三級路由
{path:'/phone',name:'phoneNum',component:Phone},
{path:'/personname',name:'personName',component:Personname},
]},
{path:'/about/orderingguide',name:'orderingGuideLink',component:OrderingGuide},
{path:'/about/delivery',name:'deliveryLink',component:Delivery},
]},
about.vue
<!-- 導航的內容 -->
<router-view></router-view>
28.導航守衛(全局守衛)
學習地址(https://router.vuejs.org/zh/guide/advanced/navigation-guards.html)
main.js中
// 全局守衛
router.beforeEach((to,from,next) => {
if(to.path == '/login' || to.path == '/register'){
next()
}else{
alert("還沒有登錄,請先登錄!");
next('/login');
}
})
29.導航守衛(路由獨享-組件內守衛)
后置鉤子(不常用)
router.afterEach((to,from) => {
alert("after each")
})
路由獨享的守衛
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
組件內的守衛
- beforeRouteEnter
- beforeRouteUpdate (2.2 新增)
- beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 因為當守衛執行前,組件實例還沒被創建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被復用時調用
// 舉例來說,對于一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
}
}
beforeRouteEnter 守衛 不能 訪問 this,因為守衛在導航確認前被調用,因此即將登場的新組件還沒被創建。
不過,你可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通過 `vm` 訪問組件實例
})
}
注意 beforeRouteEnter 是支持給 next 傳遞回調的唯一守衛。對于 beforeRouteUpdate 和 beforeRouteLeave 來說,this 已經可用了,所以不支持傳遞回調,因為沒有必要了。
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
這個離開守衛通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過 next(false) 來取消。
beforeRouteLeave (to, from , next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
beforeRouteLeave(to,from,next){
if(confirm('確認離開嗎?') == true){
next()
}else{
next(false)
}
}
30.復用router-view
router.js修改
{path:'/',name:'homeLink',component:Home,},
為
// 注意 components 的 s
{path:'/',name:'homeLink',components:{
default:Home,
'history':History,
'orderingGuide':OrderingGuide,
'delivery':Delivery
}},
App.vue添加
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-4">
<router-view name="history"></router-view>
</div>
<div class="col-sm-12 col-md-4">
<router-view name="orderingGuide"></router-view>
</div>
<div class="col-sm-12 col-md-4">
<router-view name="delivery"></router-view>
</div>
</div>
</div>
31.路由控制滾動行為
router.js中
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 期望滾動到哪個的位置
}
})
eg:
scrollBehavior (to, from, savedPosition) {
// return {x:0,y:100}; // 滾動到(0,100)
// return {selector:'.btn'}; // 滾動到 第一個.btn
// 瀏覽器返回上一頁面時,回到上次瀏覽的位置
if(savedPosition){
return savedPosition
}else{
return {x:0,y:0}
}
}
32.跨域
(0)預設
通過vue-cli3.x版本構建的項目使用proxy和以前的項目不同,而且3.x版本構建的時候可以選用typescript了。下面記錄一下如何使用proxy跨域。
首先在根目錄創建vue.config.js文件,這個配置文件在運行項目的時候自動加載。
// vue.config.js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://xxxx/device/', //對應自己的接口
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
這個文件還可以配置其它信息,比如修改端口號,默認是8080等等。
最后在頁面發送請求的時候:
axios.get('/api/getDataPoint').then(res => {
console.log(res)
})
示例如下:
(1)預設
proxyTable:{
' /apis': {
//測試環境
target:'http://www.thenewstep.cn/', //接口域名
change0rigin:true, //是否跨域
pathRewrite: {
'^/apis':'' //需要rewrite重寫的,
}
}
},
(2)fetch
created(){
// fetch
fetch("/apis/test/testToken. php", {
method:"post",
headers: {
"Content-type" :"application/json",
"token" : "f4c902c9ae5a2a9d8f84868ad064e706"
},
body: JSON.stringify({username: "henry" , password :"321321"})
})
. then( result =>{
// console. log( result)
return result. json()
})
. then(data => {
console. log ( data)
})
}
(3)axios
main.js
import axios from 'axios'
axios.defaults.headers.common[ 'token '] = "f4c902c9ae5a2a9d8f84868ad064e706"
axios.defaults.headers.post ["Content-type"] = "application/j son"
Vue.prototype.$axios = axios
App.vue
this.$axios.post("/apis/test/testToken.php" , {username :"hello",password :"123456"})
.then(data => {
console. log(data)
})
(4) 示例二加載美團外賣數據json
將包含 goods.json
,ratings.json
,seller.json
三個文件的 data
文件夾放到根目錄下
還是vue.config.js
文件
const goods = require(' ./data/goods.json');
const ratings = require(' ./data/ratings.json');
const seller = require(' ./data/seller.json');
module.exports = {
//baseUrl: './', //根路徑 //"baseUrl" option in vue.config.js is deprecated now, please use "publicPath" instead.
publicPath: './', //根路徑
outputDir: 'dist2', //構建輸出目錄
assetsDir: 'assets', //靜態資源目錄(js, css, img, fonts )
lintOnSave: false, //是否開啟eslint保存檢測,有效值: true || false || ' error'
devServer: {
open: true, // 瀏覽器自動開啟
host: 'localhost', // 主機地址'127.0.0.0','0.0.0.0'也可以
port: 8081, // 端口號
https: false, // 是否啟動https,啟動會警告
hot0nly: false, // 熱更新,默認false
proxy: {
//配置跨域
'/api': {
target: 'http//localhost:5000/api/',
ws: true,
chang0rigin: true,
pathRewrite: {
'^/api': ''
}
}
}
},
before(app) {
// http: //loca lhost: 8081/api/goods
app.get('/api/goods', (req, res) => {
res. json(goods) ;
});
app.get( '/api/ratings', (req, res) => {
res. json(ratings);
});
app.get( '/api/seller', (req, res) => {
res. json(seller);
});
}
};
vuecli3
33.Vue-Cli3.0-項目搭建及介紹
找到腳手架的github倉庫:https://github.com/vuejs/vue-cli
打開docs文件夾,拉到最后,按照步驟安裝
Install:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
Create a project:
vue create my-project
# OR
vue ui
Run a project
cd my-project
npm run serve
34.Vue-Cli3.0-新出的添加插件方法
- 原來的插件安裝方法
npm install <plugin> --save
- 新方法
會有一些文件替換的插件(比如vue add <plugin>
vuetify
)會有提示,建議用該方法
35.Vue-Cli3.0-全局環境變量的使用
全局環境
根路徑下創建.env
文件,設置全局環境變量,比如:
VUE_APP_XXX = XXX
在需要的組件內
<script>
export default{
data(){
return{
url: process.env.VUE_APP_XXX
}
}
}
</script>
.env
數據變化要重新啟動項目
開發環境
根路徑下創建.env.development
文件,設置開發環境變量,比如:
VUE_APP_XXX = XXX
npm run serve
時用該文件的值。
生產環境
根路徑下創建.env.production
文件,設置開發環境變量,比如:
VUE_APP_XXX = XXX
npm run build
時用該文件的值。
36.Vue-Cli3.0-獨立運行.vue文件
npm install -g @vue/cli-service-global
vue serve XXX.vue
37.Vue-Cli3.0-圖形頁面構建項目
vue ui
打開GUI地址,進入圖形頁面,開始構建項目。
創建新項目:詳情->預設->功能->配置
創建時 terminal 窗口會繼續運行
創建好后gui界面會有:插件,依賴,配置,任務(serve,build,inspect) 4個菜單。
vuex
38.State(Vuex-搭建Vuex中央狀態管理 & Vuex-使用computed獲取store數據)
Vuex
Centralized State Management for Vue.js.
src
目錄下新建 store
文件夾,下面新建 index.js
文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export const store = new Vuex.Store({
state:{
products:[
{name:'馬云',price:'200'},
{name:'馬化騰',price:'140'},
{name:'馬冬梅',price:'20'},
{name:'馬蓉',price:'10'},
]
}
})
main.js
中引入
import {store} from './store'
new Vue({
store,
...
}
組建中使用,computed
屬性獲取 store
中數據
<li v-for="product in products" :key='product'>
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
<script>
export default{
computed: {
products(){
return this.$store.state.products
}
},
}
</script>
39.Getter
index.js
文件中,新增 getters
屬性,里面放其他組件可以調用的方法
export const store = new Vuex.Store({
state:{
products:[
{name:'馬云',price:'200'},
{name:'馬化騰',price:'140'},
{name:'馬冬梅',price:'20'},
{name:'馬蓉',price:'10'},
]
},
getters:{
saleProducts:(state)=>{
var saleProducts = state.products.map(product =>{
return{
name: "**" + product.name + "**" ,
price: product.price / 2
}
});
return saleProducts;
}
}
})
組件對 store
中方法的調用
<li v-for="product in saleProducts" :key='product'>
<span class="name">{{product.name}}</span>
<span class="price">${{product.price}}</span>
</li>
<script>
export default{
computed: {
saleProducts(){
return this.$store.getters.saleProducts;
}
},
}
</script>
40.Mutation
谷歌瀏覽器添加插件Vue.js devtools,可以跟蹤vuex狀態
更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,并且它會接受 state 作為第一個參數。
store/index.js
中添加 mutations
屬性
mutations:{
reducePriceV:state=>{
state.products.forEach(product =>{
product.price -= 1;
})
}
}
組建中調用方法 reducePriceV
<button @click="reducePrice">降價</button>
<script>
export default {
methods: {
reducePrice(){
this.$store.commit('reducePriceM') // mutations中的方法
}
},
}
</script>
41.Action
Action 類似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接變更狀態。
- Action 可以包含任意異步操作。(vuex調試器中方法和變化同時出來)
注冊action
Action 函數接受一個與 store 實例具有相同方法和屬性的 context
對象,因此你可以調用 context.commit
提交一個 mutation,或者通過 context.state
和 context.getters
來獲取 state 和 getters。
組件觸發action
Action 通過 store.dispatch
方法觸發
接收第二個參數 payload
eg:
store/index.js
中添加 actions
屬性
actions:{
reducePriceA:context=>{
setTimeout(function(){
context.commit('reducePriceM')
},2000)
}
}
組建中調用方法 reducePriceM
<button @click="reducePrice">降價</button>
<script>
export default {
methods: {
reducePrice(){
this.$store.dispatch('reducePriceA') // actions中的方法
}
},
}
</script>
42.Vuex-mapMutations & mapActions
在組件中提交 Mutation
你可以在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 輔助函數將組件中的 methods 映射為 store.commit 調用(需要在根節點注入 store)。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 將 `this.increment()` 映射為 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 將 `this.add()` 映射為 `this.$store.commit('increment')`
})
}
}
在組件中分發 Action
你在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions 輔助函數將組件的 methods 映射為 store.dispatch 調用(需要先在根節點注入 store):
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')`
// `mapActions` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射為 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 將 `this.add()` 映射為 `this.$store.dispatch('increment')`
})
}
}
43.Module
由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)。每個模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態