Vue 基础语法之计算属性(computed)、侦听器(watch)、过滤器(filters)详解

Vue
263
0
0
2023-06-09
目录
  • 1、Vue 实例选项
  • 2、计算属性(computed)
  • 2.1、computed 的基本用法
  • 2.2、computed 作为函数传参
  • 2.3、计算属性和函数的区别
  • 3、侦听器(watch)
  • 3.1、watch 的基本用法
  • 3.2、侦听器的配置项
  • 4、过滤器(filter)
  • 4.1、过滤器有什么用
  • 4.2、全局过滤器
  • 4.3、局部过滤器
  • 4.4、过滤器串联
  • 4.5、过滤器传参

1、Vue 实例选项

在实例化Vue对象时,需要为Vue的构造函数提供一系列的配置信息,代码如下:

new Vue({
	//选项
})

当使用 new 操作符创建 Vue 实例时,可以为实例传入一个选项对象,选项对象中有很多类型的数据,具体内容如下:

  • 数据选项:data、props、propsData、computed、methods、watch
  • DOM选项:el、template、render、renderError
  • 生命周期选项:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed、activated、deactivated、errorCaptured
  • 资源选项:directives、filters、components
  • 组合选项:parent、mixins、extends、provide、inject
  • 其他选项:name、delimiters、functional、model、inheritAttrs、comments

对于选项的学习,大家可以参考 Vue 官网的 API 文档,本章教程中只对 Vue 中的计算属性、过滤器、侦听器三个核心的选项做讲解。

2、计算属性(computed)

2.1、computed 的基本用法

计算属性就是 Vue 实例选项中的 computed,computed 的值是一个对象类型,对象中的属性值为函数,而且这个函数没办法接收参数,如果想为某个计算属性传参的话,可以使用闭包的方式。

这里需要注意的是,计算属性不能声明为箭头函数! 因为箭头函数中的 this 指向的是上下文中的 this,这样就不能在计算属性的函数中获取 Vue 实例对象 this 了。

计算属性有以下特点:

  • 模板中放入太多的逻辑会让模板过重且难以维护,使用计算属性可以让模板更加的简洁。
  • 计算属性是基于它们的响应式依赖进行缓存的。
  • computed比较适合对多个变量或者对象进行处理后返回一个结果值,也就是数多个变量中的某一个值发生了变化则我们监控的这个值也就会发生变化。

示例代码:

<div id="app">
	<p>{{ total }}</p>
</div>
<script type="text/javascript">
	new Vue({
		el: '#app',
		data: {
			a:
		},
		computed: {
			total(n) {
				return this.a +
			}
		}
	})
</script>

在浏览器中运行的结果如下:

在这里插入图片描述

2.2、computed 作为函数传参

computed 对象的属性值虽然是声明为函数,computed 的用法是和 data 一样的,作为属性使用,如果要把 computed 作为函数使用,可以返回一个闭包函数。示例代码如下:

<div id="app">
	<p>{{ total() }}</p>
</div>
<script type="text/javascript">
	new Vue({
		el: '#app',
		data: {
			a:
		},
		computed: {
			total() {
				return (n) => {
					return this.a + n
				}
			}
		}
	})
</script>

在浏览器中运行的效果如下:

在这里插入图片描述

2.3、计算属性和函数的区别

虽然计算属性(computed)和函数(methods)的声明过程是很相似的,但是功能上还是有所差别的,其中最大的区别就是 计算属性可以根据它所依赖的响应式数据进行缓存 ,简单来说,就是在计算属性声明的函数中,如果染回值依赖了 data 中声明的响应式数据的话,只有当依赖的 data 中的数据发生变化时,当前的计算属性函数才会重新执行,否则的话就直接获取上次执行后缓存的结果。这样做的好处是可以提高性能,减少不必要的重复运算。

示例代码如下:

