Vue学习(四)过滤器、自定义指令

Vue的监测

  • vue会监测data中所有层次的数据。
  • vue检测对象中的数据的原理:通过setter实现监测,且要在new Vue时就传入要检测的数据。
    • 对象中后追加的属性,vue默认不作响应式处理
    • 如果要给后添加的属性做响应式,要使用一下API来添加属性:Vue.set(target, propertyName/index, value)或者vm.$set(target, propertyName/index, value)
  • vue检测数组中的数据的原理:通过包裹数组更新元素的方法实现,本质是,调用原生的对应的方法对数组进行更新,然后重新解析模板,进而更新页面
  • 在vue修改数组中的某个元素时一定要使用如下方法:
    • 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • Vue.set()或者vm.$set()
  • Vue.set()或者vm.$set()不能给 vm 或者 vm的根数据对象 添加属性

监测测试案例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="text/javascript" src="../vue.js"></script>
  </head>
  <body>
    <div id="root">
      <h3>你好,{{name}} </h3><br/>
      <h3>学生姓名是:{{student.name}}</h3>
      <h3>学生年龄是:{{student.age}}</h3>
      <h3>学生性别是:{{student.sex}}</h3>
      <ul>
        <li v-for="(person,index) in persons" :key="person.id">
          姓名:{{person.name}}  --年龄:{{person.age}}
        </li>
      </ul>
      <button @click="student.age++">年龄加一</button>
      <button @click="addSex">添加性别</button>
      <button @click="addFriend">添加人员</button>
      <button @click="updateFirstFriendName">更新第一人名字</button>
    </div>
  </body>
  
  <script type="text/javascript">
    let vm = new Vue({
      el:'#root',
      data:{
        name:'李二狗',
        student:{
          age:19,
          name:"曼波"
        },
        persons:[
          {id:'001',name:'张三',age:18},
          {id:'002',name:'李四',age:19},
          {id:'003',name:'王五',age:20}
        ]
      },
      methods:{
        addSex(){
          Vue.set(this.student,"sex","男")
          //this.$set(this.student,"sex","男")
        },
        addFriend(){
          this.persons.unshift({id:"004",name:"jack",age:19})
        },
        updateFirstFriendName(){
          this.persons[0].name = "哈基米"
        }
      }
    })
  </script>
</html>

收集表单数据

  • 若是文本框这种输入类型,v-model收集的是value属性的值,用户输入的内容就是value
  • 若是单选框,v-model收集的是选项的value,要给选项配好value属性
  • 若是多选框,没有配置value属性,那么收集的就是checked属性(勾选就是true,不勾选就是false)。配置了value值后,绑定的data中的数据要是一个数组,各个多选的值会成为数组中的元素。
  • v-model的三个修饰符:
    • lazy:失去了焦点再收集数据,默认是边输入边收集
    • number:输入的字符串转化为数字
    • trim:输入首尾空格过滤

收集表单数据案例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="text/javascript" src="../vue.js"></script>
  </head>
  <body>
    <div id="root">
      <form>
        <label for="demo">账号:</label>
        <input type="text" id="demo" v-model="account"><br><br>
        <label for="demo2">密码:</label>
        <input type="password" id="demo2" v-model="password"><br><br>
        性别:<br>
        <label for="man">男</label><input type="radio" id="man" name="sex" value="man" v-model="sex">
        <label for="woman">女</label><input type="radio" id="woman" name="sex" value="woman" v-model="sex"><br><br>
        爱好:<br>
        <label for="sing">唱</label><input type="checkbox" id="sing" name="hobby" v-model="hobby" value="sing">
        <label for="dance">跳</label><input type="checkbox" id="dance" name="hobby" v-model="hobby" value="dance">
        <label for="rap">rap</label><input type="checkbox" id="rap" name="hobby" v-model="hobby" value="rap">
        <label for="basketball">篮球</label><input type="checkbox" id="basketball" name="hobby" v-model="hobby" value="basketball"><br><br>
        所属校区:<select name="schoolArea" id="schoolArea" v-model="schoolArea">
          <option value=""></option>
          <option value="jiangxi"> 江西 </option>
          <option value="henan"> 河南 </option>
          <option value="zhejiang"> 浙江 </option>
        </select><br><br/>
        其他信息:<textarea v-model="other"></textarea><br><br>
        <input type="checkbox" v-model="agree"><a href="<http://www.atguigu.com>">《用户协议》</a><br><br>
        <button>提交</button>
      </form>
    </div>
  </body>
  
  <script type="text/javascript">
    let vm = new Vue({
      el:'#root',
      data:{
        account:"",
        password:"",
        sex:"",
        hobby:[],
        schoolArea:"",
        other:"",
        agree:""
      }
    })
  </script>
