本文就不根據整個專案從頭到尾來詳寫了,掘金社群很多寫得很好的大神已經把這整個專案總結的文章寫的非常好了,例如:Chrislinlin作者寫的Vue.js開發去哪兒網WebApp,還有一些寫的好的文章,我就不一一列舉了。
所以本文只記錄我個人記錄在專案學習筆記本上的一些點。這個仿去哪兒專案的學習,我個人的主要目的是為了瞭解一個App開發需要如何去做,如何元件化開發,如何利用Git進行程式碼管理(完整地看過Git操作影片學習,但只看不操作壓根就是紙上談兵,這個專案讓我對Git真正有了一個入門的理解),還有鞏固學習的vue的知識點。
1.專案框架圖
2.專案環境搭建
①nodejs
②程式碼管理(本專案選用碼雲)新建專案倉庫
③Git for windows下載
④新增SSH公鑰並將電腦與線上倉庫連線
1.生成公鑰
2.開啟Git Bash,輸入ssh-keygen -t rsa -C "[email protected]"
根據提示按下3次回車
3.檢視並複製剛才生成的公鑰cat /.ssh/id_rsa.pub
4.將公鑰貼上到git倉庫管理處建立連線
5.新增成功後,在Git Bash輸入ssh -T [email protected]
若提示Hi xxx,but...則為連線成功
⑤將線上生成的README.md檔案克隆到本地
1.在碼雲剛才新建的專案倉庫右邊的克隆/下載按鈕選擇SSH,複製連結
2.開啟Git Bash,用cd進入到自己新建的專案檔案目錄
3.輸入git clone
+ 剛才複製的連結
4.這樣就把線上生成的專案克隆到本地剛才新建的專案檔案目錄
⑥在剛才的目錄裡面生成vue專案腳手架(此處以vue2.x
版本為例介紹)
1.在該專案檔案目錄下執行cmd或者powershell(或直接vs終端控制檯)
2.輸入npm install --global vue-cli
回車確認(安裝的為2.9.6版本)
3.輸入vue init webpack xxx
(xxx)為專案名稱,此處用Travel命名
a.提示xxxProject name xxx
,不能用含有大寫字母的專案名稱命名,改用travel
b.Project description?
專案描述,沒有描述就直接回車
c.Author
專案作者填寫
d.Vue.build
(Runtime+complier跟Runtime only)選擇Runtime+complier具體區別請看 Runtime-Compiler和Runtime-Only的區別
e.Install vue-router?
是否安裝vue路由,Yes
f.Use ESlint to lint your code?Yes
是否使用ESlint對程式碼進行一個規範化約束
Pick an ESlint prest
選擇Standand
(說實話ESlint這玩意兒,如果以前沒用過,一開始用的時候時不時給你提示一個波浪線、紅點錯誤提示,真的有時候逼死強迫症,但是用了兩三天,啊,我的程式碼真整齊,真舒服,現在如果敲程式碼沒了這東西,我都覺得渾身難受)
g.Set up unit tests?
是否使用單元測試,這個專案是沒使用的No
h.Set up e2e tests with Nightwatch?
是否進行端到端的測試,一樣的No
i.npm yarn選擇npm做整個專案的包管理
⑦測試腳手架是否成功安裝,能否正確執行,輸入cd Travel
再輸入npm run dev
回車進入到埠初始頁面
⑧同步線上線下初始程式碼
1.在專案檔案目錄裡面右鍵選擇git bash here
開啟git bash
2.先輸入git status
以檢視在你上次提交之後是否有修改,以及現在所有分支,能看到增加了許多新檔案
3.輸入git add .
來添加當前專案的所有檔案到本地快取區
4.輸入git commit -m 'xxxxx'
xxx內容為你對本次提交的修改的檔案的描述
5.輸入git push
將上述操作的檔案推到雲端專案程式碼管理倉庫
做完上述步驟(有一些簡單能看懂的步驟我可能直接跳過了沒有寫入進來),專案的環境就已經搭建完成了,以上是我個人的理解,中間可能有一些寫錯的地方,或者寫的不好的地方還請大家指出。
3.專案初始檔案介紹
readme.md //專案的說明檔案
package.json //第三方依賴包配置、專案開發依賴包、依賴環境資訊
package.lock.json //幫助我們去確定安裝的第三方依賴包的具體的版本,保持團隊程式設計的統一,鎖住一些包的版本,保證程式在這些版本的包下執行是能夠正常執行的
license //開源協議的說明
index.html //專案預設的首頁模版檔案
.postcssrc.js //對 postcss 的配置項
.gitignore //不需要上傳到 git 上的檔案管理 、忽略上傳到雲端的檔案
.eslintrc.js //對寫的程式碼檢測是否標準做一個檢測、配置了對程式碼的規範
.eslintignore //配置不需要 eslintrc 檢測工具檢測的檔案
.editorconfig //配置編輯器總風格統一的自動化格式的語法
.babelrc //專案寫的程式碼是 Vue 的大檔案元件的程式碼的寫法,所以需要通過 babel 這種語法解析器做一些語法上的轉換,最終轉換成瀏覽器能夠編譯執行的程式碼,babel 需要做額外配置時,就放在檔案裡面
static //static 目錄放的是靜態資源,要用到的靜態圖片啊或者後續需要模擬的 json 資料
node_modules //專案中需要用到的第三方 node 包
src //放的是專案的原始碼
src/main.js //整個專案的入口檔案
src/app.vue //整個專案最原始的根元件
src/router/index.js //專案的路由放置位置
src/components //專案中要用到的小元件
src/assets //專案中需要用到的圖片
config //放置專案配置檔案
config/index.js //放基礎配置
config/dev.ent.js //開發環境配置資訊
config/prod.ent.js //線上環境配置資訊
build //放置專案打包的 webpack 配置資訊,vue-cli 會自動構建
build/webpack.base.conf.js //基礎的 webpack 配置資訊
build/webpack.dev.conf.js //開發環境的 webpack 配置資訊
build/webpack.prod.conf.js //線上環境的 webpack 配置資訊
複製程式碼
4.專案筆記記錄點
4.1 多頁應用與單頁應用對比
多頁應用:頁面跳轉→返回HTML
優點:首屏時間快,SEO效果好(搜尋引擎權重效果好)
缺點:頁面切換慢
單頁應用:頁面跳轉→JS渲染
優點:頁面切換快
缺點:首屏時間稍慢,SEO效果差
4.2 專案自定義快捷路徑
①(vue2.x腳手架):在webpack.base.conf.js
裡面往下拉,找到resolve裡面的alias處可以自定義快捷路徑
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'styles': resolve('src/assets/styles'),
'common': resolve('src/common')
}
},
複製程式碼
②(vue3.0腳手架):整合到了'vue.config.js'檔案裡面,如下這樣配置
module.exports = {
chainWebpack: (config) => {
config.resolve.alias
.set('styles', path.join(__dirname, './src/assets/styles'))
.set('@', path.join(__dirname, './src/'))
.set('common', path.join(__dirname, './src/common/'))
}
}
複製程式碼
4.3 每開發一個新功能,Git的一系列操作
①先到線上程式碼管理倉庫處建立新功能分支(建議以頁面元件名稱命名,便於管理)
②進入本地專案目錄下git bash here
,輸入git pull
將線上分支拉取下來
③輸入git checkout xxxxxx
切換到新分支上(xxxxxx為剛才新建的分支名)
④輸入git status
檢視自己現在所處分支,確認無誤開始寫程式碼
4.4每完成一個新功能的開發後,Git的一系列操作
①進入本地專案目錄下右鍵選擇git bash here
開啟git bash
②輸入git add .
將所有修改的檔案新增到本地快取區
③輸入git commit -m 'xxxxxx'
提交,並輸入提交上線的描述(xxxx內容為對此次提交、改動的描述)
④輸入git push
將上面提交的程式碼推到雲端專案程式碼管理倉庫
(做完上述步驟之後還沒好,我們僅僅是將剛才分支的內容推到了雲端,是還沒有做完的,我們還得將分支合併)
⑤輸入git checkout master
切換到master分支上
⑥輸入git merge origin/xxxxxx
合併分支(xxxxxx為剛才新建的分支)一般在實際操作中,是要經過測試後,測試沒問題,在上線前合併分支
⑦再次輸入git push
將合併後的master分支內容推到雲端同步
4.5 加一個固定div防止頁面因為網速載入問題發生抖動
這個固定div的模板樣式為如下,以一個例子css資料來展示
width:100%
height:0
overflow:hidden
padding-bottom:31.25%
複製程式碼
這種處理方法在整個專案元件的地方都用到了,做過這個專案的小夥伴應該都有映像^_^
4.6 static下存放靜態資源
專案裡面的圖片,我一開始都是用的自己下載的一些圖片,然後是把它們放到專案元件目錄下新建的一個img檔案,但我發現引用後頁面沒效果,我還以為我哪裡寫錯了,反覆檢查src引用的連結有沒有問題,檢查幾次之後我上網查了一下,發現有些人也是這樣,然後就放到了static目錄下的檔案裡面,頁面才有效果,所以這些靜態資源還是得放在static下。
4.7 優化輪播圖手動滑動後就停止自動輪播的問題(自己加的)
這個在專案裡是沒有提到的,是我自己在頁面測試的時候發現的問題,只要我手動滑動一次輪播圖之後,那個輪播效果就停止了,停在一副圖上。然後也上網查了這個問題怎麼解決,解決辦法其實也很簡單,看一下下面的輪播圖控制的程式碼,下面有指出
swiperOption: {
pagination: '.swiper-pagination',
loop: true, //是否迴圈輪播
speed: 5000, //滑動速度
autoplay: {
delay: 2200, //自動切換時間間隔
stopOnLastSlide: false //是否切換到最後一幅圖時停止自動切換
},
autoplayDisableOnInteraction: false// 避免手動滑了之後就停止自動輪播,去掉autoplay可以放入autoplay物件中
}
複製程式碼
4.8 文字超出盒子區域後自動顯示省略號css樣式模板
要做到文字超出盒子就顯示...省略號的css程式碼
overflow:hidden
white-space:nowrap
text-overflow:ellipsis
複製程式碼
如果不行就在上一級容器中加 min-width:0
4.9 手機移動端li-1畫素邊框問題
因為手機移動端寫1畫素的時候,實際上能夠明顯看到不是1畫素的邊框,那麼如何解決這個問題呢?本專案引入border.css來解決這個問題,已經是寫好的檔案了,直接引入即可
4.10 router點選後變色問題
因為router-link也有超連結樣式,點選之後會變色,所以要給這一層的盒子加一個固定的顏色color。否則點選過後顏色就改變了
4.11 繫結方法時有無()與獲取事件源物件
專案中點選城市列表的時候,要獲取事件源物件,繫結方法時@click="handlexxx"
,不新增括號,自動傳入事件源物件,寫入methods時寫方法名handlexxx(e){}
如此即可呼叫事件源物件,例如獲取點選區域下的文字,就是e.target.innerText
即可獲取到。
如果@click="handlexxx()"
繫結時加上這個括號直接這樣用是獲取不了的,還得加上$event
,即@click="handlexxx($event)"
,如此就能呼叫事件源物件了
4.12 元件間傳值問題:父子元件間傳值(子傳父、父傳子),兄弟元件間傳值
本來呢,在我看來這裡可以化為兩個問題,兄弟元件間傳值的過程其實也就是子A先傳父,父再傳到子B那,那麼最終無非也就是子傳父、父傳子這兩個問題,因為專案裡面用的也是這種方法,但是我後來上網查了其實還有一種方法(Vuex在這裡面我也就不單獨算一種方法了,學過的vue應該都知道,大家那麼聰明),還有一種方法就是兄弟之間藉助於事件車,通過事件車的方式傳遞資料。
①父傳子:子元件寫在props
下即可,寫上型別(初始值)即可用:呼叫
②子傳父:子元件通過$emit
觸發父元件的自定義事件,this.$emit('xxx自定義事件名',附加引數)
,附加的引數會傳給監聽器回撥,示例程式碼如下圖,具體可參考 父子元件傳值
子元件:
1.兄弟之間傳遞資料需要藉助於事件車,通過事件車的方式傳遞資料
2.建立一個Vue的例項,讓各個兄弟共用同一個事件機制
3.傳遞資料方,通過一個事件觸發
bus.$emit(方法名,傳遞的資料)
4.接收資料方,通過mounted(){}
生命週期觸發bus.$on(方法名,function(接收資料的引數){用該元件的資料接收傳遞過來的資料})
,此時函式中的this已經發生了改變,可以使用箭頭函式
例項如下,我們可以建立一個單獨的js檔案eventVue.js,內容如下
import Vue from 'vue'
export default new Vue
複製程式碼
父元件:
<template>
<components-a></components-a>
<components-b></components-b>
</template>
複製程式碼
子元件a:
<template>
<div class="components-a">
<button @click="abtn">A按鈕</button>
</div>
</template>
<script>
import eventVue from '../../js/event.js'
export default {
name: 'app',
data () {
return {
'msg':"我是元件A"
}
},
methods:{
abtn:function(){
eventVue .$emit("myFun",this.msg) //$emit這個方法會觸發一個事件
}
}
}
</script>
複製程式碼
子元件b:
<template>
<div class="components-a">
<div>{{btext}}</div>
</div>
</template>
<script>
import eventVue from '../../js/event.js'
export default {
name: 'app',
data () {
return {
'btext':"我是B元件內容"
}
},
created:function(){
this.bbtn();
},
methods:{
bbtn:function(){
eventVue .$on("myFun",(message)=>{ //這裡最好用箭頭函式,不然this指向有問題
this.btext = message
})
}
}
}
</script>
複製程式碼
4.13 優化城市拖動列表
這個拖動城市右側列表的功能是拖動字母表,然後執行一個方法,使城市選項跳轉到該字母開頭的城市處,原方法程式碼如下:
handleTouchMove(e) {
if (this.touchStartus) {
const starY = this.$refs['A'][0].offsetTop
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - startY) / 20)
if (index == 0 && index < this.letters.length){
this.$emit('change', this.letters[index])
}
}
}
複製程式碼
(1)startY會被重複計算,浪費效能,所以我們要通過1.減少計算次數 來提高效能,做法是將const starY = this.$refs['A'][0].offsetTop
這行程式碼放到updated(){}
生命週期鉤子函式裡面以減少計算次數,因為只有當另一個元件傳過來的資料使頁面發生改變時,頁面重新渲染才需要重新計算這個值。
(2)拖動城市字母表時,方法函式執行頻率過高,我們可以不用那麼高頻地執行這個方法,所以我們可以通過節流來提高這部分的效能。先在data處新建一個值timer:null
,然後程式碼修改如下:
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - this.startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}, 16)
}
},
複製程式碼
修改之後,此處的意思就是,假設正在執行這個方法,我讓這個方法延遲16ms再執行,假設16ms內又進行了手指滑動,導致這個方法再次被呼叫,那麼就把上一次執行的方法清除掉,重新執行這一次的方法,那麼就能減少很多次不必要的方法執行了,以此來達到提高效能的目的。
4.14 localStorage使用注意問題
使用localStorage一定要記得捕捉異常,因為有的使用者關閉了瀏覽器本地儲存或者是使用了瀏覽器的隱身模式(匿名模式),那麼就會直接導致丟擲異常,所以要使用捕捉異常以免發生不必要的bug,在store下的mutations.js檔案下如下如此寫
export default {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
複製程式碼
state.js下如此寫
let defaultCity = '北京'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default { // 公用資料
city: defaultCity
}
複製程式碼
4.15 Vuex Getters特性
Vuex的Getters類似computed,可以根據vuex裡的靜態資料計算新資料,避免資料的冗餘問題。
4.16 Html5解決300ms點選延遲問題
之前解決這個問題呢,是引入使用fastClick這個包來解決的,但是Html5呢,直接在html新增一行{ touch-action:manipulation }
即可解決,那麼專案中是哪裡用了這行程式碼呢?我一開始以為是在index.html這個檔案下的html寫入的,但是找了之後沒找到,後來發現原來是寫在引入的reset.css
下
4.17 元件中name值的用途
①用於遞迴使用元件(例如城市詳情頁的票價一欄)
②對某個頁面取消快取選取(exclude="xxxxxxx元件"
)
③Vue開發檢視
4.18 解決頁面切換時滾動行為的相互影響
當我們頁面滾動到某個中間位置時,再點選進行頁面切換,會發現切換的新頁面也直接是到了剛才的中間位置,這樣看起來很不協調,我們可以再router
檔案下的index.js
新增以下這段程式碼來解決
// 每次做路由切換的時候,始終回到最頂部
scrollBehavior (to, form, savedPosition) {
return {x: 0, y: 0}
}
複製程式碼
4.19 城市列表頁拖動頁面拖拽問題
原來的程式碼是touchstart.prevent
這樣會阻止頁面預設拖拽效果,導致出現bug,所以我們這裡要把prevent刪除掉即可解決
4.20 手機測試白屏bug
有的手機不支援Promise,會導致手機進區域網測試時出現白屏bug,所以為了解決這個問題,我們可以安裝以下這個包來解決
npm install babel-polyfill --save
安裝後引入即可
寫到這,就算是寫完了,這個專案花了一週左右的時間做完的,對於一個初學者來說還是很友好的,能瞭解一個簡單專案的開發流程。以上也就是我的筆記本中的總結了,還有一些別的細節點可以參考一下我開頭提到的那些文章,如果覺得我寫的還可以的話,麻煩點個贊,寫的不好的地方還請大家指出,以便我來改正,謝謝大家。
主頁