從Django後端(python)角度學習前端VUE框架基礎-下(觸發視圖更新,計算屬性,監聽器,過濾器) ∠( °ω°)/ 前端知識


看這邊博客前需要知道v-bind,v-modle,v-on這三個是幹什麼用的,下方會大量用到,如果不清楚可以看我的博客(https://xunmi.blog.csdn.net/article/details/106854178)

觸發視圖更新

常用方法

Vue中有一些用於數組的方法(和Python中用於列表的方法有很多相似之處,所以如果有一定Python基礎的同學可能會很輕鬆就能看懂),Vue數組使用這些方法時就會觸發更新。

  1. push() : 添加元素的方法。
  2. pop() : 刪除數組最後一個元素。
  3. shift() : 刪除數組的第一個元素。
  4. unshift("元素") : 在數組的開頭位置添加一個元素。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome10</title>
</head>

<body>

    <div id ="app">
        <p>{{vdata}}</p>
        <input type="text" v-model="vadd">
        <button @click='vpush'> push添加輸入的元素 </button>

        <button @click='vpop'>pop刪除數組末尾元素</button>

        <button @click='vshift'>shift刪除數組開頭元素</button>

        <button @click='vunshift'>unshift在數組開頭添加元素</button>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            vdata: ['Python', 'Django', 'Vue'],
            vadd: ''
        },
        methods: {
            vpush(){
                // 在數組末尾中添加元素
                this.vdata.push(this.vadd)
            },
            vpop(){
                // 刪除數組末尾的元素
                this.vdata.pop()
            },
            vshift(){
                // 刪除數組開頭的元素
                this.vdata.shift()
            },
            vunshift(){
                // 在數組開頭添加元素
                this.vdata.unshift(this.vadd)
            }

        }
     });
    </script>
</html>
  1. splice(索引->在第幾個位置開始添加, 數量->添加幾個, 內容1, 內容2 ..., 內容x) : 想數組中添加(內容>數量)或刪除(內容<數量)或替換元素(內容=數量)。
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome11</title>
</head>

<body>

    <div id ="app">
        <p>{{vdata}}</p>
        <button @click="vsplice(1)">向開頭和第一個參數後添加Django</button>
        <button @click="vsplice(2)">將首個參數替換爲flask</button>
        <button @click="vsplice(3)">開頭前兩個參數替換爲一個abc</button>
        <button @click="vsplice(4)">刪除第一個</button>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            vdata: ["Python", "Vue", "HTML"]
        },
        methods: {
            vsplice(num){
                if (num==1) {
                    // 向第一個參數後添加Django
                    this.vdata.splice(1, 0, "Django")   
                    // 向開頭位置添加Django
                    this.vdata.splice(0, 0, "Django")
                } else if(num==2) {
                    // 將首個參數替換爲flask
                    this.vdata.splice(0,1, "flask")
                } else if (num==3) {
                    // 將前兩個替換爲abc
                    this.vdata.splice(0,2, "abc")
                } else  {
                    // 刪除第一個
                    this.vdata.splice(0,1)
                }
            }
        }
     });
    </script>
</html>

在這裏插入圖片描述
6. sort(函數) : 根據函數進行排序。這裏的排序需要傳入一個匿名函數,然後會根據匿名函數的輸出值進行排序,每次只對兩個元素排序,如果是正值,則序列不變,如果是負值,則會將顛倒
7. reverse() : 將數組元素反轉。

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome12</title>
</head>

<body>

    <div id ="app">
        <p>{{vdata}}</p>
        <button @click="vsort">隨機排序</button>
        <p>{{vdome}}</p>
        <button @click="vitem">從大到小排序</button>
        <button @click="vall">反轉所有數組</button>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            vdata: ["Python", "Django", "Vue", "HTML"],
            vdome: [1, 5, 8, 7]
        },
        methods: {
            vsort(){
                this.vdata.sort(function(){
                    var a = Math.random()*10-5
                    return a
                })
                
            },
            vitem(){
                this.vdome.sort(function(x,y){
                    if (x>y) {
                        return -1
                    } else {
                        return 1
                    }
                })
            },
            vall(){
                this.vdome.reverse()
                this.vdata.reverse()
            }
        }
     });
    </script>
