一文搞懂 filter、computed、watch

878 阅读1分钟

过滤器 filter

filter

作用: 可被用于一些常见的文本格式化

使用方式:添加在 JavaScript 表达式的尾部,由“管道”符号指示

  • 全局注册(main.js)

    // main.js
    import Vue from 'vue';
    import Demo from './demo.vue';
    import { Button, Modal } from 'ant-design-vue';
    import { translate } from '@ctrip/ebk-utils';
    import { APPID } from '@/service/config';
    
    Vue.config.productionTip = false;
    // antdv 组件
    Vue.use(Button);
    Vue.use(Modal);
    
    // 多语言 filter
    Vue.filter('translate', function(value) {
      return translate(value, APPID);
    });
    
    new Vue({
      render: h => h(Demo)
    }).$mount('#app');
    
    
  • 局部注册

    <template>
      <p>{{ 'Key.Comment.174' | translate }}</p>
    </template>
    <script>
    import { translate } from '@ctrip/ebk-utils';
    import { APPID } from '@/service/config';
    export default {
      data() {
        return {
        };
      },
      filters: {
        translate(val) {
          return translate(value, APPID);
        }
      }
    };
    </script>
    
    

    当全局过滤器和局部过滤器重名时,会采用局部过滤器。

    Q:methods 能实现同样功能,为啥还要用filter

    A: 过滤器可以串联

    {{ message | filterA | filterB }}
    

    filterA 被定义为接收单个参数的过滤器函数,表达式 message 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 filterB,将 filterA 的结果传递到 filterB 中。

计算属性 computed

computed

作用:复杂逻辑包装的包装和复用

用法:在模板中绑定计算属性

<template>
  <div>
    <p>Original message: "{{ message }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
  </div>
</template>
<script>

export default {
  data() {
    return {
      message: 'hello'
    };
  },
  computed: {
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
};
</script>

Q: methods能实现同样功能,为啥还要用computed

A:计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

代码演示:

// index.vue
<template>
  <div>
    <p>Original message: "{{ msg }}"</p>
    <button @click="handleClick">change msg</button>
    
    <Computed :message="msg" />
    
    <Method :message="msg" />
  </div>
</template>
<script>
import Computed from './components/computed';
import Method from './components/method';
export default {
  data() {
    return {
      msg: 'hello'
    };
  },
  components: {
    Computed,
    Method
  },
  methods: {
    handleClick() {
      this.msg = `hello${Math.random()}`;
    }
  }
};
</script>

// components/compute
<template>
  <div>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
  </div>
</template>
<script>
export default {
  props: ['message'],

  computed: {
    reversedMessage: function() {
      console.log('computed was called');
      return this.message
        .split('')
        .reverse()
        .join('');
    }
  }
};
</script>

// components/method
<template>
  <div>
    <p>Methods reversed message: "{{ reversedMessage() }}"</p>
    <p>Methods reversed message: "{{ reversedMessage() }}"</p>
    <p>Methods reversed message: "{{ reversedMessage() }}"</p>
  </div>
</template>
<script>
export default {
  props: ['message'],
  data() {
    return {};
  },
  methods: {
    reversedMessage: function() {
      console.log('methods was called');
      return this.message
        .split('')
        .reverse()
        .join('');
    }
  }
};
</script>

侦听器 watch

watch

作用:可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态

// 当firstName值变化时,watch监听到并且执行
<template>
  <div>
    <h2>fullname: {{ fullName }}</h2>
    <p>firstName:<input type="text" v-model="firstName" /></p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: 'Morgan',
      fullName: ''
    };
  },
  watch: {
    firstName(newValue) {
      this.fullName = `${newValue} ${this.lastName}`;
    }
  }
};
</script>

handler方法和immediate属性

上面的例子是值变化时候,watch才执行,我们想让值最初时候watch就执行就用到了handlerimmediate属性

<template>
  <div>
    <h2>fullName: {{ fullName }}</h2>
    <p>firstName:<input type="text" v-model="firstName" /></p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: 'Morgan',
      fullName: ''
    };
  },
  watch: {
    firstName: {
      handler(newName) {
        this.fullName = newName + ' ' + this.lastName;
      },
      // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法,如果设置了false,那么效果和上边例子一样
      immediate: true
    }
  }
};
</script>

deep属性(深度监听,常用语对象下面属性的改变)

<template>
  <div>
    <p>obj.a: {{ obj.a }}</p>
    <p>obj.a: <input type="text" v-model="obj.a" /></p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      obj: {
        a: 123
      }
    };
  },
  watch: {
    obj: {
      handler(newVal) {
        console.log(newVal, 'obj.a changed');
      },
      immediate: true,
      deep: true
    }
  }
};
</script>