深入探讨uniapp项目开发经验总结与最佳实践

2024-12-23 0 632

深入探讨uniapp项目开发经验总结与最佳实践

在软件开发过程中,我们经常会遇到各种各样的需求。比如,题目中提到的在应用中显示通知,这类需求实际上是项目需要与微信保持一致的特殊规定。这样的要求背后,蕴含着众多技术挑战和考量,同时也对项目的整体使用感受有着重要影响。

系统通知与应用内通知的差异

深入探讨uniapp项目开发经验总结与最佳实践

我们平时都习惯了系统通知的出现。但在这个项目中,我们需要在应用内部显示通知。系统自带的提醒在应用界面不会直接显示。不过,由于特定需求,我们不得不打破这一常规。如果用户感受到这种变化处理不当,可能会影响他们的使用体验。比如,某些新闻应用在用户阅读文章时突然弹出通知,可能会干扰阅读。同样,在办公应用中,如果在处理数据时突然出现通知,也可能打乱工作流程。对于开发者来说,要满足这一需求,必须完全放弃系统通知的常规做法。

我们需要注意各个平台的具体情况,例如iOS和安卓系统。在某些功能上,安卓系统可以轻松实现,但在iOS系统上可能遇到障碍,这是因为iOS的开发受到较多限制。

自定义组件解决方式的缺点

深入探讨uniapp项目开发经验总结与最佳实践

项目初期,我们采用自定组件来处理应用内的通知问题。但这种方法存在两个显著不足。首先,可能存在兼容性问题,某些手机型号或低版本系统可能无法正常使用这些组件。比如,一些旧款手机可能就无法正常显示自定义组件发出的通知。其次,性能也可能是问题之一,例如,可能会消耗过多内存或降低应用整体运行速度。如果手机内存本身就有限,再运行其他大型应用后,使用自定义组件通知可能会导致手机运行缓慢。

原生插件方式的尝试

深入探讨uniapp项目开发经验总结与最佳实践

针对自定义组件的缺陷,我们尝试采用原生插件技术,这种做法具有一定的创新点。我们借鉴了一些成功的做法,比如运用特定的Toast类,并结合独特的技术手段来模拟系统通知。这样做无需通知权限,可以完成一些基础功能。但这种方法也有其限制,并不适合完全取代系统通知,仅适用于应用内部的通知场景。此外,它的功能也相对不全面,若要实现更复杂的通知效果,可能无法满足需求。例如,涉及多种交互的通知,如点击后弹出菜单等,可能就无法实现。

/*
 * @Author: yuanyxh 
 * @Date: 2023-12-27 12:04:11 
 * @Last Modified by:   yuanyxh 
 * @Last Modified time: 2023-12-27 12:04:11 
 */
import Vue from "vue";
const ZERO = 0;
/** 最小左侧触摸开始位置 */
const MINIMUM_LEFT_DISTANCE = 100;
/** 最小移动距离 */
const MINIMUM_MOVE_DISTANCE = 50;
/** 最小间隔事件 */
const MINIMUM_TIME_INTERVAL = 100;
/**
 * 
 * @callback OnSideSlipListener
 * @param {number} sideTime 上次侧滑事件
*/
/**
 *
 * @description 侦听 ios 侧滑事件, 通过此工具配合 beforeRouteLeave 导航守卫判断是否侧滑返回
 */
