由於上一個小項目寫的很次,這一次打算好好地寫一個博客系統,最近剛剛結束了管理員的管理端的編寫。其中遇到了很多小坑。
其實只能說自己vue用的不是特別熟練吧。很多問題都有些想當然了,實現起來發現了很多的問題。簡單的記錄幾個我自己認為值得記錄的吧。
一、一個很坑的問題,vue在對其中一個目標進行改變的時候,實際上會對模板內部的方法和變量等都進行重新渲染,這樣就會導致一個問題。如下
<template> <div class="hello"> <ul> <li v-for="item in datas"> <div :style="{fontSize:changsize()}">{{item}}</div> </li> </ul> <input type="text" v-model="tests"> {{tests}} </div> </template> <script> export default { name: 'HelloWorld', data () { return { datas:['one','two','three','one','two','three','one','two','three'], fz:'', tests:'', } }, watch:{ datas(val){ console.log(111); return; } }, methods:{ changsize(){ return (parseInt(Math.random()*15)+10)+'px'; } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
代碼如上,如果我在input內部輸入內容,這樣就會改變了data內部的tests,進而整個模板都進行一次重新渲染。這樣就導致我輸入一個數據這個字體的大小就全部改變一次。這樣就違背了我的初衷,僅僅是想在模板加載的時候賦值一次就可以了!!!以后輸入內容的時候不需要改變了。開始還以為能有類似鈎子函數的東西來禁止一下。最后發現有點問題。
在網上解決問題的時候找到這樣一句話:
每個vue實例都有一個根元素id的屬性el,Vue對象通過它來找到要渲染的部分。之后使用createDocumentFragment()方法創建一個documentFragment,遍歷根元素的所有子元素,依次劫持並插入文檔片段,將根元素掏空。然后執行Vue的編譯:遍歷documentFragment中的節點,對其中的v-for,v-text等屬性進行相應的處理。最后,把編譯完成后的documentFragment還給根元素。
這樣也就是說其實它實際上是對整體都進行了處理,如果要改變的話可能需要重寫一些方法......
那就換一個思路好了,在自己寫的代碼層面上想辦法。
1.當時想的第一個辦法是每一次在生成datas(在我得項目里這個數據是從數據庫取出來的),就直接生成一個隨機的字體大小存儲在數據庫中。這樣加載的時候就可以直接設置了。但是也有壞處。改變了自己的初始設計想法。。。。
2.今天仔細想了一下,想出了一個辦法。使用一個變量用來存儲模板刷新的時候所生成的字體大小,這樣在使用的時候用這個自己定義的數組變量和相應的item的index來進行分辨到底設置哪個字體的大小。代碼如下
<template> <div class="hello"> <ul> <li v-for="(item,index) in datas"> {{changsize(index)}} <div :style="{fontSize:font_size[index]}">{{item}}</div> </li> </ul> <input type="text" v-model="tests"> {{tests}} </div> </template> <script> export default { name: 'HelloWorld', data () { return { datas:['one','two','three','one','two','three','one','two','three'], fz:'', tests:'', font_size:[], } }, watch:{ datas(val){ console.log(111); return; } }, methods:{ changsize(index){ if(this.font_size.length!=this.datas.length){this.font_size[index]=(parseInt(Math.random()*15)+10)+'px'; }else{ return; } } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
3.對於上面的方法純屬是屬於通過自己的邏輯來進行判斷。在methods運行的時候還需要使用if來判斷一下。那么根據上一個方法有個優化的方法,我們可以聲明一個數組變量,然后不斷地push進新的數據進行存儲,在賦值的時候依舊使用 數組[index] 這樣的形式來賦值,這樣就可以了。
<template> <div class="hello"> <ul> <li v-for="(item,index) in datas"> {{changsize()}} <div :style="{fontSize:font_size[index]}">{{item}}</div> </li> </ul> <input type="text" v-model="tests"> {{tests}} </div> </template> <script> export default { name: 'HelloWorld', data () { return { datas:['one','two','three','one','two','three','one','two','three'], fz:'', tests:'', // font_size:[], } }, computed:{ font_size(){ return []; } }, methods:{ changsize(){ this.font_size.push((parseInt(Math.random()*15)+10)+'px'); } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
這樣就比較完美的解決了這個問題。當然,我們也可以將存儲數據的變量放到data內部,例如我在data內部注釋的那行代碼一樣,但是這樣會有一個缺點,瀏覽器會報錯
[Vue warn]: You may have an infinite update loop in a component render function.
這個問題的原因就是如果我們在v-for內部使用方法來改變data內的數據的時候,很有可能會導致無線循環,按照我這種寫法當然不會觸發,但是畢竟還是有可能的,所以我們還是把變量聲明到computed好了。畢竟有個紅色的報錯提醒看着也是很煩的。
-------------------------------------------------2018-05-03 23:56:14--------------------------------------------------------