vue的數(shù)據(jù)賦值聯(lián)動改變解決方案

最近連著做了好幾個vue項目,從0到版本迭代是复,vue教程算是好理解蕉陋,把vue官方文檔看一遍下來,基本上不會有什么大問題(嗯如果你看的夠仔細(xì)夠透徹的話)记舆,此篇是記錄vue踩過的坑以及可以優(yōu)化的地方鸽捻。

1.踩坑

1.1.深拷貝/淺拷貝

這實際上算不上vue的問題,算是js基礎(chǔ)沒打好的坑吧氨淌。

先來看一個簡單的例子:

let obj = {name:'fiona-SUN'};
let copyObj = obj;
copyObj.name = 'fiona';
console.log(copyObj.name);  // 'fiona'
console.log(obj.name);     // 'fiona'

在js中也有棧(stack)和堆(heap)的概念:

  • 棧:自動分配的內(nèi)存空間泊愧,大小確定會自動釋放。存放變量/局部變量/形參等盛正。在js中存放簡單數(shù)據(jù)段(五種基本數(shù)據(jù)類型:Number删咱、String、Boolean豪筝、Null痰滋、Undefined),他們是按值存放的续崖,可以直接訪問敲街。
  • 堆:動態(tài)分配的內(nèi)存,大小不定并且不會自動釋放严望。存放在堆內(nèi)存中的對象多艇,棧中的變量實際保存的是一個指針,這個指針指向堆中的某一個位置像吻。

所以上述例子中峻黍,屬于淺拷貝,當(dāng)我們聲明一個對象拨匆,由于他不屬于五種基本數(shù)據(jù)類型(即非簡單數(shù)據(jù)段)姆涩,棧中會存放一個我們聲明的obj變量,它指向了堆中實際的這個對象的地址惭每。當(dāng)我們把這個引用地址賦值給了copyObj骨饿,實際它獲得的是一個與obj一致的指向堆中的地址。當(dāng)copyOjb改變了指向的對象地址的實際的值的時候,obj拿到的值也就自然而然變化了宏赘∪薇保看圖理解?

image

嗯,道理我都懂置鼻,但是寫代碼我就自然而然的忽略了镇饮,該反思蜓竹。箕母。。

深拷貝的方法

  • 方法一:逐個去拿到簡單數(shù)據(jù)項(網(wǎng)上可以搜到遞歸解決俱济,思路類似)
let obj = {name:'fiona-SUN'};

let copyFunc = (originObj) => {
  let copyObj = {};
  for(let key in originObj){
    copyObj[key] = originObj[key];
  }
  return copyObj;
};

let copyObj = copyFunc(obj);
copyObj.name = 'fiona';
console.log(copyObj.name);  // 'fiona'
console.log(obj.name);     // 'fiona-SUN'
  • 方法二:通過JSON去解析
let obj = {name:'fiona-SUN'};

let copyObj = JSON.parse(JSON.stringify(obj));

copyObj.name = 'fiona';
console.log(copyObj.name);  // 'fiona'
console.log(obj.name);     // 'fiona-SUN'
  • 方法三:es6之展開Object.assign(拷貝obj的內(nèi)容到一個新的堆內(nèi)存嘶是,copyObj存儲新內(nèi)存的引用)
let obj = {name:'fiona-SUN'};

let copyObj = Object.assign({}, obj);

copyObj.name = 'fiona';
console.log(copyObj.name);  // 'fiona'
console.log(obj.name);     // 'fiona-SUN'
  • 方法四:es6之展開運(yùn)算符(僅用于數(shù)組)
let arr = [1,2,3];
let copyArr = [...obj];
copyArr[2] = 0;
console.log(copyArr[2]);  // 0
console.log(arr[2]);     // 2

數(shù)組的深拷貝:

方法一:使用slice

var arr = [1,2,3];
var newArr = arr.slice(0);

方法二:使用concat

var arr = [1,2,3];
var newArr = arr.concat();

1.2.列表更新檢測

1.2.1數(shù)組更新檢測

以下摘自vue官網(wǎng)API

由于 JavaScript 的限制,Vue 不能檢測以下變動的數(shù)組:

  1. 當(dāng)你利用索引直接設(shè)置一個項時蛛碌,例如:vm.items[indexOfItem] = newValue
  2. 當(dāng)你修改數(shù)組的長度時聂喇,例如:vm.items.length = newLength

