computed打包多个watch

777 阅读2分钟

本文主要描述如何巧妙应用computed来优化多个watch触发执行同一个方法的场景,经典的例子就是:分页、下拉、输入搜索页面。关于computedwatch的相关概念可以阅读 Vue.js的computed和watch是如何工作的?。博主就先不赘述了。话不多说,直接上代码。

  1. 多个watch触发同一个方法

​ 下面是实际开发常见的场景:分页、下拉、输入搜索页面的主要代码。重点代码是watch部分逻辑。这种实现方式的弊端:监听过多,容易重复触发。比如onSizeChange的时候要重置currentPage会触发两次getData。当然也可以不用watch来实现以上功能,这样的话就要绑定各种@change钩子函数,在多处钩子函数调用对应函数,这样显得更加不优美。

<template>
  <div>
    <div>
      <!-- 下拉切换类型 -->
      <el-select v-model="selection.value">
        <el-option
          v-for="item in selection.options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        ></el-option>
      </el-select>
      <!-- 搜索输入框 -->
      <el-input v-model="search.value"></el-input>
      <!-- 分页 -->
      <el-pagination
        v-bind="pagination"
        @size-change="onSizeChange"
        @current-change="onPageChange"
      ></el-pagination>
    </div>
  </div>
</template>

<script>
export default {
  name: "watchPage",
  data() {
    return {
      selection: {
        options: [
          {
            value: "选项1",
            label: "选项1"
          },
          {
            value: "选项2",
            label: "选项2"
          }
        ],
        value: "选项1"
      },
      pagination: {
        currentPage: 1,
        pageSize: 100,
        pageSizes: [100, 200, 300, 400],
        layout: "total, sizes, prev, pager, next, jumper",
        total: 400
      },
      search: {
        label: "",
        value: ""
      }
    };
  },
  watch: {
    "search.value": "getData",
    "selection.value": "getData",
    "pagination.currentPage": "getData",
    "pagination.pageSize": "getData"
  },
  methods: {
    // 请求搜索后的分页数据
    getData() {
      const { currentPage, pageSize } = this.pagination;
      const postData = {
        currentPage, // 当前页
        pageSize,
        search: this.search.value, // 搜索值
        type: this.selection.value // 下拉值
      };
      console.log(postData);
      // api.getData(postData).then(res => {
      //   // ....
      // });
    },
    onSizeChange(val) {
      this.pagination.currentPage = 1;
      this.pagination.pageSize = val;
    },
    onPageChange(val) {
      this.pagination.currentPage = val;
    }
  }
};
</script>

  1. computed打包多个watch

    下面是通过computed打包多个watch的代码,主要关注点computed、watch、getData的变化。

    <template>
      <div>
        <div>
          <!-- 下拉 -->
          <el-select v-model="selection.value">
            <el-option
              v-for="item in selection.options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
          <!-- 搜索输入框 -->
          <el-input v-model="search.value"></el-input>
          <!-- 分页 -->
          <el-pagination
            v-bind="pagination"
            @size-change="onSizeChange"
            @current-change="onPageChange"
          ></el-pagination>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: "computedPage",
      data() {
        return {
          selection: {
            options: [
              {
                value: "选项1",
                label: "选项1"
              },
              {
                value: "选项2",
                label: "选项2"
              }
            ],
            value: "选项1"
          },
          pagination: {
            currentPage: 1,
            pageSize: 100,
            pageSizes: [100, 200, 300, 400],
            layout: "total, sizes, prev, pager, next, jumper",
            total: 400
          },
          search: {
            label: "",
            value: ""
          }
        };
      },
      computed:{
        // 打包需要监听的值
        postData(){
          const { currentPage, pageSize } = this.pagination;
          return {
            currentPage, // 当前页
            pageSize,
            search: this.search.value, // 搜索值
            type: this.selection.value // 下拉值
          }
        }
      },
      watch: {
        "postData": "getData",
      },
      methods: {
        // 请求搜索后的分页数据
        getData() {
          console.log(this.postData); // 直接使用 computed 属性
          // api.getData(postData).then(res => {
          //   // ....
          // });
        },
        onSizeChange(val) {
          this.pagination.currentPage = 1;
          this.pagination.pageSize = val;
        },
        onPageChange(val) {
          this.pagination.currentPage = val;
        }
      }
    };
    </script>