Vue(二) 计算属性computed、监视属性watch、绑定class和style、条件渲染v-show,v-if;列表v-for,key的原理、收集表单数据、过滤器|

1. 计算属性与监视属性

1.1 计算属性 computed

Vue中的属性指的是data里的内容,利用已有的属性进行计算所得到的叫计算属性。
场景需求:输入姓,名,显示姓-名,并随输入的变化而变化
在这里插入图片描述
1、使用插值或方法实现:

<div id="root">
    姓:<input type="text" v-model="firstName"><br /><br />
    名:<input type="text" v-model="lastName"><br /><br />
    <!-- 如果还需对属性进行其他操作,则js表达式会更长
		而插值里的表达式应该写的简单易懂,不应太复杂 -->
    全名插值:{{firstName.slice(0,3)}}-{{lastName}}<br /><br />
    <!-- 这里是js表达式,fullName()是调用,得加小括号 -->
     <!--若写两次,就要调用两次 -->
    全名方法:{{fullName()}}<br /><br />
    全名方法:{{fullName()}}<br /><br />
</div>
<script>
	const vm = new Vue({
		el: '#root',
		data: {
			firstName: '张',
			lastName: '三'
		},	
		methods: {
			fullName () {
				return this.firstName + '-' + this.lastName
			}
		}
	})
</script>

当data里的数据发生变化时,Vue模板的内容需要重新被解析,所以函数也会被重新调用。从而实现根据输入框内容实时更新全名。

  • 用插值表达式的缺点是:如果数据处理再复杂一点,插值表达式会很复杂
  • 用方法实现该效果的缺点是:多次用该数据,就要调用多次函数

2、计算属性的写法:

<div id="root">
    姓:<input type="text" v-model="firstName"><br /><br />
    名:<input type="text" v-model="lastName"><br /><br />
    全名计算属性:{{fullNameCom}}<br /><br />
    全名计算属性:{{fullNameCom}}<br /><br />
    全名计算属性:{{fullNameCom}}<br /><br />
    全名计算属性:{{fullNameCom}}<br /><br />
</div>
<script>
    const vm = new Vue({
        el: '#root',
        data: {
            firstName: '张',
            lastName: '三'
        },
        //计算属性
        computed: {
            fullNameCom: {
                get () {
                    // 此处的this指向的是vm;改为箭头函数则不指向vm了
                    console.log('get读取属性');
                    return this.firstName + '-' + this.lastName
                },
                set (value) {
                    console.log('set', value);
                    this.firstName = value.split('-')[0]
                    this.lastName = value.split('-')[1]
                }
            }
        },
    })
</script>

几点说明:
(1) 计算属性
计算属性最终会出现在vm上(以属性的形式,不是对象的形式),直接读取使用即可。 如果计算属性要修改,必须写set函数去响应修改。
计算属性底层借助了Object.definepeoperty方法提供的getter和setter方法。
data里的数据放在了vm._data里,但是计算属性并未放在vm._data里,而是放在vm身上
在这里插入图片描述

(2) 计算属性的get方法

get方法是用来获取计算属性的,在两种情况下会执行:

  • 初次读取fullNameCom时。
  • 当所依赖的属性发生变化时

虽然代码中调用了4次计算属性,但是控制台只打印了一次get读取属性,即只调用了一次get方法,这是因为会把初次读取的计算属性放入缓存中。与methods相比,内部有缓存机制(复用),效率更高。

3. 计算属性的set方法
当fullNameCom被修改时,set方法会被调用,进而修改data中的属性,进而重新计算fullNameCom的值。
在这里插入图片描述
一般都不会写set方法。

简写形式:
当不考虑修改,只考虑读取(get)时,可简写为

const vm = new Vue({
    ...
    computed: {
        fullNameCom () {
            // function默认指的就是get方法
            console.log('get读取属性');
            return this.firstName + '-' + this.lastName
        }
    }
})

1.2 监视属性 watch

