筆記
腳手架檔案結構
├── node_modules
├── public
│ ├── favicon.ico: 頁簽圖示
│ └── index.html: 首頁面
├── src
│ ├── assets: 存放靜态資源
│ │ └── logo.png
│ │── component: 存放元件
│ │ └── HelloWorld.vue
│ │── App.vue: 彙總所有元件
│ │── main.js: 入口檔案
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置檔案
├── package.json: 應用包配置檔案
├── README.md: 應用描述檔案
├── package-lock.json:包版本控制檔案
關于不同版本的Vue
- vue.js與vue.runtime.xxx.js的差別:
- vue.js是完整版的Vue,包含:核心功能 + 模闆解析器。
- vue.runtime.xxx.js是運作版的Vue,隻包含:核心功能;沒有模闆解析器。
- 因為vue.runtime.xxx.js沒有模闆解析器,是以不能使用template這個配置項,需要使用render函數接收到的createElement函數去指定具體内容。
vue.config.js配置檔案
- 使用vue inspect > output.js可以檢視到Vue腳手架的預設配置。
- 使用vue.config.js可以對腳手架進行個性化定制,詳情見:https://cli.vuejs.org/zh
ref屬性
- 被用來給元素或子元件注冊引用資訊(id的替代者)
- 應用在html标簽上擷取的是真實DOM元素,應用在元件标簽上是元件執行個體對象(vc)
- 使用方式:
- 打辨別:
或<h1 ref="xxx">.....</h1>
<School ref="xxx"></School>
- 擷取:
this.$refs.xxx
props配置項
- 功能:讓元件接收外部傳過來的資料
- 傳遞資料:
<Demo name="xxx"/>
- 接收資料:
- 第一種方式(隻接收):
props:['name']
- 第二種方式(限制類型):
props:{name:String}
- 第三種方式(限制類型、限制必要性、指定預設值):
props:{
name:{
type:String, //類型
required:true, //必要性
default:'老王' //預設值
}
}
備注:props是隻讀的,Vue底層會監測你對props的修改,如果進行了修改,就會發出警告,若業務需求确實需要修改,那麼請複制props的内容到data中一份,然後去修改data中的資料。
mixin(混入)
- 功能:可以把多個元件共用的配置提取成一個混入對象
-
使用方式:
第一步定義混合:
{
data(){....},
methods:{....}
....
}
第二步使用混入:
全局混入:
Vue.mixin(xxx)
局部混入:
mixins:['xxx']
插件
- 功能:用于增強Vue
- 本質:包含install方法的一個對象,install的第一個參數是Vue,第二個以後的參數是插件使用者傳遞的資料。
- 定義插件:
對象.install = function (Vue, options) {
// 1. 添加全局過濾器
Vue.filter(....)
// 2. 添加全局指令
Vue.directive(....)
// 3. 配置全局混入(合)
Vue.mixin(....)
// 4. 添加執行個體方法
Vue.prototype.$myMethod = function () {...}
Vue.prototype.$myProperty = xxxx
}
- 使用插件:
Vue.use()
scoped樣式
- 作用:讓樣式在局部生效,防止沖突。
- 寫法:
<style scoped>
總結TodoList案例
-
元件化編碼流程:
(1).拆分靜态元件:元件要按照功能點拆分,命名不要與html元素沖突。
(2).實作動态元件:考慮好資料的存放位置,資料是一個元件在用,還是一些元件在用:
1).一個元件在用:放在元件自身即可。
2). 一些元件在用:放在他們共同的父元件上(狀态提升)。
(3).實作互動:從綁定事件開始。
-
props适用于:
(1).父元件 ==> 子元件 通信
(2).子元件 ==> 父元件 通信(要求父先給子一個函數)
- 使用v-model時要切記:v-model綁定的值不能是props傳過來的值,因為props是不可以修改的!
- props傳過來的若是對象類型的值,修改對象中的屬性時Vue不會報錯,但不推薦這樣做。
webStorage
- 存儲内容大小一般支援5MB左右(不同浏覽器可能還不一樣)
- 浏覽器端通過 Window.sessionStorage 和 Window.localStorage 屬性來實作本地存儲機制。
- 相關API:
-
該方法接受一個鍵和值作為參數,會把鍵值對添加到存儲中,如果鍵名存在,則更新其對應的值。xxxxxStorage.setItem('key', 'value');
-
該方法接受一個鍵名作為參數,傳回鍵名對應的值。xxxxxStorage.getItem('person');
-
該方法接受一個鍵名作為參數,并把該鍵名從存儲中删除。xxxxxStorage.removeItem('key');
-
該方法會清空存儲中的所有資料。 xxxxxStorage.clear()
- 備注:
- SessionStorage存儲的内容會随着浏覽器視窗關閉而消失。
- LocalStorage存儲的内容,需要手動清除才會消失。
-
如果xxx對應的value擷取不到,那麼getItem的傳回值是null。xxxxxStorage.getItem(xxx)
-
的結果依然是null。JSON.parse(null)
元件的自定義事件
- 一種元件間通信的方式,适用于:子元件 ===> 父元件
- 使用場景:A是父元件,B是子元件,B想給A傳資料,那麼就要在A中給B綁定自定義事件(事件的回調在A中)。
- 綁定自定義事件:
- 第一種方式,在父元件中:
或<Demo @atguigu="test"/>
<Demo v-on:atguigu="test"/>
- 第二種方式,在父元件中:
<Demo ref="demo"/>
......
mounted(){
this.$refs.xxx.$on('atguigu',this.test)
}
- 若想讓自定義事件隻能觸發一次,可以使用
修飾符,或once
方法。$once
- 觸發自定義事件:
this.$emit('atguigu',資料)
- 解綁自定義事件
this.$off('atguigu')
- 元件上也可以綁定原生DOM事件,需要使用
修飾符。native
- 注意:通過
綁定自定義事件時,回調要麼配置在methods中,要麼用箭頭函數,否則this指向會出問題!this.$refs.xxx.$on('atguigu',回調)
全局事件總線(GlobalEventBus)
- 一種元件間通信的方式,适用于任意元件間通信。
- 安裝全局事件總線:
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安裝全局事件總線,$bus就是目前應用的vm
},
......
})
- 使用事件總線:
- 接收資料:A元件想接收資料,則在A元件中給$bus綁定自定義事件,事件的回調留在A元件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.$bus.$on('xxxx',this.demo)
}
- 提供資料:
this.$bus.$emit('xxxx',資料)
- 最好在beforeDestroy鈎子中,用$off去解綁目前元件所用到的事件。
消息訂閱與釋出(pubsub)
- 一種元件間通信的方式,适用于任意元件間通信。
- 使用步驟:
- 安裝pubsub:
npm i pubsub-js
- 引入:
import pubsub from 'pubsub-js'
- 接收資料:A元件想接收資料,則在A元件中訂閱消息,訂閱的回調留在A元件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.pid = pubsub.subscribe('xxx',this.demo) //訂閱消息
}
- 提供資料:
pubsub.publish('xxx',資料)
- 最好在beforeDestroy鈎子中,用
去取消訂閱。PubSub.unsubscribe(pid)
nextTick
- 文法:
this.$nextTick(回調函數)
- 作用:在下一次 DOM 更新結束後執行其指定的回調。
- 什麼時候用:當改變資料後,要基于更新後的新DOM進行某些操作時,要在nextTick所指定的回調函數中執行。
Vue封裝的過度與動畫
- 作用:在插入、更新或移除 DOM元素時,在合适的時候給元素添加樣式類名。
- 圖示:
- 寫法:
- 準備好樣式:
- 元素進入的樣式:
- v-enter:進入的起點
- v-enter-active:進入過程中
- v-enter-to:進入的終點
- 元素離開的樣式:
- v-leave:離開的起點
- v-leave-active:離開過程中
- v-leave-to:離開的終點
- 使用
包裹要過度的元素,并配置name屬性:<transition>
<transition name="hello">
<h1 v-show="isShow">你好啊!</h1>
</transition>
- 備注:若有多個元素需要過度,則需要使用:
,且每個元素都要指定<transition-group>
值。key
vue腳手架配置代理
方法一
在vue.config.js中添加如下配置:
devServer:{
proxy:"http://localhost:5000"
}
說明:
- 優點:配置簡單,請求資源時直接發給前端(8080)即可。
- 缺點:不能配置多個代理,不能靈活的控制請求是否走代理。
- 工作方式:若按照上述配置代理,當請求了前端不存在的資源時,那麼該請求會轉發給伺服器 (優先比對前端資源)
方法二
編寫vue.config.js配置具體代理規則:
module.exports = {
devServer: {
proxy: {
'/api1': {// 比對所有以 '/api1'開頭的請求路徑
target: 'http://localhost:5000',// 代理目标的基礎路徑
changeOrigin: true,
pathRewrite: {'^/api1': ''}
},
'/api2': {// 比對所有以 '/api2'開頭的請求路徑
target: 'http://localhost:5001',// 代理目标的基礎路徑
changeOrigin: true,
pathRewrite: {'^/api2': ''}
}
}
}
}
/*
changeOrigin設定為true時,伺服器收到的請求頭中的host為:localhost:5000
changeOrigin設定為false時,伺服器收到的請求頭中的host為:localhost:8080
changeOrigin預設值為true
*/
說明:
- 優點:可以配置多個代理,且可以靈活的控制請求是否走代理。
- 缺點:配置略微繁瑣,請求資源時必須加字首。
插槽
- 作用:讓父元件可以向子元件指定位置插入html結構,也是一種元件間通信的方式,适用于父元件 ===> 子元件。
- 分類:預設插槽、具名插槽、作用域插槽
- 使用方式:
- 預設插槽:
父元件中:
<Category>
<div>html結構1</div>
</Category>
子元件中:
<template>
<div>
<!-- 定義插槽 -->
<slot>插槽預設内容...</slot>
</div>
</template>
- 具名插槽:
父元件中:
<Category>
<template slot="center">
<div>html結構1</div>
</template>
<template v-slot:footer>
<div>html結構2</div>
</template>
</Category>
子元件中:
<template>
<div>
<!-- 定義插槽 -->
<slot name="center">插槽預設内容...</slot>
<slot name="footer">插槽預設内容...</slot>
</div>
</template>
- 作用域插槽:
- 了解:資料在元件的自身,但根據資料生成的結構需要元件的使用者來決定。(games資料在Category元件中,但使用資料所周遊出來的結構由App元件決定)
- 具體編碼:
父元件中:
<Category>
<template scope="scopeData">
<!-- 生成的是ul清單 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4标題 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子元件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//資料在子元件自身
data() {
return {
games:['紅色警戒','穿越火線','勁舞團','超級瑪麗']
}
},
}
</script>
Vuex
1.概念
在Vue中實作集中式狀态(資料)管理的一個Vue插件,對vue應用中多個元件的共享狀态進行集中式的管理(讀/寫),也是一種元件間通信的方式,且适用于任意元件間通信。
2.何時使用?
多個元件需要共享資料時
3.搭建vuex環境
- 建立檔案:
src/store/index.js
//引入Vue核心庫
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//應用Vuex插件
Vue.use(Vuex)
//準備actions對象——響應元件中使用者的動作
const actions = {}
//準備mutations對象——修改state中的資料
const mutations = {}
//準備state對象——儲存具體的資料
const state = {}
//建立并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
- 在
中建立vm時傳入main.js
配置項store
......
//引入store
import store from './store'
......
//建立vm
new Vue({
el:'#app',
render: h => h(App),
store
})
4.基本使用
- 初始化資料、配置
、配置actions
,操作檔案mutations
store.js
//引入Vue核心庫
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)
const actions = {
//響應元件中加的動作
jia(context,value){
// console.log('actions中的jia被調用了',miniStore,value)
context.commit('JIA',value)
},
}
const mutations = {
//執行加
JIA(state,value){
// console.log('mutations中的JIA被調用了',state,value)
state.sum += value
}
}
//初始化資料
const state = {
sum:0
}
//建立并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
- 元件中讀取vuex中的資料:
$store.state.sum
- 元件中修改vuex中的資料:
或$store.dispatch('action中的方法名',資料)
$store.commit('mutations中的方法名',資料)
備注:若沒有網絡請求或其他業務邏輯,元件中也可以越過actions,即不寫,直接編寫
dispatch
commit
5.getters的使用
- 概念:當state中的資料需要經過加工後再使用時,可以使用getters加工。
- 在
中追加store.js
配置getters
......
const getters = {
bigSum(state){
return state.sum * 10
}
}
//建立并暴露store
export default new Vuex.Store({
......
getters
})
- 元件中讀取資料:
$store.getters.bigSum
6.四個map方法的使用
- mapState方法:用于幫助我們映射
中的資料為計算屬性state
computed: {
//借助mapState生成計算屬性:sum、school、subject(對象寫法)
...mapState({sum:'sum',school:'school',subject:'subject'}),
//借助mapState生成計算屬性:sum、school、subject(數組寫法)
...mapState(['sum','school','subject']),
},
- mapGetters方法:用于幫助我們映射
中的資料為計算屬性getters
computed: {
//借助mapGetters生成計算屬性:bigSum(對象寫法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成計算屬性:bigSum(數組寫法)
...mapGetters(['bigSum'])
},
- mapActions方法:用于幫助我們生成與
對話的方法,即:包含actions
的函數$store.dispatch(xxx)
methods:{
//靠mapActions生成:incrementOdd、incrementWait(對象形式)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(數組形式)
...mapActions(['jiaOdd','jiaWait'])
}
- mapMutations方法:用于幫助我們生成與
對話的方法,即:包含mutations
的函數$store.commit(xxx)
methods:{
//靠mapActions生成:increment、decrement(對象形式)
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//靠mapMutations生成:JIA、JIAN(對象形式)
...mapMutations(['JIA','JIAN']),
}
備注:mapActions與mapMutations使用時,若需要傳遞參數需要:在模闆中綁定事件時傳遞好參數,否則參數是事件對象。
7.子產品化+命名空間
- 目的:讓代碼更好維護,讓多種資料分類更加明确。
- 修改
store.js
const countAbout = {
namespaced:true,//開啟命名空間
state:{x:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){
return state.sum * 10
}
}
}
const personAbout = {
namespaced:true,//開啟命名空間
state:{ ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
- 開啟命名空間後,元件中讀取state資料:
//方式一:自己直接讀取
this.$store.state.personAbout.list
//方式二:借助mapState讀取:
...mapState('countAbout',['sum','school','subject']),
- 開啟命名空間後,元件中讀取getters資料:
//方式一:自己直接讀取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters讀取:
...mapGetters('countAbout',['bigSum'])
- 開啟命名空間後,元件中調用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
- 開啟命名空間後,元件中調用commit
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
路由
- 了解: 一個路由(route)就是一組映射關系(key - value),多個路由需要路由器(router)進行管理。
- 前端路由:key是路徑,value是元件。
1.基本使用
- 安裝vue-router,指令:
npm i vue-router
- 應用插件:
Vue.use(VueRouter)
- 編寫router配置項:
//引入VueRouter
import VueRouter from 'vue-router'
//引入Luyou 元件
import About from '../components/About'
import Home from '../components/Home'
//建立router執行個體對象,去管理一組一組的路由規則
const router = new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
//暴露router
export default router
- 實作切換(active-class可配置高亮樣式)
<router-link active-class="active" to="/about">About</router-link>
- 指定展示位置
<router-view></router-view>
2.幾個注意點
- 路由元件通常存放在
檔案夾,一般元件通常存放在pages
檔案夾。components
- 通過切換,“隐藏”了的路由元件,預設是被銷毀掉的,需要的時候再去挂載。
- 每個元件都有自己的
屬性,裡面存儲着自己的路由資訊。$route
- 整個應用隻有一個router,可以通過元件的
屬性擷取到。$router
3.多級路由(多級路由)
- 配置路由規則,使用children配置項:
routes:[
{
path:'/about',
component:About,
},
{
path:'/home',
component:Home,
children:[ //通過children配置子級路由
{
path:'news', //此處一定不要寫:/news
component:News
},
{
path:'message',//此處一定不要寫:/message
component:Message
}
]
}
]
- 跳轉(要寫完整路徑):
<router-link to="/home/news">News</router-link>
4.路由的query參數
- 傳遞參數
<!-- 跳轉并攜帶query參數,to的字元串寫法 -->
<router-link :to="/home/message/detail?id=666&title=你好">跳轉</router-link>
<!-- 跳轉并攜帶query參數,to的對象寫法 -->
<router-link
:to="{
path:'/home/message/detail',
query:{
id:666,
title:'你好'
}
}"
>跳轉</router-link>
- 接收參數:
$route.query.id
$route.query.title
5.命名路由
- 作用:可以簡化路由的跳轉。
- 如何使用
- 給路由命名:
{
path:'/demo',
component:Demo,
children:[
{
path:'test',
component:Test,
children:[
{
name:'hello' //給路由命名
path:'welcome',
component:Hello,
}
]
}
]
}
- 簡化跳轉:
<!--簡化前,需要寫完整的路徑 -->
<router-link to="/demo/test/welcome">跳轉</router-link>
<!--簡化後,直接通過名字跳轉 -->
<router-link :to="{name:'hello'}">跳轉</router-link>
<!--簡化寫法配合傳遞參數 -->
<router-link
:to="{
name:'hello',
query:{
id:666,
title:'你好'
}
}"
>跳轉</router-link>
6.路由的params參數
- 配置路由,聲明接收params參數
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News
},
{
component:Message,
children:[
{
name:'xiangqing',
path:'detail/:id/:title', //使用占位符聲明接收params參數
component:Detail
}
]
}
]
}
- 傳遞參數
<!-- 跳轉并攜帶params參數,to的字元串寫法 -->
<router-link :to="/home/message/detail/666/你好">跳轉</router-link>
<!-- 跳轉并攜帶params參數,to的對象寫法 -->
<router-link
:to="{
name:'xiangqing',
params:{
id:666,
title:'你好'
}
}"
>跳轉</router-link>
特别注意:路由攜帶params參數時,若使用to的對象寫法,則不能使用path配置項,必須使用name配置!
- 接收參數:
$route.params.id
$route.params.title
7.路由的props配置
作用:讓路由元件更友善的收到參數
{
name:'xiangqing',
path:'detail/:id',
component:Detail,
//第一種寫法:props值為對象,該對象中所有的key-value的組合最終都會通過props傳給Detail元件
// props:{a:900}
//第二種寫法:props值為布爾值,布爾值為true,則把路由收到的所有params參數通過props傳給Detail元件
// props:true
//第三種寫法:props值為函數,該函數傳回的對象中每一組key-value都會通過props傳給Detail元件
props(route){
return {
id:route.query.id,
title:route.query.title
}
}
}
8. <router-link>
的replace屬性
<router-link>
- 作用:控制路由跳轉時操作浏覽器曆史記錄的模式
- 浏覽器的曆史記錄有兩種寫入方式:分别為
和push
,replace
是追加曆史記錄,push
是替換目前記錄。路由跳轉時候預設為replace
push
- 如何開啟
模式:replace
<router-link replace .......>News</router-link>
9.程式設計式路由導航
- 作用:不借助
實作路由跳轉,讓路由跳轉更加靈活<router-link>
- 具體編碼:
//$router的兩個API
this.$router.push({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.replace({
name:'xiangqing',
params:{
id:xxx,
title:xxx
}
})
this.$router.forward() //前進
this.$router.back() //後退
this.$router.go() //可前進也可後退
10.緩存路由元件
- 作用:讓不展示的路由元件保持挂載,不被銷毀。
- 具體編碼:
<keep-alive include="News">
<router-view></router-view>
</keep-alive>
11.兩個新的生命周期鈎子
- 作用:路由元件所獨有的兩個鈎子,用于捕獲路由元件的激活狀态。
- 具體名字:
-
路由元件被激活時觸發。activated
-
路由元件失活時觸發。deactivated
12.路由守衛
- 作用:對路由進行權限控制
- 分類:全局守衛、獨享守衛、元件内守衛
- 全局守衛:
//全局前置守衛:初始化時執行、每次路由切換前執行
router.beforeEach((to,from,next)=>{
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判斷目前路由是否需要進行權限控制
if(localStorage.getItem('school') === 'atguigu'){ //權限控制的具體規則
next() //放行
}else{
alert('暫無權限檢視')
// next({name:'guanyu'})
}
}else{
next() //放行
}
})
//全局後置守衛:初始化時執行、每次路由切換後執行
router.afterEach((to,from)=>{
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改網頁的title
}else{
document.title = 'vue_test'
}
})
- 獨享守衛:
beforeEnter(to,from,next){
console.log('beforeEnter',to,from)
if(to.meta.isAuth){ //判斷目前路由是否需要進行權限控制
if(localStorage.getItem('school') === 'atguigu'){
next()
}else{
alert('暫無權限檢視')
// next({name:'guanyu'})
}
}else{
next()
}
}
- 元件内守衛:
//進入守衛:通過路由規則,進入該元件時被調用
beforeRouteEnter (to, from, next) {
},
//離開守衛:通過路由規則,離開該元件時被調用
beforeRouteLeave (to, from, next) {
}
13.路由器的兩種工作模式
- 對于一個url來說,什麼是hash值?—— #及其後面的内容就是hash值。
- hash值不會包含在 HTTP 請求中,即:hash值不會帶給伺服器。
- hash模式:
- 位址中永遠帶着#号,不美觀 。
- 若以後将位址通過第三方手機app分享,若app校驗嚴格,則位址會被标記為不合法。
- 相容性較好。
- history模式:
- 位址幹淨,美觀 。
- 相容性和hash模式相比略差。
- 應用部署上線時需要後端人員支援,解決重新整理頁面服務端404的問題。