實際項目中的編碼技巧總結(jié)(Vue篇)

本文目錄

  • 1.node-sass安裝失敗
  • 2.動態(tài)引入和綁定背景圖片
  • 3.寫在data中的數(shù)據(jù)無法將改變動態(tài)渲染到頁面上
    -4.vue中定義全局變量的方法
  • 5.beforeRouteEnter的書寫位置
  • 6.解決vue路由警告問題
  • 7.讓VScode保存時自動匹配ESlint規(guī)則
  • 8.封裝公用方法(以格式化數(shù)據(jù)為例)
  • 9.修改第三方組件樣式
  • 10.監(jiān)聽組件生命周期
  • 11.路由分區(qū)以及動態(tài)添加路由
  • 12.v-for循環(huán)拿到的item值動態(tài)渲染文字內(nèi)容
  • 13.路由跳轉(zhuǎn),頁面不刷新
  • 14.Vue部署與部署后刷新頁面404
  • 15.列表進入詳情頁的傳參問題
  • 16.組件的事件拿到額外的參數(shù)
  • 17.子組件改變父組件傳遞過來的數(shù)據(jù)
  • 18.父組件調(diào)用子組件的方法
  • 19.改變數(shù)組

1.node-sass安裝失敗

使用別人的一個模板項目的時候,在npm install的時候報錯提示node-sass啊沒裝失敗,出現(xiàn)原因是npm 安裝 node-sass 依賴時,會從 github.com 上下載 .node 文件。由于國內(nèi)網(wǎng)絡(luò)環(huán)境的問題,這個下載時間可能會很長,甚至導(dǎo)致超時失敗。
解決方法是首先把node_modules文件夾刪除,然后運行指令npm i node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/先單獨安裝node-sass,再啟用npm install安裝其他依賴。

2.動態(tài)引入和綁定背景圖片

vue中動態(tài)改變backgroundimage的寫法
:style="{backgroundImage:'url(\''+themeBg+'\')'}"
動態(tài)的在data中引入路徑的寫法
themeBg: require("../../assets/images/e_center.png"),
這個themeBg也可以是在緩存中獲取的
themeBg: sessionStorage.getItem("themeBg")

3.寫在data中的數(shù)據(jù)無法將改變動態(tài)渲染到頁面上

場景:數(shù)據(jù)確定會正常改變,但是變化不會自動觸發(fā)頁面上的顯示,但是功能是正常的。
可能原因1:就算數(shù)據(jù)是在data存在了,但是賦值的時候把某個屬性給丟失了,vue也就失去了對其的檢測能力。也就是說,在data中存在的數(shù)據(jù)以及對象屬性需要一直存在,否則vue就會失去對其變化的監(jiān)控。
可能原因2:vue中在data里定義的變量,在ajax獲取數(shù)據(jù)后進行改變,但是變量的改變無法動態(tài)渲染到視圖中,折騰了很長時間發(fā)現(xiàn)是回調(diào)函數(shù)中的this的指向發(fā)生了改變,回調(diào)函數(shù)應(yīng)該使用箭頭函數(shù)來保持this指向的不變。
可能原因3:computed里面數(shù)據(jù)的改變不會自動觸發(fā)視圖的更新,寫在data里的對象,需要新增加flag用來控制視圖元素的顯示和隱藏,需要進行動態(tài)的添加,如果flag本來就定義在data中,則可以直接賦值。

this.$set(this.regionOptions[i].options[si], 'flag', false);

如果像下面這樣添加,則無法和視圖進行實時動態(tài)渲染的綁定

this.regionOptions[i].options[si].flag = false;

4.vue中定義全局變量的方法

在mainjs中進行定義并將其掛載到vue實例中
var baseUrl = "http://110.50.111:8090";
Vue.prototype.$baseUrl = baseUrl
組件內(nèi)進行使用

methods: {
  asd() {
    console.log(this.$baseUrl);
  }
},
mounted() {
  this.asd()
}