為了解決第一類問題,以下兩種方式都可以實現(xiàn)和 vm.items[indexOfItem] = newValue 相同的效果蔚携,同時也將觸發(fā)狀態(tài)更新:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)

為了解決第二類問題希太,你可以使用 splice:

example1.items.splice(newLength)

觸發(fā)視圖更新的方法:

  1. 變異方法
  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()
  1. vue提供的set方法
  • Vue.set( target, key, value )
1.2.2對象更新檢測

還是由于 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 現(xiàn)在是響應(yīng)式的

vm.b = 2
// `vm.b` 不是響應(yīng)式的

解決方法:

  1. vue提供的set方法
  • Vue.set( target, key, value )
  1. Object.assign()
  • bject.assign({}, target, {key:value})

1.3.頁面刷新vuex被清空

這真的是遇到一個很坑的問題酝蜒,同一個頁面(router未改變)誊辉,一旦刷新(刷新或深度刷新),存儲的vuex就馬上和你說拜拜

  • localStorage
    網(wǎng)上推薦最多的方法就是用localStorage亡脑。但是我個人覺得不太合適堕澄,還得看項目吧。localStorage是永久存儲的霉咨。

  • 數(shù)據(jù)重新獲取
    我使用的方法是在需要某些數(shù)據(jù)之前先判斷一下數(shù)據(jù)是否存在蛙紫,如果不存在重新獲取。

1.4nextTick適當(dāng)使用

將回調(diào)延遲到下次 DOM 更新循環(huán)之后執(zhí)行途戒。在修改數(shù)據(jù)之后立即使用它坑傅,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一樣喷斋,不同的是回調(diào)的 this 自動綁定到調(diào)用它的實例上唁毒。

簡而言之,等待DOM更新之后再進(jìn)行操作继准。

1.5.異步問題

這個是一個亙古不變的話題枉证。

請求后臺數(shù)據(jù)異步,常不經(jīng)意的帶來了問題移必。(處理異步的方法就不詳細(xì)描述了室谚,網(wǎng)上一搜一大堆)

1.6.組件之間的調(diào)用方式

1.6.1.父子組件
  • prop向下傳遞,事件向上傳遞
  • 子組件添加ref屬性,父組件可以獲取到子組件的實例(不建議)
  • 插槽slot 作用域插槽
1.6.2.非父子組件
  • 使用狀態(tài)管理
  • 實例化一個公共vue實例

1.7.計算屬性設(shè)置值

計算屬性是基于它們的依賴進(jìn)行緩存的秒赤,一旦依賴發(fā)生變化猪瞬,計算屬性會重新計算

想要改變計算屬性的值。要通過set方法去觸發(fā)它所依賴的變量,(類似于觸發(fā)它重新計算入篮,單純賦予一個新值陈瘦,在取的時候也是不會被改變的)

1.8.vue文件中內(nèi)聯(lián)樣式中有無scoped屬性的差別

  • 有scoped屬性:
    當(dāng)前僅當(dāng)該vue文件可以使用這個樣式。
  • 無scoped屬性:
    影響其他文件

1.9 v-for v-key

當(dāng) Vue.js 用v-for 正在更新已渲染過的元素列表時潮售,它默認(rèn)用“就地復(fù)用”策略痊项。如果數(shù)據(jù)項的順序被改變,Vue 將不會移動 DOM 元素來匹配數(shù)據(jù)項的順序酥诽, 而是簡單復(fù)用此處每個元素鞍泉,并且確保它在特定索引下顯示已被渲染過的每個元素。

為了給 Vue 一個提示肮帐,以便它能跟蹤每個節(jié)點(diǎn)的身份咖驮,從而重用和重新排序現(xiàn)有元素,你需要為每項提供一個唯一 key 屬性训枢。理想的 key 值是每項都有的且唯一的 id托修。這個特殊的屬性相當(dāng)于 Vue 1.x 的 track-by ,但它的工作方式類似于一個屬性恒界,所以你需要用 v-bind 來綁定動態(tài)值 (在這里使用簡寫):

1.10 v-for 和 v-if

當(dāng)它們處于同一節(jié)點(diǎn)睦刃,v-for的優(yōu)先級比v-if更高。

1.11 js文件中引入的css不會自動加前綴

