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()
    }	}
    }
    
  • 相关阅读:
    什么是单例模式?
    下拉列表(web),用jQuery实现
    PS基础
    C#笔记
    C#基础篇--文件(流)
    C#基础篇03
    今天自学了网页上注册某某时的倒计时设置
    主数据管理的Jill Dyche, Evan Levy六层次模型
    scala akka 修炼之路6(scala函数式柯里化风格应用场景分析)
    OpenWrt mt7620n双SSID实现原理
  • 原文地址:https://www.cnblogs.com/jackson1/p/13299586.html
Copyright © 2011-2022 走看看