全局引用js直接在main.js中引用就可以,import remtools from './assets/js/setrem'
但是這個js只有在項目第一次加載的時候執(zhí)行一次,切換路由的時候并不觸發(fā)這個js

5.beforeRouteEnter的書寫位置

beforeRouteEnter必須放在頁面文件中,組件是監(jiān)聽不到路由的

beforeRouteEnter (to, from, next) {
  if (from.path === '/detail') {
    next((vm) => {
      // 更新列表數(shù)據(jù)方法
      vm.updateData()
    })
  }
  next()
},

6.解決vue路由警告問題

下面這三行是解決vue項目路由出現(xiàn)message: "Navigating to current location (XXX) is not allowed"的方法,把代碼放置到router文件夾的index.js文件中即可

const routerPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return routerPush.call(this, location).catch(error=> error)
}

7.讓VScode保存時自動匹配ESlint規(guī)則

首先需要找到VScode配置文件setting.json

  1. ctrl+shift+p
    2.輸入setting
    3.選擇 首選項:打開設(shè)置(json)即可.
    這個文件存放的是一個JSON格式的數(shù)據(jù),在{}中的最后增加如下代碼
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true
  }

這樣的話,在修改代碼只需要ctrl+s保存代碼,代碼規(guī)則就會自動按照ESlint的配置規(guī)則進行調(diào)整。

8.封裝公用方法(以格式化數(shù)據(jù)為例)

我們封裝組件在多個地方用到的不同的接口數(shù)據(jù),這些請求來的數(shù)據(jù)有可能會名稱不同,所以我們需要封裝一個方法,專門用來格式化我們請求來的數(shù)據(jù),從而能夠在組件中得到統(tǒng)一的調(diào)用。
在src文件夾中新建一個common文件夾,然后再新建一個js文件夾,然后再新建一個util.js文件,這個文件是用來存放我們自己寫的一些工具方法的。

export function formatSongDetail(val){
    const newVal = []
    val.forEach((item) =>{
        const detail = {}
        detail.id = item.id
        detail.al = Object.assign({}, item.al || item.album || item.song.album)
//Object.assign方法的第一個參數(shù)是目標(biāo)對象,后面的參數(shù)都是源對象。
//注意,如果目標(biāo)對象與源對象有同名屬性,或多個源對象有同名屬性,則后面的屬性會覆蓋前面的屬性。
        detail.ar = [].concat(item.ar || item.artists || item.song.artists)
        detail.name = item.name
        newVal.push(detail)
    })
    return newVal
}

