zoukankan      html  css  js  c++  java
  • VUE造轮子ui框架(上)

    1.需求分析

    用例图,状态分析

    在这里插入图片描述

    2.UI设计

    我们用SKetch进行ui的设计。可以利用symbol来绑定关联等详细操作就不赘述了,设计效果如下图

    在这里插入图片描述

    3.项目初始化

    1.先在github上建立gulu仓库,本地电脑创建项目,关联到远程仓库
    2.创建README.md 和 LICENSE许可证(许可证可在github上进行创建,具体创建的类型可以看阮一峰老师的经典图)
    3.npm init 来简化项目的传输等,记载项目依赖,此时可以进行提交但node_modules依赖包过大,可以创建.gitignore文件进行不上传指定文件
    4.这里我们利用parcel来进行构建项目,这里我们进行-D安装,所以在执行命令时需要~.node_modules/.bin/parcel~来找到本地安装的指令才可以进行打包。
    出现的问题: (You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.)这是由于vue版本不兼容的原因,我们可以上vue官网找到解决办法
    

    4.button基础样式实现

    用到了变量方便用户进行修改样式,css使用scss

    //scss//
    * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
          }
    :root { //表示根html, 也可以写其他的选择器,在选择器中生效
            --button-height: 32px;
            --font-size: 14px;
            --button-bg: white;
            --button-active-bg: #eee;
            --border-radius: 4px;
            --color: #333;
            --border-color: #999;
            --border-color-hover: #666;
          }
    #app {
            margin: 20px;
          }
    body {
            font-size: var(--font-size);
          }
          
    .g-button {
      font-size: var(--font-size);
      height: var(--button-height);
      padding: 0 1em;
      border-radius: var(--border-radius);
      border: 1px solid var(--border-color);
      background-color: var(--button-bg);
      &:hover {
        border-color: var(--border-color-hover);
      }
      &:active {
        background-color: var(--button-active-bg);
      }
      &:focus {
        outline: none;
      }
    }
    

    5.实现按钮添加字体图标

    1.去阿里巴巴图标库进行,图标的添加,利用图标库的symbol模式,使用方法可以参考图标库的文档。在图标库中可以进行项目编辑前缀名,批量操做图标的颜色,每个图标大小和名字。

    2.让用户添加属性的方式添加字体图标,具体在组件中进行编写,还添加了icon-position属性,让用户自定义图标的左右位置。还需要进行用户传入属性的验证在props中validator进行验证给与用户提示信息。

    3.把svg整合到icon.vue中,实现用户可以调用icon组件

    为按钮添加loading样式

    1.我们先添加loading这一个图标,然后在button组件中对这个图标进行旋转利用到关键帧动画,在icon添加class实现

    在这里插入图片描述

    2.然后进行一些逻辑,包括loading与icon交替显示问题,

    在这里插入图片描述

    3.为按钮添加事件,由于我们用户要动态绑定loading 属性到g-button上,所以我们只需要让vue动态追踪就可以了。但是--出现一个问题: 由于我们按钮组件是自定义的,当用户在组件上绑定点击事件时,浏览器判断不出点击哪里会触发用户定义的点击事件,所以我们需要在组件中自己来找到触发的位置,如下图:

    在这里插入图片描述

    4.button-group组件实现

    效果如下:

    在这里插入图片描述

    button-group代码如下

    <template>
      <div class="g-button-group"><slot></slot></div>
    </template>
    
    <script>
    export default {};
    </script>
    
    <style scoped lang="scss">
    .g-button-group {
      display: inline;
      .g-button {
        border-radius: 0 !important;
        margin-left: -1px; //结局边框加深问题t1, 此时代码可以优化,选择器为不是第一个时候添加
        &:first-child {
          border-top-left-radius: var(--border-radius) !important;
          border-bottom-left-radius: var(--border-radius) !important;
        }
        &:last-child {
          border-top-right-radius: var(--border-radius) !important;
          border-bottom-right-radius: var(--border-radius) !important;
        }
        &:hover { //结局边框加深问题t2
          position: relative;
          z-index: 1; 
        }
      }
    }
    </style>
    
    
    

    单元测试

    我们为了检测一个作用明确的单元是否功能正常,我们进行单元测试,即利用代码的方式进行测试,代替了手动测试方式。这样结果更具有准确性。即 测试行为—>结果。 用到了Chai这个库其中的期待和间谍

    
    import chai from 'chai'
    import spies from 'chai-spies'
    
    chai.use(spies)
    Vue.component('g-button-group', ButtonGroup)	const expect = chai.expect
    
    
    new Vue({	{
      el: '#app',	  const Constructor = Vue.extend(Button)
      data: {	  const vm = new Constructor({
        loading1: false,	    propsData: {
        loading2: true,	      icon: 'settings'
      }	    }
    })	  }).$mount()
      const useElement = vm.$el.querySelector('use')
      expect(useElement.getAttribute('xlink:href')).to.equal('#i-settings')
      vm.$destroy()
    }
    {
      const Constructor = Vue.extend(Button)
      const vm = new Constructor({
        propsData: {
          icon: 'settings',
          loading: true
        }
      }).$mount()
      const useElements = vm.$el.querySelectorAll('use')
      expect(useElements.length).to.equal(1)
      expect(useElements[0].getAttribute('xlink:href')).to.equal('#i-loading')
      vm.$destroy()
    }
    {
      const div = document.createElement('div')
      document.body.appendChild(div)
      const Constructor = Vue.extend(Button)
      const vm = new Constructor({
        propsData: {
          icon: 'settings',
        }
      }).$mount(div)
      const icon = vm.$el.querySelector('svg')
      expect(getComputedStyle(icon).order).to.eq('1')
      vm.$el.remove()
      vm.$destroy()
    }
    {
      const div = document.createElement('div')
      document.body.appendChild(div)
      const Constructor = Vue.extend(Button)
      const vm = new Constructor({
        propsData: {
          icon: 'settings',
          iconPosition: 'right'
        }
      }).$mount(div)
      const icon = vm.$el.querySelector('svg')
      expect(getComputedStyle(icon).order).to.eq('2')
      vm.$el.remove()
      vm.$destroy()
    }
    {
      const Constructor = Vue.extend(Button)
      const vm = new Constructor({
        propsData: {
          icon: 'settings',
        }
      }).$mount()
      const spy = chai.spy(() => {})
        console.log('hi')	  vm.$on('click', spy)
      })	
      vm.$el.click()	  vm.$el.click()
      expect(spy).to.have.been.called()
    }	}
    }
    
  • 相关阅读:
    人生转折点:弃文从理
    人生第一站:大三暑假实习僧
    监听器启动顺序和java常见注解
    java常识和好玩的注释
    182. Duplicate Emails (Easy)
    181. Employees Earning More Than Their Managers (Easy)
    180. Consecutive Numbers (Medium)
    178. Rank Scores (Medium)
    177. Nth Highest Salary (Medium)
    176. Second Highest Salary(Easy)
  • 原文地址:https://www.cnblogs.com/jackson1/p/13299586.html
Copyright © 2011-2022 走看看