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()
}	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM