抽象组件即无渲染组件(如vue中自带的keep-aliave组件)

就像java中的抽象类,它本身不糊做一些事情,只是提供一些接口方法等让外部使用。后续我们可以不断扩展该组件实现更好更强大的组件。这也正是SOLID

根据SOLID的单一职责原则:

一个类应该只做一件事。

🌰栗子:

你的组件可能有一个名叫password-input的组件,它肯定呈现一个密码输入框。问题在于,当你想要在其他项目重用此组件时,你可能不得不查看组件源码修改样式或者HTML,以便能和新项目的样式或设计图保持一致。

如果你这样做就破坏了SOLID原则,也就是开闭原则。

类或者组件,应该对扩展开放,对修改关闭。

由于vue了解SOLID原则,所以它允许组件具有propseventsslots以及scoped slots,从而使组件的通信和扩展变得轻而易举。然后我们可以构建具有所有功能的组件,而无需任何样式或HTML。对于编写可重用性和高性能的代码来说真的不错。

以抽象组件的形式构建一个开关组件

抽象组件定义

// toggle.js
export default {
  props: {
    on: {
      type: Boolean,
      default: false
    }
  },
  render() {
    return this.$slots.default({
      on: this.currentState,
      setOn: this.setOn,
      setOff: this.setOff,
      toggle: this.toggle
    });
  },
  data() {
    return {
      currentState: this.on
    }
  },
  methods: {
    setOn() {
      this.currentState = true;
    },
    setOff() {
      this.currentState = false;
    },
    toggle() {
      this.currentState = !this.currentState
    }
  }
}

抽象组件应用

<template>
    <Toggle>
    <div slot-scope="{ on, toggle}" class="container">
      <span 
       class="weui-switch"
       :class="{'weui-switch-on' : on}"
       @click="toggle"
       style="position:relative"
      >
        <div v-if="on" class="switch-text switch-text-left"></div>
        <div v-if="!on" class="switch-text switch-text-right"></div>
          </span>
      </div>
  </Toggle>
</template>

<script lang='ts'>
import { Component, Vue, Provide } from "vue-property-decorator";
import Toggle from "@/components/Toggle.js"; // @ is an alias to /src

@Component({
  components: {
    Toggle
  }
})
export default class High extends Vue {}
</script>

<style>
.switch-text {
  width: 100%;
  height: 100%;
  position: absolute;
  padding: 0 5px;
  line-height: 24px;
  user-select: none;
  font-size: 14px;
}
.switch-text-left {
  text-align: left;
  color: #fff;
  left: 2px;
}
.switch-text-right {
  right: 2px;
  color: #7a7a7a;
  text-align: right;
}
.weui-switch {
  display: block;
  position: relative;
  width: 52px;
  height: 24px;
  border: 1px solid #dfdfdf;
  outline: 0;
  border-radius: 16px;
  box-sizing: border-box;
  background-color: #dfdfdf;
  transition: background-color 0.1s, border 0.1s;
  cursor: pointer;
}
.weui-switch:before {
  content: " ";
  position: absolute;
  top: 0;
  left: 0;
  width: 50px;
  height: 22px;
  border-radius: 15px;
  background-color: #fdfdfd;
  transition: transform 0.35s cubic-bezier(0.45, 1, 0.4, 1);
}
.weui-switch:after {
  content: " ";
  position: absolute;
  top: 0;
  left: 0;
  width: 22px;
  height: 22px;
  border-radius: 15px;
  background-color: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  transition: transform 0.35s cubic-bezier(0.4, 0.4, 0.25, 1.35);
}
.weui-switch-on {
  border-color: #6f6f6f;
  background-color: #1add19;
}
.weui-switch-on:before {
  border-color: #1aad19;
  background-color: #409eff;
}
.weui-switch-on:after {
  transform: translateX(28px);
}
</style>

效果示例:

QQ20190629-172409-HD

results matching ""

    No results matching ""