Vue3 封装

123 阅读1分钟

1.将防抖与框架结合,利用自定义ref

// debounceRef.js
import { customRef } from "vue";
export const debounceRef = (value,duration = 1000) => {
    let timer;
    return customRef((track,triggher)=>{
        return {
            get(){
                track()    //vue3 customRef自带的收集依赖的方法
                return value
            },
            set(val){
                clearTimeout(timer)
                timer = setTimeout(() => {
                    triggher()  //vue3 customRef自带的通知依赖的方法
                    value = val
                }, duration);
            }
        }
    })
};
// 使用
<template>
  <el-input v-model="value"></el-input>
</template>
<script lang="ts" setup>
import debounceRef from './debounceRef.js'
//利用customRef自定义ref实在防抖
const value = debounceRef('',5000)
</script>

2.弹窗组件,开发成本高 使用成本低


import _MessageBox from "./message-box";
import { createApp } from "vue";
export const showMsg = (msg,clickHandler) => {
    const div = document.createElement('div')
    document.body.appendChild(div)
    const app = createApp(_MessageBox,{
        msg,
        onclick(){
            console.log('点击');
            clickHandler(()=>{
                app.unmount(div)
                div.remove()
            })
        }
    })
    app.mount(div)
};
//使用
const clickHandler = ()=>{
  showMsg('要显示的内容',(close)=>{
    close()
  })
}
// 自定义 message-box弹窗,不符合高内聚的原则,可以通过render函数在js文件写MessageBox vue文件 jsx,css代码可以通过 css in js
const MessageBox = {
  props:{
    msg:{
      type:String,
      require:true
    }
  },
  rennder(ctx){
    const {$props,$emit} = ctx
    return (
      <div class="modal">
        <div class="box">
          <div class="text">{$props.msg}</div>
          <el-button click={$emit('onClick')}></el-button>
        </div>
      </div>
    )
  }
}

3.监控请求进度

1.xhr 原生的xhr支持监听一个progress可以拿到上传的数据,上传时候可以xhr.upload方法监听

xhr.upload.addEventListener('progress',(e)=>{
  console.log('上传加载数据 :>> ', e.loaded,e.total);
})
xhr.addEventListener('progress',(e)=>{
  console.log('下载加载数据 :>> ', e.loaded,e.total);
})

2.fetch不支持监控上传的进度,下载的进度可以通过获取content-length作为总量,再获取响应流已传输的数据量

4.css的变量

动画的百分比是相对于自身的,如果要小球平移的距离适中在父元素中间,要计算 平移宽度

const container = document.querySelectorAll(.parent)
const w = container.clientWidth
container.style.setProperty('--w',w+'px')

css
animation:move 4s linear infinte
@keyframes move{
  50%{
    transform:translateX(calc(var(--w),100%))
 }
}

5.封装ui组件

1.通过$slots拿到传入的插槽,再通过插槽传递给ui组件

// slot接收父组件写入的内容 v-slot:  /# 将内容传递给子组件
  <el-input ref="ref" v-model="value">
    <template v-for="(value,name) in slots"  #[name]="slotData">
      <slot :name="name v-bind="slotData || {}"/>
    </template>
  </el-input>
// 将组件的ref 给到当前实例
const value = debounceRef('',5000)
const entries = Object.entries(this.$refs.ref)
for (const [key,value] of entries) {
  this[key] = value
}