const sideSlip = (function sideSlipListener(global) {
  let startX = 0,
    endX = 0;
  let sideTime = 0;
  const vm = Vue.prototype;
  /** @type {OnSideSlipListener[]} */
  const callbackList = [];
  function start(e) {
    const point = e.touches?.length ? e.touches[0] : e;
    startX = point.pageX;
  }
  function end(e) {
    const point = e.changedTouched?.length ? e.changedTouched[0] : e;
    endX = point.pageX;
    if (
      startX >= ZERO &&
      startX <= MINIMUM_LEFT_DISTANCE &&
      endX < ZERO &&
      vm.windowWidth - Math.abs(endX) > MINIMUM_MOVE_DISTANCE
    ) {
      sideTime = Date.now();
      callbackList.forEach((callback) => callback(sideTime));
    }
  }
  function isWithinValidityPeriod(time) {
    const interval = Date.now() - time;
    return interval >= ZERO && interval < MINIMUM_TIME_INTERVAL;
  }
  if (vm.isIos) {
    global.addEventListener("touchstart", start);
    global.addEventListener("touchend", end);
    global.addEventListener("touchcancel", end);
  }
  return {
    /**
     * @description 是否左滑
     * @readonly
     */
    get isSideSlip() {
      if (vm.isIos) {
        return isWithinValidityPeriod(sideTime);
      }
      return false;
    },
    /**
     * @description 判断侧滑时间是否在有效期内
     * @param {number} time 侧滑时间
     * @returns {boolean} 是否有效
     */
    isWithinValidityPeriod: isWithinValidityPeriod,
    /**
     * 
     * @description 侦听侧滑
     * @param {OnSideSlipListener} callback 
     */
    on(callback) {
      if (typeof callback === 'function') {
        callbackList.push(callback);
      }
    },
    /**
     * @description 取消事件侦听
     * @param {OnSideSlipListener} callback 
     */
    off(callback) {
      const i = callbackList.indexOf(callback);
      if (i === -1) return;
      callbackList.splice(i, 1);
    },
  };
})(
  (function() {
    let global = {};
    if (typeof window !== "undefined") {
      return (global = window);
    }
    global = {
      addEventListener() {},
      removeEventListener() {},
    };
    return global;
  })()
);
export default sideSlip;

iOS端的解决思路推测

深入探讨uniapp项目开发经验总结与最佳实践

iOS开发方面,由于经验不足,我们尚未找到确切的方法。不过,一个大致的方向是增加一个视图。从理论上讲,这个方法是有可能实现的。然而,iOS对应用视图的管理非常严格,新增的视图必须遵循苹果的设计标准。例如,社交类应用若不符合这些标准,可能无法通过审核。此外,还需确保新增视图不会干扰到其他视图的正常运作,比如在iPad的多任务模式下,新视图不能影响到其他任务的显示效果。

定时器相关的使用情况

深入探讨uniapp项目开发经验总结与最佳实践

项目中常用定时器来处理动画或视图变动。程序后台运行时,会主动停止定时任务,而回到前台则恢复基础定时任务。确保多端任务执行逻辑一致是关键。比如,H5和App端采用不同定时器方法。在游戏或交互应用开发中,这种方法至关重要。若处理不当,动画效果可能不稳定,影响用户体验。以一款休闲游戏为例,后台切换多次后回到前台,动画流畅度会因定时器处理方式不同而受影响。

软键盘高度获取的差异

在App上获取软键盘的高度相对容易,但在H5上则较为复杂。不同浏览器对软键盘弹出时的页面模式没有统一标准。幸运的是,主流浏览器都提供了相应的接口支持。然而,在实际开发过程中,一些侧重商务功能的软件可能受到较大影响。比如,那些需要频繁输入长文本的商务邮件应用,若无法准确判断软键盘高度,可能会影响用户的输入体验。对于前端开发者而言,为了兼容各种浏览器,往往需要编写更多的代码来应对各种不同的情况。