</html>

在這裏插入圖片描述

視圖更新注意事項

上述方法都可以立即更新視圖,但也有一些情況是無法觸發視圖更新的,避免踩坑,我會列出可能會碰到的坑, 我們直接修改數組或者字典是無法觸發視圖更新的,如果需要在數組或字典中添加新的元素,可以使用Vue.set()方法,但是修改字典中的值是會發出視圖更新的

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome</title>
</head>

<body>

    <div id ="app">
        <p>{{vdata}}</p>
        <button @click="append(0)">直接修改數組值</button>
        <button @click="append()">使用set方法修改</button>

        <p>{{vitem}}</p>
        <button @click="add(0)">直接添加屬性</button>
        <button @click="add(1)">使用set添加屬性</button>
        <button @click="add()">修改屬性</button>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            vdata : ["Python", "Django", "HTML"],
            vitem : {
                'meizu' : '黃章',
                'smartisan' : '羅永浩',
                'xiaomi' : '雷軍'
            }
        },
        methods: {
            append(a){
                if (a==0) {
                    // 直接修改某值雖然數組中值會被改變,但並不會出發視圖更新
                    this.vdata[0] = "json"
                    // 在控制檯顯示更新的內容
                    console.log(this.vdata)
                } else {
                    // 使用Vue.set方法可以出發視圖更新
                    Vue.set(this.vdata, 1, 'json')
                    console.log(this.vdata)
                }
            },
            add(a){
                if (a==0) {
                    // 添加屬性,同樣直接添加無法觸發視圖更新
                    this.vitem.apple = "喬布斯"
                    console.log(this.vitem)
                } else if(a==1) {
                    //這時候修改還是需要靠Vue.set
                    Vue.set(this.vitem, "Microsoft", "比爾蓋茨")
                    console.log(this.vitem)
                } else {
                    // 雖然添加的時候無法觸發視圖更新,但修改的時候可以
                    this.vitem.smartisan = "行業冥燈"
                }
            }

        }
     });
    </script>
</html>

在這裏插入圖片描述

計算屬性

一般情況下,我們都會將屬性放在Vue的data中,但有些屬性我們可以需要進行一些邏輯計算。我們可以將這樣的屬性變成計算屬性computed

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome14</title>
</head>

<body>

    <div id ="app">
        <p>計算圓面積</p>
        請輸入半徑: <input type="text" v-model="radius">
        <p>{{radius*radius*3.14}}</p>
        <!-- 調用方法(methods)我們需要加括號 -->
        <p>{{m_area()}}</p>
        <!-- 但是直接調用計算屬性的時候我們不需要加括號(類似python中的property裝飾器將方法變爲屬性) -->
        <p>{{c_area}}</p>
        <button @click="item">記錄當前半徑</button>
        <p>{{vdata}}</p>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            radius : 0,
            vdata: []
        },
        methods: {
            // 將計算屬性放在methods中
            m_area(){
                console.log('methods被調用了')
                return this.radius*this.radius*3.14
            },
            item(){
                this.vdata.push(this.radius)
            }
        },
        computed: {
            // 將計算屬性放在專門爲其設立的computed中
            c_area(){
                console.log('computed被調用了')
                return this.radius*this.radius*3.14
            }
        }
     });
    </script>
</html>

你可能對此有所疑問,計算函數爲什麼不直接放在方法中(methods)中,而要放在專門爲其設立的計算屬性(computed)中?他們有什麼區別嗎?
實際上,計算屬性更加智能,他是基於它們的響應式依賴進行緩存的。也就是說只要相關依賴(上面的c_area)沒有發生改變,那麼計算屬性的函數不會重新執行,而是直接返回之前的值。這個緩存功能讓計算屬性訪問更加高效
在這裏插入圖片描述
從上述圖片可以看出,寫在計算屬性computed中的方法只有在計算的時候纔會被調用,而methods中的方法,只要視圖發送更新,他就會被調用。

計算屬性中的set

計算屬性默認只有get,不過在需要的時候,我們也可以做一個set。但提供set的前提是有get方法。get是得到,一般是要返回的;set是設置,不用返回。說的直白點就是計算屬性默認只能根據this得到的值進行計算,而不能接收參數,根據參數計算。在上面計算屬性代碼中,我也有提到計算屬性computed和方法methods調用都不相同,調用computed是像屬性一樣不用加括號的。這也就導致了無法傳入參數,而set方法就能解決這個問題。

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome15</title>
</head>

