美文网首页
uniapp 开发微信小程序问题笔记

uniapp 开发微信小程序问题笔记

作者: z_hboot | 来源:发表于2023-01-01 16:07 被阅读0次

    最近接手了一个小程序开发,从头开始。使用了 uniapp 搭建,以前没有做过小程序开发,着手看文档、查文档。一步一步完成了任务的开发。特此记录开发过程中的问题。

    开发建议:

    • 使用 HBuilderX 工具进行开发。通过工具创建项目
    • 遇到原来的 vue 写法怎么不生效,别犹豫去看文档,可能就是不支持。
    • 有时间熟读文档。
    • 跨端最大的问题就是兼容性。

    1. 不能采用全局注册的方式注册组件

    通常在 components 目录会存放项目中共用的组件,然后暴露install,全局引用安装

    // components/index.js
    
    // 各种组件
    import Page from "./page.vue";
    
    //
    const Components = [Page];
    export default {
      install: (app) => {
        // 注册
        Components.forEach((component) => app.component(component.name, component));
      },
    };
    
    // 然后在 main.js 引用注册
    import Vue from "vue";
    import Component from "@/components";
    
    // 注册 就可以全局使用了。
    Vue.use(Component);
    

    但是在 uniapp 中不生效,有两种方式实现组件注册:

    1.1 导入到 main.js 中进行注册

    所有的组件直接导入到 mian.js 中,通过 Vue 对象注册即可在其他页面中引用。

    要注意的是,注册的组件名必须是字符串,不能是page.name

    import Vue from "vue";
    import Page from "@/components/page.vue";
    
    Vue.component("page", page);
    

    1.2 特有的 easycom 模式注册组件

    只要符合components/组件名称/组件名称.vue 文件存储路径,则不需要手动注册,可直接引用组件。

    而且这有助于打包时剔除掉没有使用到的组件。

    那现在我们的功能组件存放路径改为components/page/page.vue ,即可全局使用。

    也可以在pages.json 配置自定义设置,定义哪些匹配的组件。

    {
      "easycom": {
        "autoscan": true,
        "custom": {
          // uni-ui 规则如下配置
          "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
        }
      }
    }
    

    新加的组件注意清除缓存,重新运行生效。

    2. 小程序真机调试包太大,无法上传,分包处理

    由于开始项目,所有的 UI 设计图都放在了前端,导致编译后整个包大小超过了 4M。开发时并没有提示这个问题,准备真机测试时,提示无法上传。就去找解决方案。

    在采用方案之前耗费了好多时间去手动删除一些不用的文件、删除不用的代码。再一看无济于事,看来代码并占不了多少。

    2.1 将所有静态资源都存放到远程服务器上

    2.2 采用分包的方式,将主包的体积降下来

    分包的方式,刚开始的时候所有的文件都是放在pages下的,pages.jon中 也都配置在 pages中。

    需要将初始加载无关的模块拆出来,同 pages 同级目录下。

    |———————————————————————————————————— 项目
    |—————————————— integral
    |——————— rank
    |——————— log
    |——————— mall
    |—————————————— pages
    |——————— index
    |——————— login
    |——————— user
    |—————————————— pages.json
    
    

    pages.jong 通过属性subPackages 配置分包编译。

    root 为分包的主目录,pages 目录下的页面,path为相对路径。

    {
      "pages": [
        {
          "path": "pages/index/index",
          "style": {
            "navigationBarTitleText": "首页"
          }
        },
        {
          "path": "pages/login/login",
          "style": {
            "navigationBarTitleText": "登录"
          }
        }
        // ...
      ],
      "subPackages": [
        {
          "root": "integral",
          "pages": [
            {
              "path": "rank/rank",
              "style": {
                "navigationBarTitleText": "排行榜"
              }
            }
            // ...
          ]
        }
      ]
    }
    

    然后重新运行,再次真机调试,没有此前的包过大的提示。顺利打开小程序。

    分包之后,检查此前已写好的模块之间的跳转。页面路径已经变化,

    可以通过预加载的方式帮助我们在进入某个页面时,由框架自动预下载可能需要的分包,提高后续页面进入的启动速度。

    以下配置,帮助我们在进入首页后,加载全部的分包。也可以指定加载分包的某个页面,具体查看官网preloadrule

    {
      "preloadRule": {
        "pages/index/index": {
          "network": "all",
          "packages": [""]
        }
      }
    }
    

    3. 内置组件不能绑定 class 的问题

    在使用扩展的 UI 组件,比如 uni-ui、uView 等给这些组件绑定 class 时,渲染并不能渲染成功。

    只能在给他们包一层view 自定义 calss 。避免全局的样式污染。

    4. 定位 API 调用,需要增加授权配置manifest.json

    增加配置,允许小程序调用位置的权限接口。然后通过requiredPrivateInfos定义你需要哪些方法。

    {
      /* 小程序特有相关 */
      "mp-weixin": {
        // ...
        "permission": {
          "scope.userLocation": {
            "desc": "请求获取地理信息"
          }
        },
        "requiredPrivateInfos": [
          "getLocation",
          "chooseAddress",
          "choosePoi",
          "chooseLocation"
        ]
      }
    }
    

    如果我们如果想在小程序中功能使用定位功能,则需要申请高德、腾讯或其他地图的 SDK ,通过拿到的经纬度查询详细地址信息。

    uni.getLocation(options)获取当前地理位置。

    不能获取到地址中文描述,只能拿到经纬度等其他参数,可以在通过第三方地图服务,获取详细的位置信息。

    address 地址信息仅 APP 端支持。

    uni.chooseLocation(options) 提供给用户选择位置信息

    可以拿到经纬度、位置名称以及详细的 address 中文描述。

    5. 主包不能引用分包的组件

    通过分包后,降低了主包的大小。但也出现了一个问题就是主包不能复用分包的组件,很容易理解就是访问主包的页面时,分包还不一定加载。

    6. 小程序不支持 $attrs \ $listeners

    通过对组件进行二次封装、三次封装。底层组件定义的属性、事件如果每层都定义接收,就很麻烦,

    在 vue 中,通过属性inheritAttrs: false 不然根元素承载这些属性、时间,然后通过$attrs \ $listeners 绑定到目标元素上。

    <template>
      <view class="dictionary-picker">
        <data-picker v-bind="$attrs" v-on="$listeners"></data-picker>
      </view>
    </template>
    
    <script>
    export default {
      inheritAttrs: false,
    };
    </script>
    

    在 uniapp 中,则是不可以的。他没有 $attrs \ $listeners 这两个属性。

    7. 不支持自定义双向绑定model

    在 vue 中定义一个组件的输入、输出通过绑定值、然后监听抛出事件处理逻辑,

    <script>
    export default {
      name:'data-picker',
      model:{
        prop:'value',
        event:'change',
      },
      methods:{
        handleChange(val){
    
          this.$emit('change',val)
        }
      }
    }
    

    这样在调用组件时可通过v-model绑定。<data-picker v-model='value' />

    在 uniapp 中,则是不可以的。 小程序不支持

    8. 不能绑定给 style、class 对象

    小程序端不支持绑定对象给 class、style

    <template>
      <view class="dictionary-picker">
        <view :class="boxStyle"></view>
      </view>
    </template>
    
    <script>
    export default {
      computed: {
        boxStyle() {
          return {
            active: this.activeTab ? true : false,
          };
        },
      },
    };
    </script>
    

    这样是不行的,渲染后的元素节点显示 object 。 不通过计算属性,直接在属性上绑定逻辑。

    <template>
      <view class="dictionary-picker">
        <view :class="[activeTab ? 'active' : '']"></view>
      </view>
    </template>
    

    9. 适配 iphone 底部刘海

    在需要适配的页面,元素增加样式。特有的变量safe-area-inset-bottom \ safe-area-inset-bottom

    建议这种通用性设置,提供一个基础公共组件page. 通过定义插槽 nav \ header \ main \ footer 插入内容。这是一些公共的样式就不用每个页面去设置。

    .footer {
      padding-bottom: 0;
      // IOS <11.2
      padding-bottom: constant(safe-area-inset-bottom);
      // iso >11.2
      padding-bottom: env(safe-area-inset-bottom);
      // 安全距离设置后,一定要设置背景,不然滚动的内容在下方可以看到
      background-color: #fff;
    }
    

    10. 一些全局的配置色彩,字号 注意单位、格式。

    在配置pages.json的一些设置,颜色都是必须是十六进制颜色,不能是 rgb 或 rgba

    • globalStyle.navigationBarBackgroundColor 导航栏背景颜色

    • globalStyle.backgroundColor 下拉显示出来的窗口的背景色

    • tabBar.color tab 上的文字默认颜色

    • tabBar.backgroundColor tab 的背景色

    • tabBar.fontSize 文字默认大小

    • tabBar.iconWidth 图标默认宽度(高度等比例缩放)

    • ...

    11. 自定义手机顶部的导航栏。

    通常手机顶部信号、电量等一些状态占据手机的部分位子。想让这部分区域也融入到我们的程序中。

    配置pages.jons

    {
      "globalStyle": {
        "navigationStyle": "custom"
      }
    }
    

    设置自定义导航样式,这样你的页面会以手机屏幕的最顶端开始。顶部标题、返回都需要自己去定义了。

    12. 在视图中不能直接使用绑定在Vue.prototype上的全局变量

    直接在视图使用Vue.prototype上的变量是访问不到的。向下面这样:

    <template>
      <view>
        <img :src="$baseUrl + data.imgUrl" />
      </view>
    </template>
    

    可以通过计算属性,或者提供一个变量值.

    <template>
      <view>
        <img :src="avatarUrl" />
      </view>
    </template>
    <script>
    
    export default {
        data() {
        return {
          //
          data:{}
        }
      },
      computed: {
            avatarUrl() {
                return this.$baseUrl + '/upload' + this.data.imgUrl;
            }
        },
    

    13. 二次封装 uni-ui 组件,更改的组件样式未生效。

    微信小程序里的组件之间的样式隔离,只需要增加选项配置,

    <script>
    export default {
        name: 'confirmDialog',
        options: {
            styleIsolation: 'shared' // 解除样式隔离
        },
    }
    

    微信官方文档说明 - 样式隔离

    14. 使用微信小程序插件 plugin

    主要是小程序插件 plugin 的开发文档,在manifest.json 中配置

    {
      "mp-weixin": {
        "appid": "",
        "usingComponents": true,
        "plugins": {
          "myPlugin": {
            "version": "版本号",
            "provider": "wx8**********75"
          }
        }
      }
    }
    

    14.1 在这边引入的插件可全局引用,在需要引入的页面中配置,pages.json

    {
      "pages": [
        {
          "path": "pages/login/login",
          "style": {
            "navigationBarTitleText": "登录",
            "enablePullDownRefresh": false,
            // 定义微信插件
            "mp-weixin": {
              "usingComponents": {
                "login": "plugin://myPlugin/login"
              }
            }
          }
        }
      ]
    }
    

    然后在页面 login.vue 中使用组件

    <template>
        <view class="login-box">
            <login
                :config="loginConfig"
            ></login>
    </template>
    

    14.2 分包引入插件,只能在分包中使用

    pages.json配置,同一个插件不能被多个分包引入,直接放入主包中配置。

    {
      "subPackages": [
        {
          "root": "integral",
          "pages": [
            {
              "path": "integralMall/list"
            }
          ],
          "plugins": {
            "pluginName": {
              "version": "版本号",
              "provider": "wx8**********75"
            }
          }
        }
      ]
    }
    

    15. 拦截器uni.addInterceptor(API,Options)

    对于 uni 可调用的全局 API,可通过拦截器来批量处理逻辑,常用就是拦截请求,控制权限。

    App.vue 中调用拦截,定义拦截器在未注册时控制某些页面不可访问。

    import { Not_register_access_page } from "@/utils/config.js";
    
    export default {
      onLaunch: function () {
        // 跳转拦截
        uni.addInterceptor("navigateTo", {
          invoke(config) {
            if (
              !$this.isRegister &&
              !Not_register_access_page.includes(config.url)
            ) {
              // 不允许访问,则将前置访问的page地址置空
              config.url = "";
            }
          },
        });
      },
    };
    

    拦截器options参数

    • invoke 拦截前触发
    • success 成功回调触发
    • fail 失败回调触发
    • complete 完成回调后触发

    uni.removeInterceptor(API)删除拦截器

    相关文章

      网友评论

          本文标题:uniapp 开发微信小程序问题笔记

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