不要重复你自己 Don’t repeat yourself

2,654 阅读1分钟

前言

程序员有个信条叫做“不要重复你自己(Don’t repeat yourself, DRY)”

在开发中,为了实现代码的复用,减少冗余。使用公共js工具类方法,公共样式,封装公共组件。

除此之外,还有比较常用的混入mixin功能。

css预加载处理器的混入mixin

使用css预加载处理器,譬如scss,可以通过定义变量和样式混入。

示例

定义变量 variable.scss文件

$blue: #409EFF;
$shadowBg: #f8f8f8;

样式混入 mixin.scss 文件

@mixin clearfix {
  &:after {
    content: "";
    display: table;
    clear: both;
  }
}
​
@mixin border-shadow{
  border-radius: 4px;
  border: 1px solid #ebeef5;
  -webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
}
​
@mixin flex{
  display: flex;
  justify-content: center;
  align-items: center;
}

然后在vue组件中,引入这些公共样式,即可实现代码的复用

<template>
  <div>
    <div class="select-role-wrapper">
      <div class="base">
      </div>   
    </div>
  </div>
</template>
<style lang="scss" scoped>
  @import "@/assets/scss/mixin.scss";
  @import "@/assets/scss/variable.scss";
  .base {
    @include border-shadow;
    .title {
      @include flex;
      height: 100px;
      background: $blue;
      justify-content: flex-start;
      text-align: left;
      padding: 0 20px;
      border-radius: 4px 4px 0 0;
      font-size: 18px;
    }
  }
</style>

Vue中的mixins

Vue官网,关于可复用性&组合的章节,也提到了混入mixin

基础

混入(mixin)提供了一种非常灵活的方式,来分发Vue组件中的可复用功能。

一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

选项合并

当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。

比如,数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先

同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用

除了公用数据,template布局也可以混入。但是,如果已经有了template就会替换mixins中的template布局。

页面逻辑都差不多的时候,引入混入mixins可以少写很多都没,可以根据项目要求引入。

详情请见官方文档

Vue的文档看起来真是赏心悦目。

cn.vuejs.org/v2/guide/mi…

以实际项目为例:

一些常用的请求接口的方法,和文件流下载方法,点击事件,就可以放在混入mixins文件中

OperateMixin.js文件

import { parseTime } from "@/utils/common";
import { deleteColor } from "@/utils/common";
export const OperateMixin = {
  data() {
    return {
      deleteColor,
    }
  },
  created() {
​
  },
  methods: {
    // 点击操作按钮的方法
    btnClick(item) {
      let length = this.table.selection.length;
      let msg = "";
      if (length == 0 && item.alert) {
        msg = item.alert;
      }
      if (msg) {
        this.$sweetAlert.warnWithTimer(msg);
        return;
      }
      let ids = this.table.selection.map((item) => item.ID).join(",");
      this.operate(ids, item.value);
    },
    operateBeforeConfirm(ids, type, msg, callback) {
      this.$confirm(msg, "操作提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          callback(ids, type);
        })
        .catch(() => { });
    },
    interfaceRequest(httpurl, formData, method, callback) {
      this.$api.httpAction(httpurl, formData, method).then((res) => {
        if (res.code == 200) {
          this.$sweetAlert.successWithTimer(res.msg);
          callback();
        } else {
          this.$sweetAlert.errorWithTimer(res.msg);
        }
      });
    },
    downloadByFileStream(httpurl, formData, name, format) {
      let fileName = name || parseTime(new Date(), "{y}-{m}-{d}");
      let formatName = format || 'zip';
      formatName = '.' + formatName;
      this.$api.downFile(httpurl, formData).then((data) => {
        if (!data) {
          this.$sweetAlert.errorWithTimer("文件下载失败!");
          return;
        }
        if (typeof window.navigator.msSaveBlob !== "undefined") {
          window.navigator.msSaveBlob(new Blob([data]), fileName + formatName);
        } else {
          const url = window.URL.createObjectURL(new Blob([data]));
          const link = document.createElement("a");
          link.style.display = "none";
          link.href = url;
          link.setAttribute("download", fileName + formatName);
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
          window.URL.revokeObjectURL(url);
        }
      });
    }
  }
}

然后在组件中引入

<template>
  <div class="wrapper">InfoList</div>
</template>
​
<script>
import { OperateMixin } from "@/mixins/OperateMixin";
export default {
  name: "InfoList",
  mixins: [OperateMixin],
  components: {},
  props: {},
  data() {
    return {};
  },
  watch: {},
  computed: {},
  methods: {},
  created() {},
  mounted() {},
};
</script>
<style scoped>
.wrapper {
}
</style>