</html>

过滤器

过滤器用于对要使用的数据进行特定操作后再使用(适用于一些简单的逻辑),产生的是一个经过处理的新数据。

注册过滤器

局部过滤器

使用Vue实例的filters属性进行注册过滤器,例:

new Vue({
        el:"#root",
        data:{
            hello:"哈哈哈",
            time:1621561377603 //时间戳
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
            }
        },
        //局部过滤器
        filters:{
            filterTest(value){
                return dayjs(value).format('YYYY-MM-DD HH:mm:ss')
            },
            filterTest2(value,str="YYYY-MM-DD HH:mm:ss"){
                return dayjs(value).format(str)
            },
            mySlice(value){
                return value.slice(0,4)
            }
        }
    })

在filters属性中,其中的方法的方法名就是过滤器的名称,return返回的是过滤后的结果,value和其他参数的说明在以下过滤器的使用中阐述。

全局过滤器

使用Vue.filter(name,callbackFunction)注册全局过滤器,要在Vue实例的初始化之前就注册,例:

//全局过滤器
    Vue.filter("mySlice2",function(value){
        return value.slice(0,2)
    })

过滤器的使用

在表达式中,比如{{}}中的表达式或者一些属性(v-bind等)的属性值表达式中,使用管道符来表示使用过滤器,最终的结果就是过滤器产生的结果,例:

<h3>(过滤器)现在是:{{time | filterTest}}</h3>

此时time便会变成以上过滤器中的方法(见局部过滤器中的案例)的那个value参数,即管道符左边的表达式的结果会变成管道符右边的过滤器的value参数。

如果要加入别的参数,在管道符右边的过滤器中加上括号,在括号中加入其他参数即可,但是此时的管道符右边的参数在filters属性的方法中是从第二个参数算起的,因为第一个参数永远是管道符左边表达式的结果产生的value值(即管道符右边的第一个参数是filters中的方法的第二个参数,第二个参数是filters中的第三个参数,以此类推)。例:

<h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD")}}</h3>

同时,过滤器还可以嵌套使用,计算顺序是从左到右,即第二个过滤器产生的结果就是第三个过滤器的value参数值,例:

<h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD") | mySlice}}</h3>

过滤器的整体案例如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="icon" href="favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="<https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.12/dayjs.min.js>"></script>
    <script type="text/javascript" src="../vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>显示格式化之后的时间</h2>
        <h3>现在是:{{fmtTime}}</h3>
        <h3>(过滤器)现在是:{{time | filterTest}}</h3>
        <h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD")}}</h3>
        <h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD") | mySlice}}</h3>
        <h3>{{hello | mySlice2}}</h3>
    </div>
    <div id="root2">
        <h2>{{msg | mySlice2}}</h2>
    </div>
</body>
<script>
    //全局过滤器
    Vue.filter("mySlice2",function(value){
        return value.slice(0,2)
    })

    new Vue({
        el:"#root",
        data:{
            hello:"哈哈哈",
            time:1621561377603 //时间戳
        },
        computed:{
            fmtTime(){
                return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
            }
        },
        //局部过滤器
        filters:{
            filterTest(value){
                return dayjs(value).format('YYYY-MM-DD HH:mm:ss')
            },
            filterTest2(value,str="YYYY-MM-DD HH:mm:ss"){
                return dayjs(value).format(str)
            },
            mySlice(value){
                return value.slice(0,4)
            }
        }
    })
    new Vue({
        el:"#root2",
        data:{
            msg:"你好呀"
        }
    })
</script>
</html>