import Vue from "vue";
const DELAY_TIME = 300;
let callbackList = [];
let unimplementedChangeList = [];
function emit(target, payload) {
  if (target.length) {
    for (let i = 0; i < target.length; i++) {
      target[i](payload);
    }
  }
}
// 页面原始高度
let windowHeight = 0;
function onKeyboardHeightChangeWithH5() {
  let extraHeight = 0;
  let hasFocus = false;
  let originScrollY = 0;
  let cancheHeight = 0;
  let keyboardChangeTimer = null;
  function exec(height) {
    const keyboardHeight = Math.max(0, windowHeight - height);
    if (cancheHeight === keyboardHeight) {
      return;
    }
    cancheHeight = keyboardHeight;
    const { isIos } = Vue.prototype;
    emit(callbackList, {
      extra: isIos ? extraHeight : 0,
      height: keyboardHeight,
    });
  }
  window.addEventListener(
    "focus",
    (e) => {
      if (
        e instanceof FocusEvent &&
        (e.target instanceof HTMLInputElement ||
          e.target instanceof HTMLTextAreaElement ||
          e.target.contenteditable)
      ) {
        hasFocus = true;
        originScrollY = window.scrollY;
        setTimeout(() => {
          hasFocus = false;
        }, 600);
      }
    },
    { capture: true }
  );
  window.addEventListener(
    "blur",
    (e) => {
      if (
        e instanceof FocusEvent &&
        (e.target instanceof HTMLInputElement ||
          e.target instanceof HTMLTextAreaElement ||
          e.target.contenteditable)
      ) {
        hasFocus = true;
        setTimeout(() => {
          hasFocus = false;
        }, DELAY_TIME);
      }
    },
    { capture: true }
  );
  window.addEventListener(
    "scroll",
    () => {
      if (hasFocus) {
        extraHeight = window.scrollY - originScrollY;
      }
    },
    { capture: true }
  );
  if (typeof window.visualViewport !== "undefined") {
    return window.visualViewport.addEventListener("resize", (e) => {
      if (hasFocus === false) {
        return emit(unimplementedChangeList);
      }
      if (keyboardChangeTimer) {
        clearTimeout(keyboardChangeTimer);
      }
      keyboardChangeTimer = setTimeout(() => {
        exec(e.target.height);
      }, DELAY_TIME);
    });
  }
  window.addEventListener("resize", () => {
    if (hasFocus === false) {
      return emit(unimplementedChangeList);
    }
    if (keyboardChangeTimer) {
      clearTimeout(keyboardChangeTimer);
    }
    keyboardChangeTimer = setTimeout(() => {
      exec(window.innerHeight);
    }, DELAY_TIME);
  });
}
let isInited = false;
function initKeyboardHeightChangeListener() {
  // #ifdef APP-PLUS
  uni.onKeyboardHeightChange((res) => {
    emit(callbackList, { extra: 0, height: res.height });
  });
  // #endif
  // #ifdef H5
  windowHeight = Vue.prototype.windowHeight;
  onKeyboardHeightChangeWithH5();
  // #endif
}
/**
 * @callback OnKeyboardHeightChangeCallback
 * @param {{ extra: number; height: number }} 键盘高度(ios 中还有底部块的高度)
 */
/**
 * @typedef Options
 * @type {Object}
 * @property {boolean} reset app 端对 uni.onKeyboardHeightChange 重置侦听
 */
/**
 *
 * @description 侦听键盘高度变化事件, 对多端做兼容处理
 * @param {OnKeyboardHeightChangeCallback} callback 键盘高度变化事件回调
 * @param {Options} options 额外参数
 */
function onKeyboardHeightChange(callback, options = {}) {
  const { isPc } = Vue.prototype;
  if (isPc) {
    return console.error(
      "PC devices do not need to listen for soft keyboard height"
    );
  }
  // #ifdef APP-PLUS
  if (options.reset) {
    isInited = false;
    callbackList = [];
  }
  // #endif
  if (typeof callback === "function") {
    callbackList.push(callback);
  }
  if (isInited === false) {
    isInited = true;
    initKeyboardHeightChangeListener();
  }
}
/**
 *
 * @description 移除事件侦听函数
 * @param {OnKeyboardHeightChangeCallback} callback 需要移除的已注册函数
 */
function offKeyboardHeightChange(callback) {
  if (typeof callback === "function") {
    const index = callbackList.indexOf(callback);
    if (index >= 0) callbackList.splice(index, 1);
  }
}
/**
 *
 * @description H5 页面高度变化但未执行键盘高度变化事件时触发
 * @param {OnKeyboardHeightChangeCallback} callback 需要添加的注册函数
 */
function onUnimplementedChange(callback) {
  const { isPc } = Vue.prototype;
  if (isPc) {
    return console.error(
      "PC devices do not need to listen for soft keyboard height"
    );
  }
  if (typeof callback === "function") {
    unimplementedChangeList.push(callback);
  }
  if (isInited === false) {
    isInited = true;
    initKeyboardHeightChangeListener();
  }
}
/**
 *
 * @description H5 页面高度变化但未执行键盘高度变化事件时触发
 * @param {OnKeyboardHeightChangeCallback} callback 需要添加的注册函数
 */
function offUnimplementedChange(callback) {
  if (typeof callback === "function") {
    const index = unimplementedChangeList.indexOf(callback);
    if (index >= 0) unimplementedChangeList.splice(index, 1);
  }
}
export default {
  onKeyboardHeightChange,
  offKeyboardHeightChange,
  onUnimplementedChange,
  offUnimplementedChange,
};

在进行项目开发过程中,大家是否遇到过不同平台间差异显著的难题?期待大家分享个人经历,同时也欢迎对这篇文章给予点赞和转发。

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 行业资讯 深入探讨uniapp项目开发经验总结与最佳实践 https://www.7claw.com/2804623.html

七爪网源码交易平台

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务