浏览代码

upd: checkbox 开发

Ymm0008 5 年之前
父节点
当前提交
9c756d2ea4
共有 3 个文件被更改,包括 221 次插入27 次删除
  1. 45 12
      src/packages/checkbox/demo.vue
  2. 76 1
      src/packages/checkbox/index.scss
  3. 100 14
      src/packages/checkbox/index.vue

+ 45 - 12
src/packages/checkbox/demo.vue

@@ -1,22 +1,55 @@
 <template>
-  <div class="demo">
-    <h2>checkbox</h2>
-    <nut-cell>
-      <nut-temp name="wifi"></nut-temp>
-      <nut-temp name="mail" txt="test txt"></nut-temp>
-    </nut-cell>
+  <div class="demo-list">
+    <h4>基础用法</h4>
+    <div class="show-demo">
+      <nut-checkbox v-model="checkbox1" @change="changeBox1">选项</nut-checkbox>
+      <nut-checkbox v-model="checkbox2" @change="changeBox1">选项</nut-checkbox>
+    </div>
+    <h4>基本用法</h4>
+    <div class="show-demo"> </div>
   </div>
 </template>
-
 <script lang="ts">
+import { reactive, toRefs } from 'vue';
 import { createComponent } from '@/utils/create';
-const { createDemo } = createComponent('temp');
+const { createDemo } = createComponent('checkbox');
 export default createDemo({
-  props: {},
-  setup() {
-    return {};
+  setup(props, context) {
+    const data = reactive({
+      checkbox1: false,
+      checkbox2: true
+    });
+    const changeBox1 = (name: string) => {
+      console.log(`点击了name是的面板`);
+    };
+    return {
+      changeBox1,
+      ...toRefs(data)
+    };
   }
 });
 </script>
 
-<style lang="scss" scoped></style>
+<style>
+#app {
+  background: #f7f8fa;
+}
+</style>
+<style lang="scss" scoped>
+.demo-list {
+  margin: 60px 0;
+  padding: 17px;
+  h4 {
+    line-height: 20px;
+    color: #909ca4;
+    font-size: 14px;
+  }
+  .show-demo {
+    margin-top: 10px;
+    padding: 15px;
+    background-color: #ffffff;
+    border-radius: 7px;
+    box-shadow: 0px 1px 7px 0px rgba(237, 238, 241, 1);
+  }
+}
+</style>

+ 76 - 1
src/packages/checkbox/index.scss