其他内置指令

内置指令复习

v-bind:单向绑定解析表达式

v-model:双向数据绑定

v-for:遍历数组、对象、字符串

v-on:绑定事件监听,可以简写为@

v-if:条件渲染(动态控制节点是否存在)

v-else:条件渲染(动态控制节点是否存在)

v-show:条件渲染(动态控制节点是否展示)

v-text

作用是解析表达式中的内容,渲染文本内容。

与插值语法的区别:v-text解析后会替换掉整个节点的文本内容,而插值表达式可以动态渲染部分文本内容

v-html

作用是向指定节点中渲染包含html结构的内容。

也是会替换整个节点的所有内容,与v-text的区别是v-html可以识别并解析html结构。

在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。

一定要在可信的内容上使用v-html,不要使用在用户提交的内容上

v-cloak

没有属性值,Vue实例创建完成后并接管容器后,会删掉v-cloak属性。

使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题

v-once

没有属性值,v-once所在节点在初次动态渲染后,就视为静态内容了。

以后数据的改变不会引起v-once所在的结构的更新。

v-pre

没有属性值,跳过其所在的节点的编译过程。

可以利用其跳过没有使用指令语法、没有使用插值语法的节点,会加快编译。

自定义指令

自定义指令在directives属性中进行定义,定义方式有两种

函数式

在directives属性中,新建方法,方法名为自定义自定义指令的指令名。方法有两个参数:

  1. element:代表该自定义指令绑定的那个节点的DOM(为真实DOM)
  2. binging:其中有一些指令相关的信息,比如指令的属性值对应的表达式,指令属性值对应的值(也就是表达式的结果),指令对应的值用binging.value表示

然后在方法内进行定义指令的逻辑,例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="text/javascript" src="../vue.js"></script>
  </head>
  <body>
    <div id="root">
      <h2>当前的n值是:<span v-text="n"></span></h2>
      <h2>放大十倍后的n值是:<span v-big="n"></span></h2>
      <button @click="n++">点我n+1</button>
    </div>
  </body>
  
  <script type="text/javascript">
    let vm = new Vue({
      el:'#root',
      data:{
        name:'李二狗',
        n:12
    },
    directives:{
      big(element,binding){
        element.innerText = binding.value * 10
      }
    }
  })
  </script>
</html>

对象式

在directives属性中,使用对象的形式表示自定义指令的创建,该对象的属性名为自定义指令的指令名。对象中有三个常用方法:

  • bind方法:当指令与元素成功绑定时调用
  • inserted方法:指令所在元素被插入页面时
  • update方法:指令所在的模板被重新解析时

函数式的逻辑其实就是bind方法和update方法用同一个方法体,结合在一起,不过没有inserted,也不能将bind和update方法的逻辑分离。

案例:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="text/javascript" src="../vue.js"></script>
  </head>
  <body>
    <div id="root">
      <h2>当前的n值是:<span v-text="n"></span></h2>
      <h2>放大十倍后的n值是:<span v-big="n"></span></h2>
      <button @click="n++">点我n+1</button>
      <hr><hr>
      <input type="text" v-fbind:value="n">
    </div>
  </body>
  
  <script type="text/javascript">
    let vm = new Vue({
      el:'#root',
      data:{
        name:'李二狗',
        n:12
    },
    directives:{
      big(element,binding){
        element.innerText = binding.value * 10
      },
      fbind:{
        //当指令与元素成功绑定时调用此函数
        bind(element,binding){
          element.value = binding.value
        },
        //指令所在元素被插入页面时调用
        inserted(element,binding){
          element.focus()
        },
        //指令所在的模板重新被解析时调用
        update(element,binding){
          element.value = binding.value
          element.focus()
        }
      }
    }
  })
  </script>
</html>

注:

  • 如果自定义指令的指令名是xxxx-xxxx这种格式的,那么在directives属性中的写法就要写为原始的形式,即属性名为字符串形式,方法也不能使用简写形式,要使用原来的”key”:function(){ }形式
  • 如果定义全局的自定义指令,要使用Vue.directives(”指令名”, 函数式/对象式 写法)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会敲代码的熊mao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值