<div id="app">
     <!--  
        当多次调用 reverseString  的时候 
        只要里面的 num 值不改变 他会把第一次计算的结果直接返回
    直到data 中的num值改变 计算属性才会重新发生计算
     -->
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
     <!-- 调用methods中的方法的时候  他每次会重新调用 -->
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
  </div>
  <script type="text/javascript">
    /*
      计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao',
        num:
      },
      methods: {
        reverseMessage: function(){
          console.log('methods')
          return this.msg.split('').reverse().join('');
        }
      },
      //computed属性的声明和data属性、methods属性是平级关系 
      computed: {
        //reverseString属性名称是自定义的 
        reverseString: function(){
          console.log('computed')
          var total =;
          // 当data中num 属性的值发生改变时,reverseString 函数会自动进行计算  
          for(var i=;i<=this.num;i++){
            total += i;
          }
         // 在reverseString函数中必须要有return,否则在页面中无法获取到计算后的值    
          return total;
        }
      }
    });
  </script>

2.4、计算属性的 getter 和 setter 函数

计算属性虽然可以像 data 属性一样取值,但是如果要对计算属性赋值的话,必须使用 setter 方法,示例代码如下:

<div id="app">
     <!--  
        当多次调用 reverseString  的时候 
        只要里面的 num 值不改变 他会把第一次计算的结果直接返回
    直到data 中的num值改变 计算属性才会重新发生计算
     -->
    <div>{{reverseString}}</div>
    <div>{{reverseString}}</div>
     <!-- 调用methods中的方法的时候  他每次会重新调用 -->
    <div>{{reverseMessage()}}</div>
    <div>{{reverseMessage()}}</div>
  </div>
  <script type="text/javascript">
    /*
      计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao',
        num:
      },
      methods: {
        reverseMessage: function(){
          console.log('methods')
          return this.msg.split('').reverse().join('');
        }
      },
      //computed属性的声明和data属性、methods属性是平级关系 
      computed: {
        //reverseString属性名称是自定义的 
        reverseString: function(){
          console.log('computed')
          var total =;
          // 当data中num 属性的值发生改变时,reverseString 函数会自动进行计算  
          for(var i=;i<=this.num;i++){
            total += i;
          }
         // 在reverseString函数中必须要有return,否则在页面中无法获取到计算后的值    
          return total;
        }
      }
    });
  </script>

点击重新计算按钮之前:

在这里插入图片描述

点击重新计算按钮之后:

在这里插入图片描述

在 reset() 函数中为计算属性 total 赋值,会被计算属性中的 set() 函数接收,然后再把值传给 data 中的 a 变量,那么此时获取到的计算属性值就是更新后的 a 变量 +5 之后的结果。

3、侦听器(watch)

3.1、watch 的基本用法

watch是监听器,其值为一个对象,对象中的属性值可以为函数、对象和数组。当data中的一个属性需要被观察期内部值的改变时,可以通过watch来监听data属性的变化。

watch监听器的基本用法如下:

  • 使用watch来响应数据的变化
  • 一般用于异步或者开销较大的操作
  • watch 中的属性 一定是data 中 已经存在的数据
  • 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听

示例代码:

<!-- 验证用户名 -->
<div id="app">
  <div>
    姓:<input type="text" v-model='lastName'>
  </div>
  <div>
    名:<input type="text" v-model='firstName'>
  </div>
  <div>
  	全名:{{fullName}}
  </div>
</div>

<script type="text/javascript">
  var vm = new Vue({
    el: '#app',
    data: {
      firstName: '张',
      lastName: '三'
    },
    // 计算属性
    watch: {
      firstName(val) {
        this.fullName = val + ' ' + this.lastName;
      },
      lastName(val) {
        this.fullName = this.firstName + ' ' + val;
      }
    }
  });
</script>

watch 对象中的 firstName 对应着 data 中的 firstName ,当 firstName 值发生改变时会自动触发 watch 中的 firstName() 函数的执行。同理,watch 中的 lastName 对应的也是 data 中的 lastName。

watch 对象中的函数属性的参数有两个,参数一是对应 data 中相同变量名属性被修改后的新值,参数二是该 data 属性修改前的旧值。

3.2、侦听器的配置项

如果要监听的 data 属性值是一个对象或者是数组,如果对象嵌套层级比较深的情况下,需要开启 watch 的深度监听。示例代码如下:

new Vue({
	el: '#app',
	data: {
		num: {
			a:,
			b:,
			c: {
				d:
			}
		}
	},
	watch: {
		num: {
			deep: true, // 开启深度监听
			handler(val, oldVal) {
				//...
			}
		}
	}
})

4、过滤器(filter)

4.1、过滤器有什么用

  • Vue.js允许自定义过滤器,可被用于一些常见的文本格式化。
  • 过滤器可以用在两个地方:双花括号插值和v-bind表达式。
  • 过滤器应该被添加在JavaScript表达式的尾部,由“管道”符号指示

4.2、全局过滤器

Vue 的全局 API 中提供了注册全局过滤器的函数 Vue.filter(),全局过滤器注册好之后所有的组件可以使用。

全局过滤器示例代码:

<div id="app">
    <input type="text" v-model='msg'>
      <!-- upper 被定义为接收单个参数的过滤器函数,表达式  msg  的值将作为参数传入到函数中 -->
    <div>{{msg | upper}}</div>
    <!--  
      支持级联操作
      upper  被定义为接收单个参数的过滤器函数,表达式msg 的值将作为参数传入到函数中。
	  然后继续调用同样被定义为接收单个参数的过滤器 lower ,将upper 的结果传递到lower中
 	-->
    <div>{{msg | upper | lower}}</div>
    <div :abc='msg | upper'>测试数据</div>
  </div>

<script type="text/javascript">
  //  lower  为全局过滤器     
  Vue.filter('lower', function(val) {
    return val.charAt().toLowerCase() + val.slice(1);
  });

  new Vue({
  	el: '#app'
  })
</script>

4.3、局部过滤器

局部过滤器被声明在 Vue 实例对象选项中的 filters 中,这里需要注意的是,全局注册时是filter,没有s的,而局部过滤器是filters,是有s的。

局部过滤器注册好之后只能在注册的组件内使用,示例代码如下:

var vm = new Vue({
  el: '#app',
  data: {
    msg: ''
  },
  filters: { 
    upper: function(val) {
      return val.charAt().toUpperCase() + val.slice(1);
    }
  }
});

filters 属性 定义 和 data 已经 methods 平级,定义 filters 中的过滤器为局部过滤器。上面代码中的 upper 是自定义的过滤器名字,upper 被定义为接收单个参数的过滤器函数,表达式 msg 的值将作为参数传入到函数中。过滤器中一定要有返回值,这样外界使用过滤器的时候才能拿到结果。

4.4、过滤器串联

并且过滤器可以串联使用, 在此处是将filter1的值作为filter2的参数。

{{  data | filter | filter2  }}

4.5、过滤器传参

示例代码如下:

<div id="box">
  {{ message | filterA('arg', 'arg2') }}
</div>
<script>
	  Vue.filter('filterA',function(n,a,b){
		 if(n<){
		   return n+a;
		 }else{
		   return n+b;
		 }
	});

	new Vue({
	  el:"#box",
	  data:{
	    message: "哈哈哈"
	  }
	})
</script>

上面代码中,filterA 被定义为接收三个参数的过滤器函数。其中 message 的值作为第一个参数,普通字符串 ‘arg1’ 作为第二个参数,表达式 arg2 的值作为第三个参数。

在过滤器中第一个参数 对应的是管道符前面的数据 n 此时对应 message,第2个参数 a 对应 实参 arg1 字符串,第3个参数 b 对应 实参 arg2 字符串。