美文网首页
vue3中常用工具类(自用)

vue3中常用工具类(自用)

作者: 硅谷干货 | 来源:发表于2022-05-22 22:29 被阅读0次

    observer.ts

    const eventList = {};
    
    const $on = function (eventName, callback) {
      if (!eventList[eventName]) {
        eventList[eventName] = [];
      }
      eventList[eventName].push(callback);
    };
    
    const $off = function (eventName, callback) {
      if (eventList[eventName]) {
        if (callback) {
          const index = eventList[eventName].indexOf(callback);
          eventList[eventName].splice(index, 1);
        } else {
          eventList[eventName].length = 0;
        }
      }
    };
    
    const $emit = function (eventName, ...params) {
      if (eventList[eventName]) {
        const fnArr = eventList[eventName];
        fnArr.forEach((callback) => {
          callback(...params);
        });
      }
    };
    
    export default {
      $on,
      $off,
      $emit,
    };
    
    

    setRem.ts

    import { getCurrentInstance } from 'vue';
    import { MapConsts } from '@/common/consts/MapConsts';
    import { getPageClientWidth } from './usePagePosition';
    
    const baseFont = 16; // 字体大小基准值
    
    // 计算rem
    const setRem = () => {
      // 相对于750像素的缩放比
      const clientWidth = getPageClientWidth();
      let scale = clientWidth / 375;
      // 根据屏幕变化 1rem 对应的 font-size
      // scale = scale > 1 ? 1 : scale;
      // const ratio = Math.max(parseFloat(window.devicePixelRatio.toFixed(2)), 1)
      const realFont = baseFont * scale;
      document.documentElement.style.fontSize = realFont + 'px';
     
      // 根据视口计算vh
      // let vh = window.innerHeight * 0.01
      // document.documentElement.style.setProperty('--vh', `${vh}px`)
    };
    
    // 初始化rem
    export const initRem = () => {
      // 初始化rem
      setRem();
      // 获取全局属性变量
      const instance = getCurrentInstance();
      const globalProperties = instance.appContext.config.globalProperties;
      // 改变窗口大小时重新设置 rem
      window.addEventListener(MapConsts.RESIZE, () => {
        setRem();
        // 视窗大小变化监听
        globalProperties.$observer.$emit(MapConsts.HANDLERR_ESIZE);
      });
    };
    
    

    usePagePosition.ts

    // 获取页面左边卷起距离
    export function getPageScrollLeft() {
      const scrollLeft =
        window.pageXOffset ||
        document.documentElement.scrollLeft ||
        document.body.scrollLeft ||
        0;
      return scrollLeft;
    }
    
    // 获取页面顶部卷起距离
    export function getPageScrollTop() {
      const scrollTop =
        window.pageYOffset ||
        document.documentElement.scrollTop ||
        document.body.scrollTop ||
        0;
      return scrollTop;
    }
    
    // 获取页面左边、顶部卷起距离
    export function getPageScroll() {
      return {
        left: getPageScrollLeft(),
        top: getPageScrollTop(),
      };
    }
    
    // 获取可视区域宽度
    export function getPageClientWidth() {
      const w =
        window.innerWidth ||
        document.documentElement.clientWidth ||
        document.body.clientWidth ||
        0;
      return w;
    }
    
    // 获取可视区域高度
    export function getPageClientHeight() {
      const h =
        window.innerHeight ||
        document.documentElement.clientHeight ||
        document.body.clientHeight ||
        0;
      return h;
    }
    
    // 获取屏幕可见高度的兼容性document.documentElement.clientHeight之前是这样获取的,PC端没什么问题,就是手机浏览器打开时,出现异常。网上查了下,最终的实现代码
    export function getPageClient() {
      return {
        width: getPageClientWidth(),
        height: getPageClientHeight(),
      };
    }
    
    // 以上获取做了浏览器兼容性处理,可直接对外提供使用,同时也可以对外统一使用
    export const usePagePosition = () => {
      return {
        getPageScrollLeft,
        getPageScrollTop,
        getPageScroll,
        getPageClientWidth,
        getPageClientHeight,
        getPageClient,
      };
    };
    
    

    loadDevTools.ts

    ;(function () {
      if (!/mdebug=true/.test(window.location.href)) return;
      var script = document.createElement('script');
      script.src = 'https://cdn.bootcss.com/eruda/1.2.6/eruda.min.js';
      script.async = true;
      document.getElementsByTagName('head')[0].appendChild(script);
      script.onload = function () {
        // @ts-ignore
        eruda.init();
      };
    })();
    
    

    ConfigUtils.ts

    import { getConfig } from "@/api";
    import Config from "./Config";
    
    export default class ConfigUtils {
      private static config = null;
      private static callbackResolves = [];
    
      static async initConfig() {
        const response = await getConfig();
        this.config = response;
        this.callbackResolves.forEach((resolve) => resolve(this.config));
        return this.config;
      }
    
      static getConfig(): Promise<Config> {
        return new Promise((resolve) => {
          if (this.config) {
            resolve(this.config);
          } else {
            this.callbackResolves.push(resolve);
          }
        })
      }
    }
    

    DeviceType.ts

    export default class DeviceType {
      static getDeviceType() {
        const obj = this.checkDeviceType();
        if (obj.isMobile) {
          return 'phone';
        }
        if (obj.isTablet) {
          return 'pad';
        }
        if (obj.isPc) {
          return 'pc';
        }
        return 'pc';
      }
    
      static checkDeviceType() {
        const ua = navigator.userAgent;
        const isWindowsPhone = /(?:Windows Phone)/.test(ua);
        const isSymbian = /(?:SymbianOS)/.test(ua) || isWindowsPhone;
        const isAndroid = /(?:Android)/.test(ua);
        const isFireFox = /(?:Firefox)/.test(ua);
        const isTablet =
          /(?:iPad|PlayBook)/.test(ua) ||
          (isAndroid && !/(?:Mobile)/.test(ua)) ||
          (isFireFox && /(?:Tablet)/.test(ua));
        const isiPhone = /(?:iPhone)/.test(ua) && !isTablet;
        const isMacOSX = /(?:iPad|Mac OS X)/.test(ua);
        const isPc =
          window.devicePixelRatio === 1 &&
          !isiPhone &&
          !isAndroid &&
          !isSymbian &&
          !('ontouchend' in document.body);
        return {
          isTablet,
          isMobile:
            (DeviceType.isMobileDevice() && !isTablet) ||
            (isAndroid && !isTablet) ||
            isiPhone,
          isAndroid,
          isPc,
          isiPhone,
          isMacOSX,
          isWeChat: Boolean(navigator.userAgent.match(/MicroMessenger/gi)),
        };
      }
    
      // 判断设备类型是否为手机、平板
      // 方式一:推荐
      static isMobile(): boolean {
        const obj = this.checkDeviceType();
        if (obj.isMobile) { // 手机
          return true;
        }
        if (obj.isTablet) { // 平板
          return true;
        }
        return false;
      }
    
      // 方式二:normal
      static isMobileDevice() {
        return 'ontouchend' in document.body;
      }
    
      // 方式一:推荐
      static isAndroid(): boolean {
        return this.checkDeviceType().isAndroid;
      }
      // 方式二:normal
      static isAndroid2(): boolean {
        return navigator.userAgent.toLowerCase().indexOf('android') > 0;
      }
    
      // 判断移动设备是否横屏模式(推荐)
      static isMobileLandscape() { 
        if (window.orientation == 0 || window.orientation == 180) {
          return false
        } else if (window.orientation == 90 || window.orientation == -90) {
          return true
        }
        return false
      }
    
      // 判断移动设备是否竖屏模式
      static isMobilePortrait() {
        const isMobileDevice = this.checkDeviceType().isMobile;
        return isMobileDevice && window.innerWidth <= window.innerHeight;
      }
    }
    
    

    language.ts

    /*
     * @Descripttion: 描述:需要哪种语言就在languageList里面加上
     */
    const languageList = ['zh', 'en']
    
    export const getLanguage = () => {
      let localLang = navigator.language.toLocaleLowerCase() || 'en'
      if (languageList.indexOf(localLang) !== -1) {
        return localLang
      } else if (localLang.match(/\w+(?=[\-]|[\_])/g)) {
        localLang = localLang.match(/\w+(?=[\-]|[\_])/g)[0]
        if (languageList.indexOf(localLang) !== -1) {
          return localLang
        }
      }
      localLang = localLang === 'zh' ? 'zh-cn' : localLang // zh   zh-cn均代表中文
      localLang = localLang === 'iw' ? 'he' : localLang // 'he', 'iw'都是希伯来语
      localLang = languageList.indexOf(localLang) === -1  ? 'en' : localLang   // 定义默认的语言为 en
      return localLang
    }
    
    // 获取浏览器,默认语言'zh'
    export const getNavigatorLanguage = () => {   // getNavigatorLanguage 此函数没有用到
      let language = (
        (navigator.language ? navigator.language : navigator.userLanguage) || "zh"
      ).toLowerCase();
      return language.split("-")[0] || "zh";
    }
    
    

    RegExpUtils.ts

    export default class RegExpUtils {
      // 基础uri
      private static publicPath = '/about';
    
      // 替换路径
      public static rmPublicPath(path: string): string {
        if (path) {
          return path.replace(this.publicPath, '');
        }
        return '';
      }
    
      // 检查用户输入是否以http或者https开头,如果不是则添加http或者https
      public static httpCheck(href) {
        if (href == null || href.length == 0) {
          return;
        }
        var reg = new RegExp(/^(http|https).*$/);
        if (!reg.test(href)) {
          return 'https://' + href;
        }
        return href;
      }
    
      public static getQueryParam(paramName: string): string {
        return (
          (new RegExp(`[?|&]${paramName}=([^&;]+?)(&|#|;|$)`).exec(
            location.href
          ) || ["", ""])[1].replace(/\+/g, "%20") || ""
        );
      }
    
      public static getFileName(disposition: string): string {
        let fileName = "";
        if (disposition) {
          const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
          const matches = filenameRegex.exec(disposition);
          if (matches != null && matches[1]) {
            fileName = matches[1].replace(/['"]/g, "");
          }
        }
        return fileName;
      }
      //更新url地址参数
      public static changeURLPar(url, params) {
        for (let key in params) {
          let pattern = key + "=([^&]*)";
          let replaceText = key + "=" + params[key];
          if (url.match(pattern)) {
            let tmp = new RegExp(`${key}=[^&]*`);
            url = url.replace(tmp, replaceText);
          } else {
            if (url.match("[?]")) {
              url = url + "&" + replaceText;
            } else {
              url = url + "?" + replaceText;
            }
          }
        }
        return url;
      }
      // 处理url,防xss攻击
      public static isValidURL(url: string): string {
        const tempURL = url?.toLowerCase();
        if (tempURL && tempURL.indexOf("javascript:") !== -1) {
          return "#";
        }
        return url;
      }
    }
    
    

    useContentObserver.ts

    import { onMounted, onBeforeUnmount, getCurrentInstance } from "vue";
    import { MapConsts } from "@/common/consts/MapConsts"
    
    // 替代v2中的mixins,但是注意使用顺序
    export default function(): void{ 
      
      const instance = getCurrentInstance(); // 获取当前组件的实例、上下文来操作router和vuex等
      // 通过 getCurrentInstance这个函数来返回当前组件的实例对象,也就是当前vue这个实例对象
    
      onMounted(() => {
        window.addEventListener(MapConsts.SCROLL, handleScroll);
      });
      
      onBeforeUnmount(() => {
        window.removeEventListener(MapConsts.SCROLL, handleScroll);
      });
      
      const handleScroll = ()=> {
        //挂载全局属性和方法,使用app.config.globalProperties
        const globalProperties = instance.appContext.config.globalProperties;  
        globalProperties.$observer.$emit(MapConsts.HANDLER_SCROLL);
      };
    }
    
    

    animate.ts

    // 动画方法
    export function animate(obj, target, callback) {
      // console.log(callback);  callback = function() {}  调用的时候 callback()
    
      // 先清除以前的定时器,只保留当前的一个定时器执行
      clearInterval(obj.timer);
      obj.timer = setInterval(function() {
          // 步长值写到定时器的里面
          // 把我们步长值改为整数 不要出现小数的问题
          // var step = Math.ceil((target - obj.offsetLeft) / 10);
          var step = (target - obj.offsetLeft) / 10;
          step = step > 0 ? Math.ceil(step) : Math.floor(step);
          if (obj.offsetLeft == target) {
              // 停止动画 本质是停止定时器
              clearInterval(obj.timer);
              // 回调函数写到定时器结束里面
              // if (callback) {
              //     // 调用函数
              //     callback();
              // }
              callback && callback();
          }
          // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
          obj.style.left = obj.offsetLeft + step + 'px';
    
      }, 15);
    }
    

    相关文章

      网友评论

          本文标题:vue3中常用工具类(自用)

          本文链接:https://www.haomeiwen.com/subject/whelprtx.html