watch基本使用

  • 当被监视的属性变化时, 回调函数(handler)自动调用, 进行相关操作
  • 监视的属性(data中的属性或计算属性)必须存在,才能进行监视!!(如果不存在,也不会报错)
  • 监视的两种写法:
    • new Vue时传入watch配置
    • 通过vm.$watch监视
<div id="root">
    <h1>今天天气很{{info}}</h1>
    <!-- 当绑定事件@click=xxx的操作很少时,也可以直接写在xxx里面 -->
    <button @click="isHot =!isHot">切换天气</button>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data: {
            isHot: true
        },
        computed: {
            info () {
                return this.isHot ? '炎热' : '凉爽'
            }
        },
        watch: {
	        isHot: {
	          immediate: true, // 默认是false,true意味着初始化的时候调用一下handler
	          handler (newvalue, oldValue) {
	            console.log('isHot:改为' + newvalue, oldValue);
	          }
          }
        }
    })
    //写法2:
    vm.$watch('isHot', {
      handler (newValue, oldValue) {
        console.log('isHot被修改了', newValue, oldValue)
      }
    })
</script>

在这里插入图片描述
immediate属性的应用看4.2的列表过滤

深度监视deep

现在data里有一个多级结构的属性

<div id="root">
    <h1>a的值是{{numbers.a}}</h1>
    <button @click="numbers.a++">a++</button>
</div>
<script>
    const vm = new Vue({
        ...
        data: {
            numbers: {
                a: 1,
                b: 2,
                obj: {
                    c: 3
                }
            }
        }
    })
</script>

监视numbers里a的变化:

    const vm = new Vue({
   ...  
      watch: {
          // 监视a,正常写属于应该有引号,之前别的属性没写是vue会给加上引号
        'numbers.a': {
          handler (newvalue, oldValue) {
            console.log('a被修改为:' + newvalue);
          }
        }
      }
    })

监视number所有数据的变化

// 若不加deep属性,无论是a变还是c变,这个方法都不调用,因为numbers存的是地址值。除非加上deep:true
     numbers: {
        deep: true,
        handler (newValue) {
          console.log(newValue);
          // 加入检测其中c的变化
          console.log('numbers的被修改', newValue.obj.c);
        }
      }

在这里插入图片描述
总结:

  • Vue中的watch默认不监测对象内部值的改变(一层);
  • 配置deep:true可以监测对象内部值改变(多层)
  • Vue自身可以监测对象内部值的改变,即控制台vm.numbers.a可以得到a的新值,但Vue提供的watch默认不可以!

watch简写

当不需要设置deep等属性,只写handler函数时,可简写为:

// watch第一种方式的简写  
isHot (newvalue, oldValue) {
    console.log('isHot:改为' + newvalue, oldValue);
    console.log(this); //指向vm
},
// watch第二种方式的简写
vm.$watch('isHot', function (newValue, oldValue) {
    console.log('isHot被修改了', newValue, oldValue)
    console.log(this); // this指向vm
 })

写成箭头函数则this不会指向vue

1.3 watch与computed的区别

  • computed能完成的功能,watch都可以
  • watch可以进行异步操作,但computed不行
    比如,异步操作setTimout里写匿名函数,由于computed必须要一个return返回值,在setTimout的匿名函数里,返回值无法交给计算属性。因此不行;而watch里不需要return,通过this可修改值,所以可以进行异步操作

还是姓名的案例,3S后显示新的全名
1. computed

const vm = new Vue({
    el: "#root",
    data: {
        firstName: '张',
        lastName: '三',
    },
    // 计算属性
    computed: {
        fullName () {
            setTimeout(() => {
                // return 返回给了setTimeout里的这个匿名函数,fullName拿不到返回值,所以无法进行异步操作
                return this.firstName + '-' + this.lastName
            })
        }
    }
})

2.watch

