从Django后端(python)角度学习前端VUE框架基础-下(触发视图更新,计算属性,监听器,过滤器) ∠( °ω°)/ 前端知识

177 阅读5分钟

文章目录


看这边博客前需要知道v-bind,v-modle,v-on这三个是干什么用的,下方会大量用到,如果不清楚可以看我的 博客(xunmi.blog.csdn.net/article/det…)

触发视图更新

常用方法

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>

在这里插入图片描述