uni-app常见问题解决办法

easycom组件模式是怎么回事

官方文档:https://uniapp.dcloud.io/collocation/pages?id=easycom

easycom组件就是符合components/组件名称/组件名称.vue目录结构的组件。

简单说,只要听从官方的约定,那么无需引入、无需注册,可以实现开发时全局使用、打包时按需打包。

注意事项:

  1. 官方文档说的注意事项我就不重复了。

  2. 小程序原生组件要放到/wxcomponents/里面,并不是放到components里面,也不适用easycom。

  3. 符合components/组件名称/组件名称.vue目录结构,只要存放,无需其他任何操作就会被HBuilderX认出,但现实中几乎没人这么存,因为我们可能要使用多个组件库,这时候怎么办?你可以到pages.json去明确注册一下,这样存放路径就不那么受限了。例如:

// pages.json
{
    "easycom": {
        "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
    },
    
    // 以下为pages.json本身已有的内容
    "pages": [
        // ......
    ]
}

我们就看这行,它其实类似于正则替换,以u-开头的组件名,都会自动去@/uview-ui/components里面找。

"^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"

如果还有一个组件库也是以u-开头作为组件名呢?怎么解决冲突?

首先看哪个组件库是低使用频率的,然后pages.json注册它的时候,不要写^u-(.*),改成别的前缀,比如^ux-(.*),使用的时候也注意要使用这个前缀就行了,比如

vue语法 this.$emit('update:xxx') 在小程序不生效?

似乎就是不生效,可以用另外的写法:

this.$emit('update:fieldValue', e.detail.value);
// 改成:
this.$emit('update', e.detail.value);

其中fieldValue是prop名,由于父组件里要显式声明自定义事件,所以改成省略。

然后,父组件里需要显式声明自定义事件:

// 给组件加上
@update="password=$event"

页面间传递数据、调用方法的几种方式

URL传参

就不说了。

向navigateTo的页面传递数据、调用方法

这个是小程序的基础知识,在此简单说一下。比如,我想调用后一个页面的xxxToast方法,做法是:

A页面:

    methods: {
      onTap() {
        uni.navigateTo({
          url: '/pages/mine/index',
          success: (res) => {
            res.eventChannel.emit('xxxToast', { title: 'TOAST的标题' });
          }
        })
      }
    }

mine页面:

    onLoad() {
      const eventChannel = this.getOpenerEventChannel();
      eventChannel.on('xxxToast', ({title}) => {
        uni.showToast({
          title
        })
      }),
    },

向navigateBack的前一页传递信息

有这样一个场景,从文章列表页打开某个详情页,详情页有个删除按钮,点击删除,则文章被删除,并跳回列表页,列表页应重新ajax,或者从内存中的列表数组中删掉该文章。让列表页更新数据不允许无脑更新,必须是有指令才更新,没指令则不更新。我们分析一下:

  • 似乎需要用navigateBack,但是navigateBack的success不具有res.eventChannel能力。

  • navigateBack没有url属性,无法URL传参。

  • 换用navigateTo的话,被删除的详情页会留存在页面栈,手机回退会重新进入被删除的详情页,肯定不允许。

  • 换用redirectTo的话,虽然详情页被杀掉,因此不会重新进入详情页,但是进入列表页之后,手机回退会又进一次列表页,也不允许。

所以,我们依然需要用navigateBack,然后用某种方式传递信息,怎么办呢?

可以利用getCurrentPages()获取页面栈,然后执行前一页的方法即可。

A页面:

    methods: {
      list() {
        // ...
      }
    }

mine页面(也就是B页面):

原理是利用页面栈调用其他页面的方法。但不同平台又有区别。

  • H5和小程序必须先调用页面栈的方法,再回退,也就导致,页面栈要找倒数第二个页面。

  • APP可以有2个选择,那么采用上方的方法,要么是先回退,再调用页面栈的方法。

综合说,应当全平台统一采用先调页面栈、后回退的方式。

然后区分.$vm

    methods: {
      onTap() {
            let pages = getCurrentPages();
            let prevPage = pages[pages.length - 2];
            // #ifdef H5
            prevPage.list();
            // #endif
            // #ifndef H5
            prevPage.$vm.list();
            // #endif
            uni.navigateBack()
      }
    }

A页面调用uni原生方法,B页面显示

现在,我们不跨页调用自定义方法,只是调用uni原生方法, 这时候最简单,直接写到success就行了。适用于所有路由方法。不适用于H5,因为H5一旦路由变化就终止一切后续代码。

        uni.navigateBack({
          success: () => {
            uni.showToast({
              title: '哈哈哈'
            })
          }
        });

引用本地图片作为背景图

本地背景图片的引用路径推荐使用以~@开头的绝对路径。

动态添加右上角按钮

          // #ifdef APP-PLUS
            var wv = plus.webview.currentWebview();
            wv.setStyle({
                titleNView: {  
                    titleText: '删除'  
                }  
            });
          // #endif

同样的,plus.webview.currentWebview()可以做很多事,参看:

https://www.html5plus.org/doc/zh_cn/webview.html#plus.webview.WebviewObject

你可能感兴趣的:(uni-app常见问题解决办法)