const vm = new Vue({
    el: "#root",
    data: {
        firstName: '张',
        lastName: '三',
        fullName: '张-三'
    },
    // 监视
    watch: {
        firstName (newValue, oldValue) {
            // firstName是Vue管理的函数,还是普通函数,所以this指向vm
            console.log(this);
            // 异步
            setTimeout(() => {
                // 箭头函数没有自己的this,则往外找,往外找就是firstName的this,即为vm
                this.fullName = newValue + '-' + this.lastName
            }, 3000)
        }lastName (newValue, oldValue) {...}
    }
})

这里需要注意setTimeout里一定要写箭头函数,否则this不会指向vm。比如lastName里

lastName (newValue, oldValue) {
    setTimeout(function () {
        // function这个匿名函数是JS引擎调用的,有自己的this
        console.log(this); // window
        this.fullName = this.firstName + '-' + newValue
    }, 3000)
}

总结

  1. 被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
  2. 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数, 这样this的指向才是vm 或 组件实例对象。

2 绑定样式

2.1 绑定class类

1、字符串写法:适用于样式的类名不确定,需要动态指定
class指定类名
:class=xxx等价于v-bind:class=xxx:动态绑定类名,xxx为js表达式`,且可以直接读取到data中的所有属性。

<div class="box" :class="bgC" @click="changeColor">小猪佩奇</div>
<script>
    ...
    data: {
        bgC: 'bgColor1',
    },
    methods: {
    // 采用随机数,随机指定样式
        changeColor () {
            arr = ['bgColor1', 'bgColor2', 'bgColor3']
            const index = Math.floor(Math.random() * arr.length)
            this.bgC = arr[index]
          }
   }
</script>

解析后的效果为:
在这里插入图片描述
2、数组写法,适用于:要绑定的样式个数不确定、名字也不确定

<div class="box" :class="classArr">小猪佩奇</div>
<script>
data: {
    // 数组里有哪个类就用哪个
    classArr: ['fontStyle', 'bgColorStyle', 'borderStyle'],
}
</script>

在这里插入图片描述

3、对象写法,适用于已确定样式类的名称,个数,但不确定用哪一个
已确定样式类有borderStylebgColorStyle,但不确定用哪一个

<div class="box" :class="classObj">小猪佩奇</div>
<script>
data: {
  // 为true应用这个类,为false则不用这个类
     classObj: {
       bgColorStyle: false,
       borderStyle: true
     }
}
</script>

可通过更改布尔值来确定用哪个样式

2.2 绑定style样式

包括对象写法和数组写法

<!-- 对象写法 -->
<div class="box" :style="styleObj">小猪佩奇</div>
<!-- 数组写法 -->
<div class="box" :style="[styleObj,styleObj2]">小猪佩奇</div>
<div class="box" :style="styleArr">小猪佩奇</div>
</div>
<script>
   const vm = new Vue({
     el: "#root",
     data: {
       styleObj: {
         fontSize: '40px',
         color: 'red'
       },
       styleObj2: {
         backgroundColor: 'skyblue'
       },
       styleArr: [
         {
           fontSize: '20px',
         },
         {
           color: 'red'
         }
       ]
     },
   })
 </script>

在这里插入图片描述
总结:

  1. class样式
    写法:class=“xxx” xxx可以是字符串、对象、数组。
    字符串写法适用于:类名不确定,要动态获取。
    对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
    数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
  2. style样式
    :style="{fontSize: xxx}“其中xxx是动态值。
    :style=”[a,b]"其中a、b是样式对象。

3、条件渲染

v-show

  • 写法:v-show=“表达式”
  • 适用于:切换频率较高的场景。
  • 特点:不展示的DOM元素未被移除。本质上就是设置元素的display属性值(none/block)
 <h2 v-show="n===1">{{name}}</h2>
 <script>
    const vm = new Vue({
      ...
      data: {
      name: 'Tom and Jerry',
        n: 0
      }
    })
  </script>

在这里插入图片描述
v-if

  • v-if=“表达式” || v-else-if=“表达式” || v-else=“表达式”
  • 适用于:切换频率较低的场景。
  • 特点:不展示的DOM元素直接被移除。
<!-- v-if判断之后,对应的else if则不会再判断条件是否满足.
	此时data里的n为1-->
<h2 v-if="n===1">喜羊羊</h2>
<h2 v-if="n===1">懒羊羊</h2>
<h2 v-else-if="n===1">美羊羊</h2>
<h2 v-else>哈哈</h2>

满足v-if的条件,就不会再判断v-else-if,所以美羊羊不存在
在这里插入图片描述
拓展
v-if与template的联合使用:当条件满足时,解析的页面结构中并不会出现template。

<!-- 若想对一系列元素都进行v-if判断,可在外边包裹一个父元素;
	 若包裹div,则改变了代码的结构-->
<template v-if="n===1">
    <h2>喜羊羊</h2>
    <h2>美羊羊</h2>
    <h2>懒羊羊</h2>
</template>
<div v-if="n===1">
    <h2>小猪佩奇</h2>
    <h2>乔治</h2>
</div>

在这里插入图片描述

4、列表

4.1 列表渲染

1. v-for基本使用

v-for可用来遍历数组、对象、字符串(用的少)
语法:v-for="(item, index) in xxx" :key="yyy"
key可以取遍历的索引index或者其他值,但key取值不能重复

<div id="root">
    <h2>遍历数组</h2>
    <!-- 1.v-for遍历数组,key也可取index值-->
    <ul>
        <li v-for="(item,index) in persons" :key="item.id">
            {{item.id}}--{{item.name}}---{{item.age}}
        </li>
    </ul>

    <h2>遍历对象</h2>
    <!-- 2.遍历对象 (value,key) -->
    <ul>
        <li v-for="(value,key) in dog" :key="index">
            {{key}}--{{value}}
        </li>
    </ul>
</div>
<script>
    const vm = new Vue({
        el: "#root",
        data: {
            persons: [
                { id: '001', name: 'tom', age: 18 },
                { id: '002', name: 'jerry', age: 19 },
                { id: '003', name: 'lucy', age: 20 },
            ],
            dog: {
                name: '小狗',
                price: '10万',
                color: '棕色'
            }
        }
    })
</script>

在这里插入图片描述

2 key原理

1. key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。
2. 虚拟DOM对比算法的规则

  • 首先根据key值,新虚拟DOM寻找key相同的旧虚拟DOM
    • 找到了
      • 若新旧虚拟DOM中内容没变, 直接使用之前的真实DOM
      • 若新虚拟DOM中内容变了, 变化的部分则生成新的真实DOM,没变的部分继续沿用之前的真实DOM。
    • 没找到
      • 创建新的真实DOM,随后渲染到到页面。

3. 当用index作为key时
比如,现有一个数组及新成员老刘的信息:

persons: [
    { id: '001', name: '张三', age: 18 },
    { id: '002', name: '李四', age: 19 },
    { id: '003', name: '王五', age: 20 },
]
const member = { id: '004', name: '老刘', age: 19 }

遍历渲染到列表上,点击按钮时,会将老刘添加在数组首位:

<button @click.once="add">添加新成员</button>
<ul>
    <li v-for="(item,index) in persons" :key="index">
        {{item.id}}--{{item.name}}--{{item.age}}
        <input type="text">
    </li>
</ul>

在添加之前,将页面上的信息粘贴到输入框内
在这里插入图片描述
点击添加后:
在这里插入图片描述
这种情况涉及到底层的虚拟DOM对比算法,结合前边的算法对比规则
在这里插入图片描述
可以看出,在这个例子中,输入框里复制的内容是存在真实DOM里的,而不是虚拟DOM。所以在虚拟DOM对比时,两边的li里边都是一样的input标签,所以input直接沿用之前的真实DOM。

若在数组后边追加新数据,而不是添加在数组前边,则不会有这样的问题

4. 当用数据的唯一标识(id)作为key时
在这里插入图片描述
总结:

  • 如果不写key值,则默认将index作为key值
  • 用index作为key可能会引发的问题:
    • 若对数据进行:逆序添加、逆序删除等破坏顺序操作: 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
    • 如果结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题。
  • 开发中如何选择key
    • 最好使用每条数据的唯一标识作为key
    • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

4.2 列表过滤

需求:已有人员列表,通过输入姓名,对人员列表进行过滤,实现模糊筛选
在这里插入图片描述

<input type="text" placeholder="请输入名字" v-model="keyWord">
 <ul>
   <li v-for="(item,index) in filterPersons">
     {{item.name}}-{{item.age}}-{{item.sex}}
   </li>
 </ul>
<script>
 data: {
        persons: [
          { id: '001', name: '马冬梅', age: 19, sex: '女' },
          { id: '002', name: '周冬雨', age: 20, sex: '女' },
          { id: '003', name: '周杰伦', age: 21, sex: '男' },
          { id: '004', name: '温兆伦', age: 22, sex: '男' }
        ],
        keyWord: '',
      },
</script>

方法一:采用计算属性的方法:

      computed: {
        filterPersons () {
          return this.persons.filter((item) => {
            // indexOf('') --返回0
            // indexOf()---有该字符,返回索引位置;没有则返回-1
            return item.name.indexOf(this.keyWord) !== -1
          })
        }
      }

方法二:采用监听属性的方法:

// data里要提前加上属性 filterPersons:[]
watch: {
  keyWord: {
    immediate: true, // 先调用一次,展示所有列表
    handler () {
      console.log('keyWord改变');
      this.filterPersons = this.persons.filter((item) => {
        return item.name.indexOf(this.keyWord) != -1;
      })
    }
  }
}

此处如果不写immediate: true,则一开始filterPersons是空,列表就什么也不展示;
先调用一次handler(),keyWord为空,indexOf('')的值是0,可以将persons里的内容都赋给filterPersons

总结:优先选择watch写法

4.3 列表排序

在上边过滤的基础上,对过滤出来的数据进行排序
在这里插入图片描述

 <button @click="sortType = 1">年龄升序</button>
 <button @click="sortType = 2">年龄降序</button>
 <button @click="sortType = 0">原顺序</button>
<script>
    computed: {
      filterPersons () {
        const arr = this.persons.filter((item) => {
          return item.name.indexOf(this.keyWord) !== -1
        })
        // 判断是否需要排序 0就是原顺序,不需要排序
        if (this.sortType) {
          console.log(this.sortType);
          arr.sort((p1, p2) => {
            // 1是升序
            return this.sortType === 1 ? p1.age - p2.age : p2.age - p1.age
          })
        }
        return arr
      }
    }
</script>

4.4 Vue监测对象及数组变化的原理

1. 引出问题

在这里插入图片描述
如图所示,点击更新按钮,马冬梅的信息应该得到修改,此时按钮点击事件的回调函数是

updateMei () {
     this.persons[0].name = "马老师"
     this.persons[0].age = 50
     this.persons[0].sex = "男"
}

但是如果改成

updateMei () {
    this.persons[0] = { id: '001', name: '马老师', age: 50, sex: "男" }
}

页面不会更新,但是数据确实是变了
在这里插入图片描述
看完下边的Vue监测数组数据原理的内容后,可知回调函数可以修改为:

updateMei () {
    this.persons.splice(0,1,{ id: '001', name: '马老师', age: 50, sex: "男" })
}

2. Vue监测对象变化原理及模拟数据监测

const vm = new Vue({
    el: "#root",
    data: {
        name: 'tom',
        age: 20
    },
})
  • 在之前的数据代理中可知,data中的数据放在了vm._data身上,当读取vm身上的name属性时,是调用了getter方法,读取了vm._data中的数据;
  • 实际上,data首先被加工,以实现响应式(响应式就是数据变,页面就跟着更新)。然后被放在了vm._data上。当修改name属性时,调用setter方法,而setter方法里实现了重新解析模板。
  • 总结:name被修改,setter方法就会被调用,模板重新被解析,就会生成虚拟DOM,然后新旧虚拟DOM对比,更新页面。
    在这里插入图片描述

模拟对象数据监测:(没太懂)

// 对象监测
let data = {
    name: 'tom',
    age: 10
}
// 创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data)
console.log(obs);

// 准备一个vm实例对象
let vm = {}
vm._data = data = obs

function Observer (obj) {
    // 汇总对象中的所有属性形成一个数组
    const keys = Object.keys(obj)
    // 遍历
    keys.forEach((k) => {
        // this指的是实例 obs,往obs身上加属性
        Object.defineProperties(this, k, {
            get () {
                return obj[k]
            },
            set (value) {
                console.log(`${k}被改了,重新解析模板,生成虚拟DOM`)
                obj[k] = val
            }
        })
    })
}

3. Vue.set方法

需求:现在有这样一组数据的信息展示在页面上,要求点击按钮给students对象添加响应式属性gender,默认值是男
在这里插入图片描述
页面结构:

<h1>姓名:{{students.name}}</h1>
<button @click="aggGender">点击添加属性</button>
<h1 v-if="students.gender">性别:{{students.gender}}</h1>
<h1>年龄:真实{{students.age.rAge}},对外{{students.age.sAge}}</h1>
<h1>朋友们</h1>
<ul>
    <li v-for="f in students.friends">
        {{f.name}}---{{f.age}}
    </li>
</ul>

:data里的students没有gender属性,为什么不报错
:对象里没有这个属性,则这个属性的值是undefined。对于undefined,Vue不会报错;但是如果是缺少gender这个属性,则会报错不存在。

<!-- 这样会报错,因为data里没有定义这个属性 -->
<h1>性别:{{gender}}</h1>

如果通过vm._data.students.gender='男'这种方式添加属性。这样添加上的gender不是响应式的属性,即没有getter和setter
在这里插入图片描述
解决:

  • 语法:Vue.set(target,key,value)
  • 作用:向响应式对象中添加一个property,并确保这个新的property同样是响应式的,且触发试图更新。
  • 注意:set方法里的target不能是vue实例(vm),或者Vue实例的根数据对象(vm.data)
aggGender () {
 // 只能给data里的某一个对象追加属性,并不能给data追加属性
  Vue.set(vm._data.students, 'gender', '男')
  vm.$set(vm._data.students, 'gender', '男')
  //  根据数据代理可知 vm._data.students === vm.students,所以还可以写为:
  Vue.set(vm.students, 'gender', '男')
  vm.$set(vm.students, 'gender', '男')
  // 因为方法里的this指向的是vm,所以还可以写为
  Vue.set(this.students, 'gender', '男')
}

5、收集表单数据

1. 文本输入框
<input type="text"/>,v-model收集的是value值,用户输入的就是value值。

2. 单选框radio
<input type="radio"/>,v-model收集的是value值,且要给标签配置value值。

<div id="root">
    <!-- label: 点击标签表单元素获取焦点 label属性for 通过与表单元素的id 对表单进行关联 -->
    <label for="uname">姓名:</label>
    <input type="text" v-model="uname" id="uname"><br><br>
    性别:
    男<input type="radio" v-model="gender" value="man" /><input type="radio" v-model="gender" value="woman"><br><br>
</div>
<script>
//vue实例里的data
data:{
    uname:'',
    gender:''
}
</script>

在这里插入图片描述
3. 复选框checkbox
<input type="checkbox"/>
1.没有配置input的value属性,那么收集的就是checked(勾选 or 未勾选,是布尔值)
2.配置input的value属性:
​ (1) v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
​ (2) v-model的初始值是数组,那么收集的的就是value组成的数组

<h2>没有配置value</h2>
旅游:
泰山<input type="checkbox" v-model="place">
马尔代夫<input type="checkbox" v-model="place">
海南<input type="checkbox" v-model="place"><br><br>

<!-- data:{hobby: ''} -->
<h2>配置value,data接收的数据是字符串</h2>
爱好:
睡觉<input type="checkbox" v-model="hobby" value="sleep">
吃饭<input type="checkbox" v-model="hobby" value="eat">
游戏<input type="checkbox" v-model="hobby" value="game"><br><br>

<!-- 标准配置 -->
<!-- data:{fruit:[]} -->
<h2>配置value,data接收的数据是数组</h2>
水果:
苹果<input type="checkbox" v-model="fruit" value="apple">
香蕉<input type="checkbox" v-model="fruit" value="banana">
橙子<input type="checkbox" v-model="fruit" value="orange"><br><br>

hobby和place都是只要选一个选项,data就存为true。其他选项也都会被自动勾选
在这里插入图片描述
修饰符

  • lazy:失去焦点再收集数据
  • number:输入字符串转为有效的数字
  • trim:输入首尾空格过滤
<!-- type设为number,则文本框内只能输入数字。number修饰符使得收集到的数据是number类型,而不是字符串 -->
<label for="uname">姓名:</label>
<input type="text" v-model.trim="uname" id="uname"><br><br>
年龄: <input type="number" v-model.number="age"><br><br>
<textarea v-model.lazy="info"></textarea>

在这里插入图片描述

6、过滤器

对要显示的数据进行特定处理后再显示(适用于一些简单逻辑的处理),并没有改变原本的数据, 是产生新的对应的数据。

比如:对时间戳进行处理,显示当前时间。此处用到dayjs库安装 | Day.js中文网

1.使用过滤器
方式一:插值 {{ 要处理的数据xxx | 过滤器名}}
方式二(使用较少):或 v-bind:属性=“xxx | 过滤器名”

2.过滤器参数
默认传递的是要处理的数据xxx,当传多个参数时,过滤器接收到的第一个参数默认为待处理的数据xxx

<!-- 引入dayjs库 -->
<script src="./js/dayjs.min.js"></script> 
<div id="root">
    <h2>显示格式化之后的时间</h2>
    <!-- 插值 无参-->
    <h3>现在是:{{time | timeFormater}}</h3>
    <!-- 插值,有参数 接收到的第一位是value值,即time-->
    <h3>现在是:{{time | timeFormater2('/')}}</h3>
</div>

<script>
    const vm = new Vue({
     。。
        data: {
            //  Date.now() 获取时间戳
            time: 1721268391234,
        },
        filters: {
            timeFormater (value) {
                return dayjs(value).format('YYYY-MM-DD HH:mm:ss')
            },
            timeFormater2 (value, str) {
                return dayjs(value).format(`YYYY${str}MM${str}DD HH:mm:ss`)
            }
        }
    })
</script>

在这里插入图片描述
3.过滤器串联

语法:{{ 要处理的数据xxx | 过滤器1 | 过滤器2}}

<div id="root">
    <h3>现在是:{{time|timeFormater2('-')|mySlice}}</h3>
    <!-- v-bind使用,data里定义属性msg: '云彩很好看' -->
    <input type="text" :name="msg | mySlice">
</div>
<script>
    const vm = new Vue({
        ...
        filters: {
            timeFormater2 (value, str) {
                return dayjs(value).format(`YYYY${str}MM${str}DD HH:mm:ss`)
            },
            // 截取前4位
            mySlice (value) {
                return value.slice(0, 4)
            }
        }
    })
</script>

在这里插入图片描述
4.局部过滤器与全局过滤器
局部过滤器只限本vue实例使用,定义全局过滤器:

// 全局过滤器
 Vue.filter('mySlice', function (value) {
     return value.slice(0, 4)
 })
 const vm = new Vue({
     ...
     // 局部过滤器
     filters: {
         ...
      }
  })
  • 32
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值