<body>

    <div id ="app">
        <p>計算圓面積</p>
        <!-- .lazy是雙向綁定的一個修飾符,用於等待輸入完成後在出發更新 -->
        請輸入半徑: <input type="text" v-model.lazy="radius">
        <!-- 如果不理解雙向綁定可以看我的博客(https://xunmi.blog.csdn.net/article/details/106854178) -->
        <input type="text" v-model.lazy="area">
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            radius : 0
        },
        computed: {
            // 注意,如果需要添加get和set,這裏就不是函數了(area:function(){}或area(){}變成了area:{})
            area:{
                get(){
                    return this.radius*this.radius*3.14
                },
                // set可以接受參數,然後根據參加直接計算
                set(value){
                    this.radius = (value/3.14)**0.5
                }
            }
        }
     });
    </script>
</html>

在這裏插入圖片描述

監聽屬性

監聽屬性顧名思義,可以針對某個屬性進行監聽,只要這個屬性的值發生改變了,那麼就是執行相應的函數。監聽屬性存放在Vue的watch中,並且創建使用需要監聽的屬性進行命名的方法,監聽器中的方法默認會有兩個參數,分別爲改變之前的參數和改變之後的參數。

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome16</title>
</head>

<body>

    <div id ="app">
        請輸入:<input type="text" v-model="keyword">
        <P>{{vdata}}</P>
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
     //創建Vue實例
     var vm = new Vue({
        el: '#app',
        data: {
            keyword : "",
            vdata : ""
        },
        watch: {
            // 使用需要監聽的屬性進行命名
            keyword(newValue, oldValue){
            	// 並且監聽器中的方法默認會有兩個參數,分別爲改變之前的參數和改變之後的參數
                console.log("變更前的久值: "+oldValue)
                console.log("變更後的新值: "+newValue)
                this.vdata = "當前輸入的內容由: -> " + oldValue + " <- 變更爲 -> " + newValue + " <- 新值共:" + newValue.length + "個字。"
            }
        }
     });
    </script>
</html>

在這裏插入圖片描述

過濾器

過濾器可以過濾一些用戶輸入的字符,可以用於防範一些xss攻擊!

使用

過濾器可以用於兩個地方: 雙花括號值{{}}v-bind(Vue2.1版本之後支持)中。過濾器應該被添加在JavaScript表達式尾部,用"管道符"|連接。

定義

過濾器的定義也有兩種,一種是在組件選項中定義的本地過濾器filters,另一種是在創建Vue實例之前定義的全局過濾器Vue.filter

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>dome17</title>
</head>

<body>

    <div id ="app">
        請輸入: <input type="text" v-model="vdata"> (其中英文狀態下單雙引號將會被過濾)
        <!-- 過濾器在{{}}雙大括號中可以調用 -->
        <p>{{vdata|xss}}</p>
        <!-- 過濾器在v-bind綁定中也可以使用 -->
        <input type="text" :value="vdata|leach" placeholder="全局過濾器">
    </div>

</body>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script>
    // 全局過濾器
    Vue.filter('leach', (value)=>{
        console.log("全局過濾器接收的值:"+value)
        // .replace()中我放入的是一個正則表達式
        // js的正則表達式需要使用 `//`包裹, 雙斜槓中的反斜槓是用來轉義單、雙引號用的,其中g是指的批量替換(如果沒有g只會替換一個)
        value = "我是全局過濾器:"+value.replace(/\"/g,"").replace(/\'/g,"")
        return value
    })
    //創建Vue實例
    var vm = new Vue({
    el: '#app',
    data: {
        vdata : '',
        filter : ''
    },
    // 本地過濾器
    filters: {
        // xss: (value)=>{} 是xss: function(value){}的簡寫, =>可以取代匿名函數中的function
        xss: (value)=>{
            console.log("本地過濾器接收的值:"+value)
            value = "我是本地過濾器:"+value.replace(/\"/g,"").replace(/\'/g,"")
            return value
        }
    }});
    </script>
</html>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章