接下來,在要格式化數(shù)據(jù)的組件中先引入這個方法
``import { formatSongDetail } from "../../common/js/util";`
然后可以在data中新建一個formatData,用來存放我們格式化之后的數(shù)據(jù)

data() {
    return {
       formatData: []
    };
}

在ajax獲取到數(shù)據(jù)的時候,調(diào)用formatSongDetail方法,然后將數(shù)據(jù)格式化之后的數(shù)據(jù)存儲到formatData中
this.formatData = formatSongDetail(data.result);

9.修改第三方組件樣式

在使用vue構(gòu)建項目的時候,引用了第三方組件庫,只需要在當(dāng)前頁面修改第三方組件庫的樣式以做到不污染全局樣式。通過在樣式標(biāo)簽上使用scoped達到樣式只制作用到本頁面,但是此時再修改組件樣式不起作用。
解決方法:通過 >>> 穿透scoped
父組件中修改子組件的樣式使用樣式穿透
.parent >>> .child
父組件的 class或ID >>>(三個箭頭表示樣式穿透) 子組件的class或ID

<style scoped>
    外層 >>> 第三方組件類名{
        樣式
    }
</style>

有些Sass 、Less之類的預(yù)處理器無法正確解析 >>>??梢允褂?/deep/操作符( >>> 的別名)

<style lang="sass" scoped>
/deep/  第三方組件類名 {
      樣式
  }
</style>

10.監(jiān)聽組件生命周期

通常我們監(jiān)聽組件生命周期會使用 $emit ,父組件接收事件來進行通知
子組件代碼:

export default {
    mounted() {
        this.$emit('listenMounted')
    }
}

父組件代碼:

<template>
    <div>
        <List @listenMounted="listenMounted" />
    </div>
</template>

其實還有一種簡潔的方法,使用 @hook 即可監(jiān)聽組件生命周期,組件內(nèi)無需做任何改變。同樣的, created 、 updated 等也可以使用此方法。

<template>
    <List @hook:mounted="listenMounted" />
</template>

12.v-for循環(huán)拿到的item值動態(tài)渲染文字內(nèi)容

<div class="user_item" v-for="(item, index) in listData" :key="item.workid">
    <div>
        {{item.status === 1 ? '待確認(rèn)' : item.status === 2 ? '已拒絕' :item.status === 3 ? '已綁定' :item.status === 100 ? '已過期' : '' }}
    </div>
</div>

總結(jié):{{}}中是可以寫三元表達式的。

13.路由跳轉(zhuǎn),頁面不刷新

假設(shè)我們在寫一個博客網(wǎng)站,需求是從/post-page/a,跳轉(zhuǎn)到/post-page/b。然后我們驚人的發(fā)現(xiàn),頁面跳轉(zhuǎn)后數(shù)據(jù)竟然沒更新?!原因是vue-router"智能地"發(fā)現(xiàn)這是同一個組件,然后它就決定要復(fù)用這個組件,所以你在created函數(shù)里寫的方法壓根就沒執(zhí)行。通常的解決方案是監(jiān)聽$route的變化來初始化數(shù)據(jù),如下:

data() {
  return {
    loading: false,
    error: null,
    post: null
  }
}, 
watch: {
  '$route': {
    handler: 'resetData',
    immediate: true
  }
},
methods: {
  resetData() {
    this.loading = false
    this.error = null
    this.post = null
    this.getPost(this.$route.params.id)
  },
  getPost(id){

  }
}

bug是解決了,可每次這么寫也太不優(yōu)雅了吧。
其實可以借助router-view添加一個unique的key,這樣即使是公用組件,只要url變化了,就一定會重新創(chuàng)建這個組件。(雖然損失了一丟丟性能,但避免了無限的bug)。
同時,注意我將key直接設(shè)置為路由的完整路徑,一舉兩得。

<router-view :key="$route.fullpath"></router-view>

14.Vue部署與部署后刷新頁面404

我們先來看一下打包出來的的dist文件


dist文件夾.png

可以看到dist下只有一個 index.html 文件及一些靜態(tài)資源,這個是因為Vue是單頁應(yīng)用(SPA),只有一個index.html作為入口文件,其它的路由都是通過JS來進行跳轉(zhuǎn)
我們只需要將這個目錄上傳至目標(biāo)服務(wù)器即可
讓web容器跑起來,以nginx為例

server {
  listen  80;
  server_name website.com;
  location / {
    index  /data/dist/index.html;
  }
}

配置完成記得重啟nginx

// 檢查配置是否正確
nginx -t 
// 平滑重啟
nginx -s reload

操作完后就可以在瀏覽器輸入域名進行訪問了
當(dāng)然上面只是提到最簡單也是最直接的一種布署方式
什么自動化,鏡像,容器,流水線布署,本質(zhì)也是將這套邏輯抽象,隔離,用程序來代替重復(fù)性的勞動。

接著我們再回頭來看下web容器的 nginx 配置

server {
  // 監(jiān)聽80端口
  listen 80;
  // 定義你的站點名稱
  server_name website.com;
  // 根據(jù)請求 URI 設(shè)置配置
  location / {
      // 站點根目錄,這里為 vue 構(gòu)建出來的 dist 目錄
      root   /www/dist;
      // 站點初始頁為index.html 或 index.htm
      index  index.html;
  }
}

我們現(xiàn)在可以根據(jù) nginx 配置得出,當(dāng)我們在地址欄輸入 website.com 時,這時會打開我們 dist 目錄下的 index.html 文件,然后我們在跳轉(zhuǎn)路由進入到 website.com/login
關(guān)鍵在這里,當(dāng)我們在 website.com/login 頁執(zhí)行刷新操作,nginx location 是沒有相關(guān)配置的,所以就會出現(xiàn) 404 的情況

為什么hash模式下沒有問題
router hash 模式我們都知道是用符號#表示的,如 website.com/#/login, hash 的值為 #/login
它的特點在于:hash 雖然出現(xiàn)在 URL 中,但不會被包括在 HTTP 請求中,對服務(wù)端完全沒有影響,因此改變 hash 不會重新加載頁面
hash 模式下,僅 hash 符號之前的內(nèi)容會被包含在請求中,如 website.com/#/login 只有 website.com 會被包含在請求中 ,因此對于服務(wù)端來說,即使沒有配置location,也不會返回404錯誤

產(chǎn)生問題的本質(zhì)是因為我們的路由是通過JS來執(zhí)行視圖切換的,
當(dāng)我們進入到子路由時刷新頁面,web容器沒有相對應(yīng)的頁面此時會出現(xiàn)404
所以我們只需要配置將任意頁面都重定向到 index.html,把路由交由前端處理

location / {
  index  /data/dist/index.html;
  try_files $uri $uri/ /index.html;
}

這里有一個小細(xì)節(jié),如果出現(xiàn)真的 404 頁面了呢?比如 website.com/notfound
因為這么做以后,你的服務(wù)器就不再返回 404 錯誤頁面,因為對于所有路徑都會返回 index.html 文件。為了避免這種情況,應(yīng)該在 Vue 應(yīng)用里面覆蓋所有的路由情況,然后在給出一個 404 頁面

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})

15.列表進入詳情頁的傳參問題

例如商品列表頁面前往商品詳情頁面,需要傳一個商品id;

<router-link :to="{path: 'detail', query: {id: 1}}">前往detail頁面</router-link>

c頁面的路徑為http://localhost:8080/#/detail?id=1,可以看到傳了一個參數(shù)id=1,并且就算刷新頁面id也還會存在。此時在c頁面可以通過id來獲取對應(yīng)的詳情數(shù)據(jù),獲取id的方式是this.$route.query.id
vue傳參方式有:query、params+動態(tài)路由傳參。
說下兩者的區(qū)別:
1.query通過path切換路由,params通過name切換路由

// query通過path切換路由
<router-link :to="{path: 'Detail', query: { id: 1 }}">前往Detail頁面</router-link>
// params通過name切換路由
<router-link :to="{name: 'Detail', params: { id: 1 }}">前往Detail頁面</router-link>

2.query通過this.route.query來接收參數(shù),params通過this.route.params來接收參數(shù)。

// query通過this.$route.query接收參數(shù)
created () {
    const id = this.$route.query.id;
}

// params通過this.$route.params來接收參數(shù)
created () {
    const id = this.$route.params.id;
}

3.query傳參的url展現(xiàn)方式:/detail?id=1&user=123&identity=1&更多參數(shù)
params+動態(tài)路由的url方式:/detail/123
4.params動態(tài)路由傳參,一定要在路由中定義參數(shù),然后在路由跳轉(zhuǎn)的時候必須要加上參數(shù),否則就是空白頁面:

{      
    path: '/detail/:id',      
    name: 'Detail',      
    component: Detail    
}

注意,params傳參時,如果沒有在路由中定義參數(shù),也是可以傳過去的,同時也能接收到,但是一旦刷新頁面,這個參數(shù)就不存在了。這對于需要依賴參數(shù)進行某些操作的行為是行不通的,因為你總不可能要求用戶不能刷新頁面吧。例如

{
    path: 'detail/:id',
    name: 'Detail',
    components: Detail
}

// template中的路由傳參,
// 傳了一個id參數(shù)和一個token參數(shù)
// id是在路由中已經(jīng)定義的參數(shù),而token沒有定義
<router-link :to="{name: 'Detail', params: { id: 1, token: '123456' }}">前往Detail頁面</router-link>

// 在詳情頁接收
created () {
    // 以下都可以正常獲取到
    // 但是頁面刷新后,id依然可以獲取,而token此時就不存在了
    const id = this.$route.params.id;
    const token = this.$route.params.token;
}

16.組件的事件拿到額外的參數(shù)

本來的寫法@search-keyup=keyupSearchItem"
自定義事件keyupSearchItem拿到默認(rèn)的參數(shù)

keyupSearchItem (e){}

優(yōu)化后的寫法@search-keyup="argument => keyupSearchItem(index,argument)",自定義事件拿到額外的自定義參數(shù)

keyupSearchItem (index,e){}

index和argument的順序更換也沒問題

17.子組件改變父組件傳遞過來的數(shù)據(jù)

引用的組件

<mp-dialog class="page_module_dialog_batch_store" title="配置助力榜" v-model="showFlag" :width="625">

會觸發(fā)一些頁面?zhèn)魅氲臄?shù)據(jù)

props: {
  show:{
      type:Boolean,
      default:false
  }
},

設(shè)置computed的set和get完美解決

computed: {
    showFlag:{
        get() {
            return this.show
        },
        set(v) {
            this.$emit('closeHelpContainer')
        }
    }
},

如果只是下面這樣

computed: {
    showFlag (){
        return this.show
    }
},

則當(dāng)關(guān)閉組件的時候,頁面會報錯

Computed property "showFlag" was assigned to but it has no setter.

18.父組件調(diào)用子組件的方法

this.$refs.Category.getFormData();
給子組件添加上ref="Category",上面的代碼就直接可以調(diào)用到子組件的getFormData方法,并獲取到其中的返回值。

19.改變數(shù)組

vue2中定義一個數(shù)組demoArr: [1,2,3,4,5],然后渲染到頁面上,在methods中通過this.demoArr = [10,20,30,40,50]改變demoArr可以動態(tài)改變到頁面上嗎?
可以
this.set(this.demoArr,[10,20,30,40,50])這樣會報錯嗎 不會報錯,但也不起作用 vue2中改變數(shù)組項和對象屬性的正確方法:this.set(object, key, value)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Vue學(xué)習(xí)總結(jié)(Vue基礎(chǔ),VueCli3,VueRouter,Vuex) 目錄 vue基礎(chǔ)知識(1-13)vue...
    Allenem閱讀 4,339評論 0 22
  • vue是什么? vue是構(gòu)建數(shù)據(jù)驅(qū)動的web界面的漸進式框架。Vue.js 的目標(biāo)是通過盡可能簡單的 API 實現(xiàn)...
    九四年的風(fēng)閱讀 8,818評論 2 131
  • Vue 雙向綁定原理 mvvm 雙向綁定,采用數(shù)據(jù)劫持結(jié)合發(fā)布者-訂閱者模式的方式,通過 Object.defin...
    檸檬與斷章閱讀 915評論 0 3
  • 第一個 vue-router 路由 路由,其實就是指向的意思,當(dāng)我點擊頁面上的home按鈕時,頁面中就要顯示hom...
    索倫x閱讀 2,530評論 0 3
  • 卵磷脂的神奇功效! 卵磷脂或磷脂酰膽堿同膽固醇一樣,都是由肝臟不斷地產(chǎn)生,并隨同膽汁進入腸內(nèi),然后被血液所吸收。它...
    知識改變生活閱讀 350評論 0 0

友情鏈接更多精彩內(nèi)容