無論是開發(fā)環(huán)境還是生成環(huán)境都不會自動加前綴仗处,因為vue-loader只管.vue文件里面的樣式眯勾,沒有自動執(zhí)行autoprefixer loader

參考鏈接

在build/utils.js下引入postcss-loader

var postcssLoader = {
    loader: 'postcss-loader',
    options: {
        plugins: (loader) => [
            require('autoprefixer')()
        ],
        sourceMap: true
    }
}

如果還有問題在改成

var postcssLoader = {
    loader: 'postcss-loader',
    options: {
        plugins: (loader) => [
            require('autoprefixer')({
                browsers: [
                    // 加這個后可以出現(xiàn)額外的兼容性前綴
                    "> 0.01%"
                ]
            })
        ],
        sourceMap: true
    }
}

1.12 組件、prop大小寫不敏感婆誓,事件敏感

對于組件和prop而言,html上用kebab-case (短橫線分隔命名) 吃环,其對應(yīng)的js上要用

(HTML 中的特性名是大小寫不敏感的,所以瀏覽器會把所有大寫字符解釋為小寫字符洋幻。這意味著當(dāng)你使用 DOM 中的模板時郁轻,camelCase (駝峰命名法) 的 prop 名需要使用其等價的 kebab-case (短橫線分隔命名) 命名:)

【但是:如果你使用字符串模板,那么這個限制就不存在了文留『梦ǎ】

components: {
    kebabCase
}

---

prop: ['kebabCase']

跟組件和 prop 不同,事件名不存在任何自動化的大小寫轉(zhuǎn)換燥翅。而是觸發(fā)的事件名需要完全匹配監(jiān)聽這個事件所用的名稱骑篙。

跟組件和 prop 不同,事件名不會被用作一個 JavaScript 變量名或?qū)傩悦椋跃蜎]有理由使用 camelCase 或 PascalCase 了茴迁。并且 v-on 事件監(jiān)聽器在 DOM 模板中會被自動轉(zhuǎn)換為全小寫 (因為 HTML 是大小寫不敏感的),所以 v-on:myEvent 將會變成 v-on:myevent——導(dǎo)致 myEvent 不可能被監(jiān)聽到狮腿。

因此,我們推薦你始終使用 kebab-case 的事件名脏榆。

1.13 refs是靜態(tài)節(jié)點(diǎn)

refs是靜態(tài)節(jié)點(diǎn)

1.14 prop值的改變--不是立即

如果父組件中給子組件傳遞了一個prop的值,然后調(diào)用子組件的方法去獲取該值台谍,會發(fā)現(xiàn)值沒有立即改變须喂。