@@ -1,2 +1,77 @@
-.nut-temp {
+.nut-checkbox {
+  margin-right: 10px;
+  .nut-checkbox-label {
+    pointer-events: none;
+    vertical-align: middle;
+  }
+  input {
+    position: relative;
+    -webkit-appearance: none;
+    border-radius: 1%;
+    background-image: url('https://img11.360buyimg.com/imagetools/jfs/t1/153637/38/10229/854/5fd9cfd3E25c62c2a/fed43bc74cd473dd.png');
+    background-size: cover;
+    outline: 0;
+    opacity: 1;
+    vertical-align: middle;
+    margin: 0;
+    &::after {
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      content: '';
+      width: 0;
+      height: 0;
+      transform: translate(-50%, -50%);
+      background: $primary-color;
+      border-radius: 1%;
+      opacity: 0;
+      pointer-events: none;
+    }
+    &:checked {
+      background-image: url('https://img13.360buyimg.com/imagetools/jfs/t1/131359/19/19372/2463/5fd3101bEdaf04120/3c8fa97cd4b22c02.png');
+      background-repeat: no-repeat;
+      background-position: center;
+      border-color: $primary-color;
+      box-shadow: 0 4px 6px 0 rgba($primary-color, 0.15);
+    }
+    &:disabled {
+      background-image: url('https://img14.360buyimg.com/imagetools/jfs/t1/155506/4/9365/704/5fd3103cE779ad491/1939699720df7770.png');
+      border-color: $disable-color;
+      box-shadow: none;
+      &:checked {
+        background-color: $disable-color;
+      }
+    }
+  }
+  .nut-checkbox-label {
+    color: #1d1e1e;
+  }
+  &.nut-checkbox-size-base {
+    input {
+      width: 18px;
+      height: 18px;
+    }
+    .nut-checkbox-label {
+      font-size: $font-size-2;
+      margin-left: 15px;
+    }
+  }
+  &.nut-checkbox-size-small {
+    input {
+      width: 16px;
+      height: 16px;
+    }
+    .nut-checkbox-label {
+      font-size: $font-size-1;
+    }
+  }
+  &.nut-checkbox-size-large {
+    input {
+      width: 22px;
+      height: 22px;
+    }
+    .nut-checkbox-label {
+      font-size: $font-size-3;
+    }
+  }
 }

+ 100 - 14
src/packages/checkbox/index.vue

@@ -1,38 +1,124 @@
 <template>
-  <view :class="classes" @click="handleClick">
-    <view>{{ name }}</view>
-    <view>{{ txt }}</view>
+  <view>
+    <label :class="['nut-checkbox', 'nut-checkbox-size-' + size]">
+      <input
+        type="checkbox"
+        :name="name"
+        :class="{ 'nut-checkbox-ani': animation }"
+        :disabled="disabled"
+        :checked.prop="isChecked"
+        :value="submittedValue"
+        @change="changeEvt"
+      />
+      <span class="nut-checkbox-label" v-if="label">
+        {{ label }}
+      </span>
+      <span class="nut-checkbox-label" v-else>
+        <slot></slot>
+      </span>
+    </label>
   </view>
 </template>
 <script lang="ts">
-import { toRefs } from 'vue';
+import { reactive, ref, toRefs, watchEffect } from 'vue';
 import { createComponent } from '@/utils/create';
-const { componentName, create } = createComponent('temp');
+const { componentName, create } = createComponent('checkbox');
 
 export default create({
   props: {
     name: {
+      type: String
+    },
+    size: {
+      type: [String, Number, Boolean],
+      default: 'base'
+    },
+    label: {
       type: String,
       default: ''
     },
-    txt: {
+    modelValue: {
+      required: true
+    },
+    trueValue: {
+      default: true
+    },
+    falseValue: {
+      default: false
+    },
+    submittedValue: {
       type: String,
-      default: ''
+      default: 'on' // HTML default
+    },
+    checked: {
+      type: Boolean,
+      default: false
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    animation: {
+      type: Boolean,
+      default: true
     }
   },
   components: {},
-  emits: ['click'],
-
   setup(props, { emit }) {
-    console.log('componentName', componentName);
+    let isChecked: boolean =
+      props.modelValue == props.trueValue || props.checked;
+
+    const isObject = obj => {
+      return obj !== null && typeof obj === 'object';
+    };
 
-    const { name, txt } = toRefs(props);
+    const looseEqual = (a, b) => {
+      return (
+        a == b ||
+        (isObject(a) && isObject(b)
+          ? JSON.stringify(a) === JSON.stringify(b)
+          : false)
+      );
+    };
+
+    watchEffect(() => {
+      isChecked = looseEqual(props.modelValue, props.trueValue);
+    });
 
-    const handleClick = (event: Event) => {
-      emit('click', event);
+    const { size, label, name, disabled, submittedValue, animation } = reactive(
+      props
+    );
+
+    const changeEvt = (event: { target: HTMLInputElement }) => {
+      const isCheckedPrevious: boolean = isChecked;
+      const isCheck: boolean = event.target.checked;
+      emit(
+        'input',
+        isCheck ? props.trueValue : props.falseValue,
+        props.label,
+        event
+      );
+      if (isCheckedPrevious !== isCheck) {
+        emit(
+          'change',
+          isCheck ? props.trueValue : props.falseValue,
+          props.label,
+          event
+        );
+      }
     };
+    console.log(isChecked);
 
-    return { name, txt, handleClick };
+    return {
+      size,
+      label,
+      name,
+      disabled,
+      submittedValue,
+      animation,
+      isChecked,
+      changeEvt
+    };
   }
 });
 </script>