创建Button组件

  1. <template>
  2. <button>
  3. <slot/>
  4. </button>
  5. </template>

父组件属性传递

  1. <template>
  2. <div>
  3. <Button @click="handleClick">你好</Button>
  4. </div>
  5. </template>
  • 默认父组件传递的所有属性都绑定到子组件的根元素
  • 使用inheritAttrs: false可以取消默认绑定
  • 使用$attrs或者context.attrs获取所有属性
  • 使用v-bind="$attrs"批量绑定属性
  • 使用const {size, ...rest} = context.attrs将属性分解

给Button添加theme基础样式

  1. <div>
  2. <Button>你好</Button>
  3. <Button theme="button">你好</Button>
  4. <Button theme="link">你好</Button>
  5. <Button theme="text">你好</Button>
  6. </div>
  1. <template>
  2. <button class="pika-button" :class="{[`theme-${theme}`]: theme}">
  3. <slot/>
  4. </button>
  5. </template>
  6. <script lang="ts">
  7. export default {
  8. props: {
  9. theme: {
  10. type: String,
  11. default: 'button'
  12. }
  13. }
  14. }
  15. </script>

添加基础样式

  1. <style lang="scss" scoped>
  2. $h: 32px;
  3. $border-color: #d9d9d9;
  4. $color: #333;
  5. $blue: #40a9ff;
  6. $radius: 4px;
  7. .pika-button {
  8. box-sizing: border-box;
  9. height: $h;
  10. padding: 0 12px;
  11. cursor: pointer;
  12. display: inline-flex;
  13. justify-content: center;
  14. align-items: center;
  15. white-space: nowrap;
  16. background: white;
  17. color: $color;
  18. border: 1px solid $border-color;
  19. border-radius: $radius;
  20. box-shadow: 0 1px 0px fade-out(black, 0.95);
  21. & + & {
  22. margin-left: 8px;
  23. }
  24. &:hover,
  25. &:focus {
  26. color: $blue;
  27. border-color: $blue;
  28. }
  29. &:focus {
  30. outline: none;
  31. }
  32. &::-moz-focus-inner {
  33. border: 0;
  34. }
  35. }
  36. </style>
  • inline-flex和flex的区别:inline-flex把容器变成内联元素, flex把容器变成块级元素
  • white-space: nowrap;不换行
  • ::-moz-focus-inner兼容火狐浏览器

    UI组件库的CSS注意事项

  1. 不能使用scoped
    1. 因为data-v-xxx中的xxx每次运行都可能不同
    2. 必须输出稳定不变的class选择器,方便使用者覆盖
  2. 必须加前缀
    1. .button不行,容易被使用者覆盖,.pika-button可以
    2. .theme-link不行,容易被使用者覆盖 .pika-theme-link可以

      CSS最小影响原则

      UI库的CSS不能影响到用户的CSS
      在lib目录中新建pika.scss
      1. [class^="pika-"],
      2. [class*=" pika-"] {
      3. margin: 0;
      4. padding: 0;
      5. box-sizing: border-box;
      6. font-size: 16px;
      7. font-family: -apple-system, "Noto Sans", "Helvetica Neue", Helvetica,
      8. "Nimbus Sans L", Arial, "Liberation Sans", "PingFang SC", "Hiragino Sans GB",
      9. "Noto Sans CJK SC", "Source Han Sans SC", "Source Han Sans CN",
      10. "Microsoft YaHei", "Wenquanyi Micro Hei", "WenQuanYi Zen Hei", "ST Heiti",
      11. SimHei, "WenQuanYi Zen Hei Sharp", sans-serif;
      12. }
      用户要使用UI库,就要先引入这个css, 所有class以pika-开头或者class中包含pika-的就使用这个css
      注意顺序,必须在最开始import ```typescript import ‘./lib/pika.scss’ import ‘./index.scss’ import { router } from ‘./router’; import { createApp } from ‘vue’ import App from ‘./App.vue’

createApp(App) .use(router) .mount(‘#app’)

  1. <a name="epQhE"></a>
  2. ### 支持theme属性
  3. ```css
  4. &.pika-theme-link {
  5. border-color: transparent;
  6. box-shadow: none;
  7. color: $blue;
  8. &:hover, &:focus {
  9. color: lighten($blue, 10%)
  10. }
  11. }
  12. &.pika-theme-text {
  13. border-color: transparent;
  14. box-shadow: none;
  15. color: inherit;
  16. &:hover, &:focus {
  17. background: darken(white, 5%);
  18. }
  19. }

支持size属性

使用计算属性

  1. setup(props){
  2. const {theme, size} = props
  3. const classes = computed(()=>{
  4. return {
  5. [`pika-theme-${theme}`]: theme,
  6. [`pika-size-${size}`]: size,
  7. }
  8. })
  9. return {
  10. classes
  11. }
  12. }
  1. &.pika-size-big {
  2. font-size: 24px;
  3. height: 48px;
  4. padding: 0 16px;
  5. }
  6. &.pika-size-small {
  7. font-size: 12px;
  8. height: 20px;
  9. padding: 0 4px;
  10. }

支持level属性

  1. <div>
  2. <Button theme="link" size="big" level="main">大大大</Button>
  3. <Button theme="link">普普通</Button>
  4. <Button theme="link" size="small" level="danger">小小小</Button>
  5. </div>

支持disabled

props需指定为Boolean值

  1. props: {
  2. disabled: {
  3. type: Boolean,
  4. default: false
  5. }
  6. }

当传了props时则认为是true

  1. <Button disabled>禁用</Button>
  1. <template>
  2. <button class="pika-button" :class="classes" :disabled="disabled">
  3. <slot />
  4. </button>
  5. </template>
  1. &.pika-theme-button {
  2. &[disabled] {
  3. cursor: not-allowed;
  4. color: $grey;
  5. &:hover {
  6. border-color: $grey;
  7. }
  8. }
  9. }
  10. &.pika-theme-link,
  11. &.pika-theme-text {
  12. &[disabled] {
  13. cursor: not-allowed;
  14. color: $grey;
  15. }
  16. }

支持loading

  1. <Button loading>加载中</Button>
  1. <button class="pika-button" :class="classes" :disabled="disabled">
  2. <span v-if="loading" class="pika-loadingIndicator"></span>
  3. <slot />
  4. </button>
  1. @keyframes pika-spin {
  2. 0% {
  3. transform: rotate(0deg)
  4. }
  5. 100% {
  6. transform: rotate(360deg)
  7. }
  8. }
  9. .pika-loadingIndicator {
  10. width: 14px;
  11. height: 14px;
  12. display: inline-block;
  13. margin-right: 4px;
  14. border-radius: 8px;
  15. border-color: $blue $blue $blue transparent;
  16. border-style: solid;
  17. border-width: 2px;
  18. animation: pika-spin 1s infinite linear;
  19. }