解決方法:

  1. 可以監(jiān)聽值的改變?nèi)フ{(diào)用相應(yīng)子組件的方法
  2. 將子組件相關(guān)方法的調(diào)用放在nextTick里面

1.15 elmentui里面的el-form '就地復(fù)用'

和v-for一樣,更新已渲染過的元素時趁蕊,它默認(rèn)用‘就地復(fù)用’策略坞生。如果數(shù)據(jù)項的順序被改變,Vue將不會移動DOM元素來匹配數(shù)據(jù)項的順序介衔,而是簡單服用此處每個元素恨胚,并且確保它在特定索引下顯示已被渲染過的每個元素骂因。

1.16 elementui中的el-table的列顯示與隱藏

如果有一組按鈕組炎咖,點(diǎn)擊不同的tab的時候顯示不同的列,列會更換位置寒波。默認(rèn)用‘就地復(fù)用’乘盼,不會更新,需要加一個key值取隨機(jī)數(shù)

1.17 fetch兼容

在vue-cli中使用fetch方式請求的時候俄烁。存在一定的兼容問題绸栅。

可以在build/webpack.base.conf.js中添加一個plugins

plugins:[
new webpack.ProvidePlugin({
  fetch: 'imports-loader?this=>global!exports-loader?global.fetch!whatwg-fetch',
  Promise:  'imports-loader?this=>global!exports-loader?global.Promise!es6-promise',
})
]

1.18 字符串模板

字符串模板

ps:注意依賴包的下載

2.優(yōu)化

2.1.錯誤處理

錯誤處理很重要但是這是最容易讓開發(fā)忽略的點(diǎn)。

2.1.1.請求接口錯誤

由于我的請求是使用axios插件或者fetch單獨(dú)寫在了一個js页屠,可以對其進(jìn)行響應(yīng)攔截粹胯。一旦失敗,或者后臺報錯辰企,就進(jìn)行響應(yīng)的錯誤處理以及友好提示风纠,也避免了重復(fù)的代碼,提高可維護(hù)性

2.1.2.頁面錯誤處理(404)
  1. nginx未匹配到路由走404路由
  2. router.beforeEach是否匹配到響應(yīng)的路由牢贸,否則走錯誤路由竹观。
2.1.3 錯誤提示封裝

將錯誤提示模塊化,通過vuex來操作錯誤的顯示以及信息等內(nèi)容潜索。

2.2.減少不必要的依賴包

性能優(yōu)化是很重要的臭增,特別是對于vue這種首屏加載時間長的。

例如有些項目用到了圖表(echarts),可以選擇加載依賴包竹习,不用加載整個echarts庫誊抛。

2.3.不發(fā)送多個相同的請求

不發(fā)送多個相同的請求,在點(diǎn)擊觸發(fā)請求的同時鎖定請求整陌,直至給出響應(yīng)/錯誤解鎖拗窃。

以上內(nèi)容昔园,如有錯誤請指出,不甚感激并炮。
如需轉(zhuǎn)載默刚,請注明出處

2.4.組件中引入css的css依賴 -- sass-resources-loader

為了讓SCSS之類的文件在CSS中引入中不需要每次都引入var.scss文件,可以引入一個sass-resources-loader解決逃魄。

2.4.為了解決組件內(nèi)引入的外部css文件沒有做css兼容處理 -- postcss-loader

在build/utils中引入postcss-loader

loader: 'postcss-loader',
options:{
  plugins: (loader) => [
      require('autoprefixer')()
  ],
  sourceMap: true 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末荤西,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子伍俘,更是在濱河造成了極大的恐慌邪锌,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件癌瘾,死亡現(xiàn)場離奇詭異觅丰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)妨退,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進(jìn)店門妇萄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人咬荷,你說我怎么就攤上這事冠句。” “怎么了幸乒?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵懦底,是天一觀的道長。 經(jīng)常有香客問我罕扎,道長聚唐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任腔召,我火速辦了婚禮杆查,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宴咧。我一直安慰自己根灯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布掺栅。 她就那樣靜靜地躺著烙肺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪氧卧。 梳的紋絲不亂的頭發(fā)上桃笙,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天,我揣著相機(jī)與錄音沙绝,去河邊找鬼搏明。 笑死鼠锈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的星著。 我是一名探鬼主播购笆,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼虚循!你這毒婦竟也來了同欠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤横缔,失蹤者是張志新(化名)和其女友劉穎铺遂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茎刚,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡襟锐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了膛锭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粮坞。...
    茶點(diǎn)故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泉沾,靈堂內(nèi)的尸體忽然破棺而出捞蚂,到底是詐尸還是另有隱情,我是刑警寧澤跷究,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站敲霍,受9級特大地震影響俊马,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肩杈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一柴我、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扩然,春花似錦艘儒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至兵拢,卻和暖如春翻斟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背说铃。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工访惜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘹履,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓债热,卻偏偏與公主長得像砾嫉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子窒篱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • vue概述 在官方文檔中焰枢,有一句話對Vue的定位說的很明確:Vue.js 的核心是一個允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,193評論 0 25
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容舌剂。關(guān)于...
    云之外閱讀 5,046評論 0 29
  • 第二章 細(xì)心八戒發(fā)現(xiàn)端倪 只身赴寺有去無回 我們很多人只記得現(xiàn)在這個好吃懶做的八戒济锄,卻忘了那個曾...
    一個正經(jīng)的作家閱讀 215評論 0 1
  • 我會給你波瀾不驚的愛情避消,陪你看世界的風(fēng)景低滩,許你一世歡顏。 栗子小姐和洋蔥先生又吵架了岩喷,鬧得特別不開心要分手恕沫。兩人相...
    握不住的ta閱讀 638評論 0 0
  • 人們往往追求繽紛絢爛,光彩奪目的事物纱意,但漸漸地婶溯,在追求的過程中突然發(fā)現(xiàn),這些東西只是虛有其表偷霉,非常不真實迄委,而且會讓...
    緣起緣滅_0bb8閱讀 61評論 0 0