v***@163.com
v***@163.com
  • 发布:2019-05-08 18:58
  • 更新:2024-11-01 17:10
  • 阅读:43988

uniapp怎么设置所有页面共用的组件

分类:uni-app

就是一个组件,我只想全局注册一次,不需要在需要用的页面再去引用,像vue里面app.vue的那种效果

2019-05-08 18:58 负责人:DCloud_UNI_OttoJi 分享
已邀请:

最佳回复

DCloud_UNI_OttoJi

DCloud_UNI_OttoJi - 日常回复 uni-app/x 问题,如果艾特我没看到,请主动私信

久等了,我来看下这个问题,我看到评论中提到的一些解决方案有平台限制,我研究下,有进展我会更新到这里。

多端通用的 uniapp 怎么设置共用的组件

uniapp 怎么设置所有页面共用的组件
https://ask.dcloud.net.cn/question/70510

我看了评论区各位的反馈,有的讨论已经大大拓展了最初的问题,也有热情的社区用户贡献了技术方案,特别感谢他们,为他们点赞。

很多人争论的点,是使用场景不同,小程序、app 环境会有一些限制,不能直接使用浏览器 h5 的方案,这样导致了一些用户评论的误解。我整理下不同的业务场景,供不同需求的人使用。下面场景始终考虑多端。

前置共识:

  • 在小程序运行环境和 h5 不同,没有 document 方法,也就不能创建元素、插入元素。
  • 小程序环境中,彼此页面独立
  • uni-app 在 vue2 中使用 webpack 工具,在 vue3 中使用 vite 工具。

场景 1: 最简单的组件复用

无论是 h5、小程序、app 都遵循 vue 的写法,引入组件 - 使用组件。

也就是组件需要先引用注册,再去使用。在 vue2/vue3 中引入组件都一致。

场景 2:组件不想每次都 import 引入

组件每次都需要 import,推荐使用 easycom 功能。

easycom 是 HBuiderX 2.5.5 可用的功能,早期的讨论可能没注意到

使用 easycom 自动注册方案,使用 uni-app 提供的功能特性,自动按照规则自动匹配,直接使用
https://uniapp.dcloud.net.cn/collocation/pages.html#easycom

省去了导入的方案,效果和场景 1 一样,正常使用组件。

场景 3:想自定义实现 uni.showToast

uni-app 内置的 uni-showToast 可以通过函数调用实现消息弹窗,这个在小程序端是依赖小程序本身提供的功能做的包装。比如微信小程序提供了 wx.showToast 方法。

有的业务想拓展功能、更改样式,符合自己的业务逻辑。比如评论里提到的全局剪切板弹窗、全局悬浮球等。在 web/app 中很容易实现,但在小程序端不能实现,因为小程序本身不支持动态创建。那要怎么做呢?看看小程序组件库就知道了。

在小程序组件库中,为了解决这个场景,一般需要在 template 里使用组件,在逻辑中控制组件显隐,说到底是要保证弹窗里的元素在页面中存在,等待唤起生效。

伪代码如下:

<xx-popup show="{{ show }}" bind:close="onClose">内容</xx-popup>

如果不想在模版中声明组件,可以考虑在编译时候自动填充内容。举例子,比如用户这样伪代码:

<template>  
  <view>123</view>  
</template>

通过编译器插件编译时候追加元素。

<template>  
    <my-toast ref='mytoast' />  
    <view>123</view>  
</template>

也就是说,这个组件声明是必须存在的,只是由谁来完成。

在 uni-app 的工具链中,使用了 webpack/vite,社区热心的用户已经开发了对应的插件功能。

比如:

  • webpack 方案 vue-inset-loader ,核心思路是调整 webpack 配置使用 loader,对文件进行中间处理。文档地址 https://ask.dcloud.net.cn/article/39345 仓库地址 https://github.com/1977474741/vue-inset-loader
  • vite 插件方案 vue3-inset-loader,和上面思路一致,vite 方向的插件,仓库地址 https://github.com/smartXJ/vue3-inset-loader/tree/main

两个方案,都使用了相同的配置,不需要额外学习配置方法。由衷感谢社区的共享方案,大家有时间可以给点点 github star。

场景 4:想实现 app.vue 的效果

这里讨论比较多,用户想和 web 一样,对 app.vue 进行修改,实现一劳永逸的效果。如果考虑多端实现,就不能这样做。因为 app.vue 在小程序端不参与页面渲染。app.vue 地址

技术实现思路是,使用一个自定义组件放在页面顶部,通过插槽 slot 编写具体的页面逻辑,可以实现整体页面的包装。这种方案比较直观,同样可以实现场景 3 的需求。

<template>  
    <my-page>  
        <view>123</view>  
    </my-page>  
</template>

这里推荐社区热心用户 自学的烦恼,提供的方案 https://ext.dcloud.net.cn/plugin?id=2560

总结

可以看到,最终还是因为平台限制不能想 web 一样灵活,产生了各种变通方案。

如果上面提到的场景,还不能满足你的需求和使用场景,你可以提供你的发行方案,描述使用场景反馈给我。

  • 1***@qq.com

    希望能支持小程序,app(vue,nvue) 这些页面,谢谢

    2024-01-30 11:16

  • DCloud_UNI_OttoJi

    回复 1***@qq.com: 请看下我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:30

  • 1***@qq.com

    回复 DCloud_UNI_OttoJi: 之前开发的 app 场景就是之前页面开发太多了,逻辑比较多,不想全部改动变成插槽的形式,有没有其他方式实现呢

    2024-04-12 17:22

  • 爱tutu爱生活

    不能解决要求啊,app从登录到使用的页面如果断网了要像微信那种的提示如何实现?

    2024-06-19 15:52

  • _Skiyee

    大家可以看看这个解决方案,模拟实现 app.vue 的效果,目前Hbx与cli项目均支持


    https://github.com/uni-ku/root

    2024-09-10 17:32

2***@qq.com

2***@qq.com

uni-app 不提供全局挂载的方法,只能退而求其次:

1.通过Vue.use定义一个全局组件的挂载点,如下:

  1. 定义一个全局组件,把你所有想用的全局组件定义到里面,如下图

在mounted钩子中把想要全局使用的方法全部挂到上一步定义的挂载点上

3.在main.js中申明这个全局组件
Vue.component('global', Global);

4.使用方法:
在要使用的组件中加载全局组件
<template>
<view >
<global />
</view>
</template>

在方法中通过 this.$gc.$toast('xxx') 使用即可

  • corgi

    大佬好,那你这样,每个页面还是需要去引用下组件把?

    2021-01-18 17:12

  • 1***@163.com

    这样的做法就是页面回退组件会失效

    2021-04-02 08:39

  • w***@126.com

    这个可以解决返回页面失效问题,代码有点复杂 可以适当理解一下 大致逻辑就是在全局定义的时候是注册在当前页面下而不是全局,调用的时候根据当前页面进行查找返回,这样其实每一个页面的show方法其实都在$w下


    import Vue from 'vue'  
    export const name = 'gobalComponents'
    // 配置全局组件,保证全局组件在返回页面时依旧可以使用
    const get = (name) => {
    let $w = Vue.prototype.$w
    const page = uni.$u.page()
    return $w?.gobalComponents[`${page}`][`${name}`]
    }
    const add = (name, fn) => {
    let $w = Vue.prototype.$w
    const page = uni.$u.page()
    const addObj = ($w?.gobalComponents && $w?.gobalComponents[`${page}`]) ?
    $w.gobalComponents[`${page}`] : {}
    addObj[`${name}`] = fn
    $w.gobalComponents = {
    ...$w.gobalComponents,
    [`${page}`]: addObj
    }
    Vue.prototype.$w = {
    ...$w,
    get [`${name}`]() {
    return get(name)
    }
    }
    }
    export default {
    add,
    get
    }

    2022-09-03 22:00

  • w***@126.com

    回复 w***@126.com: 这里有一个小问题,由于用的是拓展运算符,所有如果又多个全局组件,最后一个会把前面的覆盖掉(也不算是覆盖 就是会让前面的get失效),后来考虑使用Proxy统一写一个get函数进行处理就ok了

    2022-09-03 23:07

hhyang

hhyang - 如有问题,请添加QQ1606726660 备注付费咨询

  • v***@163.com (作者)

    这样页面上还是需要去写一次,我想弄个全局都统一用的不用单独写了,好像不行

    2019-05-09 15:28

  • 飞翔的腿毛

    回复 v***@163.com: 解决了么?uni-app不能操作dom貌似不能append到body下面

    2019-06-19 16:08

  • g***@gmail.com

    按照这种方式进行了尝试,在h5模式下有效,但是在app上没有效果,这个算是一个问题吗

    2019-07-10 15:44

  • 忘记我是谁

    回复 hhyang: 他的意思是 就跟用 uni.showToast 一样 uni.showToast都不需要全局注册,也不需要在页面上加标签, 现在只想全局引用一次 ,页面上不用加标签,直接调用方法就完事了

    2019-07-19 17:12

  • 迪丽热bug

    回复 飞翔的腿毛: appned可以 但是小程序的话没有找到body这个属性

    2019-10-08 14:07

  • 曼殊沙华

    回复 v***@163.com: 老哥问题结局没有,我也是遇到这个

    2020-01-14 15:48

  • 霍金

    回复 hhyang: 人家是在想优化的方法,你却在嘲讽人家懒

    2020-04-11 19:12

  • 1***@qq.com

    我弄的tabbar组件在页面引入每次点击就会样式没加载就出来了 然后点击一遍后就好了 怎么解决

    2020-05-22 17:52

  • 蓝眸

    回复 hhyang: 听不懂需求就不要瞎jb逼逼,你这冷嘲热讽的语气,听着就想给你龟儿两巴掌

    2020-10-16 11:32

  • 蓝眸

    回复 v***@163.com: 你是想做一个全局页面都使用的类似悬浮按钮的功能吧

    2020-10-16 11:34

  • 花满袖

    回复 蓝眸:我就想做这个功能,这边有好的办法吗?求解

    2020-10-25 14:52

  • 5***@qq.com

    回复 hhyang: 他的意思是每个页面都要引入那个组件的插槽,他想要页面不写插槽,统一引入,所有页面公用,比如100个页面我要写100个插槽,但我就只想写一次

    2021-02-22 17:17

  • 4***@qq.com

    回复 hhyang: 这么简单的问题都没有听懂,他的意思就是不用每个页面都有代码,在全局文件引入就行了,看你也不聪明到哪里去,一遇到这种问题,不理解就说这么极端的话,看不起人的最让人看不起。鄙视你这种回答问题的方式。自己250,别把所有人想成250

    2021-04-10 14:41

  • 谭小谭

    回复 1***@qq.com: 所有人都听懂需求了,就你没懂,你还有脸嘲讽别人,你可以不回答,何必语出伤人?都是搬砖的,何必谁又看不起谁

    2021-07-15 09:59

  • 2***@qq.com

    普通的vue很轻松就能实现的功能嘲讽尼玛呢

    2021-07-24 02:02

  • 2***@qq.com

    不会做就别逼逼

    2021-07-24 02:03

  • 云淡风轻gfg

    回复 蓝眸: 你好,我也有相同的需求。我想让一个组件长留页面,比如我有一个悬浮框组件,我从A页面切换到B页面,这个组件还在。这个该怎么做了

    2021-10-09 09:29

  • 4***@qq.com

    回复 hhyang: 看到大家都在骂你我就放心了

    2021-10-29 15:30

  • 霍霍

    回复 v***@163.com: 我也有这个需求,已经差不多快成熟的产品,现在要追加一个全局功能,要是每个页面再去加组件感觉不太好,而且万一以后还要加其他的就更麻烦了,不知道有解决办法没有

    2021-12-23 10:44

5***@qq.com

5***@qq.com

我也想知道怎样才能只要全局注册组件每个页面不用写组件也能使用。。。

8***@qq.com

8***@qq.com

我也想知道怎样才能只要全局注册组件每个页面不用写组件也能使用。。+10086

m***@live.cn

m***@live.cn

楼主说的应该是Vue中app.vue文件里写的html内容吧?
是不是例如

<template>  
  <div id="app">  
    <router-view/>  
    <my-component></my-component>  
  </div>  
</template>

中的my-component?
是的话我也想问这个。
否则页面多到十几或者几十个的话,每个页面都要去写一遍,太麻烦了。

现在uniapp里的app.vue没有html部分...

  • 6***@qq.com

    同问?有没有办法解决?

    2020-01-09 10:43

  • 小花生

    直接在app里添加 template 好像可以

    <template>

    <view>

    <router-view/>

    <foot-bar></foot-bar>

    </view>

    </template>

    2020-05-01 19:44

  • 小花生

    回复 6***@qq.com: 在app中添加 teamplate,h5可以跑起来

    2020-05-01 19:52

  • 前端花美男

    直接在app里面跟写<template>

    <view>

    <router-view/>

    <bottomBotton />

    </view>

    </template>就行 ,比如这个 ,,哎 ,,一波人搞不清状况的别瞎回复。。。

    2020-06-03 20:08

  • 4***@qq.com

    回复 前端花美男:你这样 h5可以,app上就不行了,兄弟,看清问题

    2020-07-30 19:04

  • t***@163.com

    回复 前端花美男: 你这样不行,uni-app文档明确说了app.vue不是视图不能编写页面元素。

    2020-11-05 08:50

Jeking

Jeking

app平台,可以通过创建一个透明的页面A,将弹窗视图放到A页面上,显示弹窗就navigateto到A页面,具体实现可以参照这个示例 https://ext.dcloud.net.cn/plugin?id=6644

3***@qq.com

3***@qq.com

2023年了,还没有好的办法吗,不过2023年还有人连需求都没有看懂...

1***@qq.com

1***@qq.com

挂载到全局

Potato1314

Potato1314

https://github.com/xiaowang1314/uniapp-plugin-collections
随便看个例子就会了,在main.js文件里全局注册,在页面就可以直接使用

  • 霍金

    人家说的是 注册一次 就可以直接出现效果了 而不是每个页面都得引入一下 才能使用组件内具体的实例和方法

    2020-04-11 19:11

尹成诺

尹成诺 - 辣鸡前端

  • 自学的烦恼

    经测试,只有微信小程序有用,其他端报错

    2020-08-18 09:50

  • HRK_01

    回复 自学的烦恼: 可以通过改源码,使其在其他端生效

    2024-01-31 15:35

DCloud_UNI_GSQ

DCloud_UNI_GSQ

跨端通用参考方案:

  1. 新建一个 base-page.vue 文件作为页面根组件,其中引入公共组件,并暴露操作方法 showPopup。
  2. 新建一个 base-page.js 文件作为页面 mixin 引入根组件并暴露根组件操作方法 showPopup。
  3. 每个页面引入 base-page.js 并加入 mixins 中,根节点使用 base-page 组件。
  4. 页面或者组件中调用 this.$root.showPopup()。

扩展阅读:

  • 具体实现可以参考其他 自学的烦恼 写的示例:https://ext.dcloud.net.cn/plugin?id=2560
  • 其中重复的工作在步骤3,如想省略步骤3,可以尝试自行调整编译器,自动插入到每个页面。
  • 1***@qq.com

    自行调整编译器,自动插入怎么做呢?组件和调用方法都写好了,就是不希望每个页面都去引用一下文件

    2022-06-22 09:56

2***@qq.com

2***@qq.com

uni里面不是有easycom吗?不需要引用和注册啊,直接用!!一看其他评论,瞬间蒙了,难道不是简单的一个问题

1***@qq.com

1***@qq.com

都2023年了,这个问题还没解决吗,大家的需求都是一样的uni.showToast()太丑了,title还有长度限制,想自己写一个,只想引入一次,实现不了嘛,dcloud有看过这个问题吗啊?

_Skiyee

_Skiyee

解决方案:https://github.com/uni-ku/root

虚拟根组件模拟原 App.vue 的功能,可以解决大伙所遇到的问题,只需要写一次即可共享所有页面

9***@qq.com

9***@qq.com - 前端工程师

请问解决了吗 我也遇见了这个问题

北辰羽墨

北辰羽墨

具体的应用场景是不是类似全局监听剪切板,然后不管APP打开哪一个页面,都会去监听,然后就跟用 uni.showToast 一样

  • qiuxe

    对,我也想要这样的效果,请问你有解决方案吗

    2019-07-26 15:36

  • 北辰羽墨

    回复 qiuxe: 我试过了,H5可以正常用,但是在APP下无效,看了其他贴子回复说Vue.use在APP下无效,就放弃了

    2019-07-27 10:50

  • qiuxe

    是的,我就想写一个自定义的弹框然后能像uni.showToast一样调用

    2019-08-05 17:39

  • 侯小方

    回复 qiuxe: 然后写一个请求拦截器和响应拦截器来实现所有页面数据加载的loading效果?

    2019-12-09 15:27

  • 1***@qq.com

    回复 qiuxe: 解决了吗,我试了好久,h

    5可以,小程序不行

    2021-04-29 17:10

9***@qq.com

9***@qq.com - 90后

我也想知道怎样才能只要全局注册组件每个页面不用写组件也能使用。。。

  • 8***@qq.com

    这个问题你们解决了吗

    2019-12-31 14:21

  • 9***@qq.com

    这个问题你解决了吗请问

    2020-05-27 10:30

问问情

问问情 - 人生工具,辨人识人, 情有多深

我也需要这个功能!可恨的是uni.showModal太简陋

damdmen

damdmen - 社交app创业中,求靠谱合伙人

mixins是个可以解决?

  • ahhhhhhh

    mixins中引入的组件,想要在每个页面使用,还是要在每个页面中引入

    2020-03-23 23:22

6***@qq.com

6***@qq.com - 傻小子QZ

关注一个、是否可以建立一个全局组件 ,把这个全局组件当做页面标签使用,全部页面内容包含在该组件下。全局组件组件里面可以写你想要的。

  • b***@163.com

    当时页面多了,就相当于在这个全局组件下面写一堆v-if,同时路由也没用了

    2020-07-20 16:13

9***@qq.com

9***@qq.com - 购物省钱赚钱就上友优惠

楼主解决了吗,我也想实现全局监测剪切板,不管哪个页面打开都可以弹出

chenli

chenli

监听剪贴板可以写在App.vue,去执行全局弹窗。

  • 9***@qq.com

    我的弹框是个组件,怎么能在每个页面弹出而且还不需要每个页面引入该组件,要不页面多了太麻烦了

    2020-05-27 10:29

  • chenli

    回复 9***@qq.com: 全局mixins

    2020-05-29 01:20

  • 2***@qq.com

    回复 chenli: 自定义tabBar会闪....

    2020-07-31 10:05

神的尾巴

神的尾巴 - 欢迎关注我的微信公众号:神的尾巴

我提供一种我目前的解决思路:

前面回答里面说的在App.vue里面,添加template,在APP实测无效

目前我有一个通用的page组件,用来处理作为所有页面的父组件,处理loading、骨架图等,在该父组件添加全局组件

获取ref,有两个方案:

  1. 在page组件添加方法getRef(),获取page组件内的ref
  2. 初始化的时候注册到vuex,在使用的时候到vuex中取

两种方案都能获取到,看你怎么使用方便,我是使用的方案2,然后在通用mixins中添加获取全局组件的方法

  • 9***@qq.com

    好的,我试试

    2020-06-08 18:14

  • 1***@qq.com

    回复 9***@qq.com: 解决了吗?

    2020-06-15 19:20

  • s***@aliyun.com

    请问”前面回答里面说的在App.vue里面,添加template,在APP实测无效“这种方法是如何写的代码呢?可以贴一下代码吗

    2020-06-17 16:04

  • 神的尾巴

    回复 s***@aliyun.com:


    <template>  
    <view>
    <router-view/>
    <!-- 你的全局popup组件,在渲染成功后,没执行组件的mounted -->
    <popup />
    </view>
    </template>

    2020-06-18 22:48

  • 神的尾巴

    回复 1***@qq.com: 我实测可用,虽然绕了一些弯路,但还是用起来蛮顺手的,涉及代码比较多,不好贴出来,这里只提供了思路

    2020-06-18 22:50

  • 自学的烦恼

    回复 神的尾巴: 在app.vue里,其他端获取的this.$refs都是空,这方法只适合h5...

    2020-06-25 18:45

  • s***@aliyun.com

    本小白表示 上面两种方法都不会用,可以直接上代码吗

    2020-06-28 17:18

  • 神的尾巴

    回复 自学的烦恼: 我是在app、h5都测试通过了,我都快上线了

    2020-06-30 00:19

  • 2***@qq.com

    "目前我有一个通用的page组件,用来处理作为所有页面的父组件,处理loading、骨架图等,在该父组件添加全局组件",这句话不太明白,能多说点嘛?谢谢~

    2020-07-16 10:33

  • 神的尾巴

    回复 2***@qq.com: 每个页面的父组件都是page

    2020-07-17 01:02

  • 自学的烦恼

    回复 神的尾巴: 用了这个方法,navigateBack不能后退

    2020-07-21 18:47

  • 神的尾巴

    回复 自学的烦恼: 可以啊,每次page初始化的时候,重置下refs

    2020-07-21 21:13

  • 1***@163.com

    大佬,怎么设置page组件,作为所有页面的父组件啊

    2020-08-06 17:24

  • 神的尾巴

    回复 1***@163.com: 手动包裹...

    2020-08-06 19:07

  • 1***@163.com

    回复 神的尾巴: 还是没明白啊 有示例代码吗 能看看吗

    2020-08-07 15:00

  • 神的尾巴

    回复 1***@163.com: 最近我在写一些uni-app的文章,其中有一篇是全局组件的,等我完成后@你

    2020-08-10 22:22

  • 1***@163.com

    回复 神的尾巴: 好的 谢谢

    2020-08-12 17:24

  • 不争_

    回复 神的尾巴: 请问你这个方法的话是不是所有原来的页面都也要写成组件然后在page中引入,而且原来page的设置都没用了,相当于把uni-app的结构再包一层的意思?

    2020-08-14 12:00

  • 神的尾巴

    回复 不争_: 不用,只是每个页面最外层会包一个page组件,其他组件不用修改

    2020-08-14 14:32

  • 自学的烦恼

    回复 神的尾巴: 根据你的方法,终于实现了,多端支持

    2020-08-18 19:59

  • LunaMinus

    回复 神的尾巴: 这种方法的话可以实现每个页面都有,但是不是同一个。比如全局可拖拽的悬浮球,就不行,实际上每个页面的悬浮球都是重新渲染的,一个页面拖拽后,其他页面的位置要更改的话,还是很麻烦

    2020-08-25 17:11

  • 自学的烦恼

    回复 LunaMinus: 替他说一句,根据你的问题我试了试,确实是重新渲染了,但还是能用,而且修改不麻烦,位置存起来,同时用$emit就可以了

    2020-08-27 17:49

  • LunaMinus

    回复 自学的烦恼: 位置我现在用状态管理更加方便。但是,app端页面切换有动画,会看到球跟着走了。还是看着不舒服。

    2020-08-27 18:14

  • t***@163.com

    回复 神的尾巴: 你这种方式是不是自定义一个公用的页面然后其他的页面都以这个为父页面?

    2020-11-05 08:55

  • 1***@163.com

    回复 神的尾巴: 那个关于uni-app全局共用组件的文章是在微信公众号里吗?

    2021-01-05 10:28

  • 1***@qq.com

    回复 自学的烦恼: 你好,方便贴一段代码吗?

    2021-01-11 15:11

  • 自学的烦恼

    回复 1***@qq.com: https://ext.dcloud.net.cn/plugin?id=2560

    2021-01-11 19:16

  • 1***@qq.com

    这还是有点类似全局的引用呀,那对于我这快上线的项目还是得改很多页面

    2023-06-30 09:49

923

923

main.js
import tabBar from "./pages/component/tabBar.vue" //全局引入自定义底部导航
let play = Vue.component('tabBar', tabBar) //全局注册
document.body.appendChild(new play().$mount().$el)
页面里不用在引入,注册

和router-view一样原理,添加了一个和uni-app,同级的元素,点击跳转,只加载uni-app里的元素

  • 神的尾巴

    这种不能兼容全端吧?小程序应该没有document

    2020-07-02 15:04

  • yPeng

    这种可以在全端使用吗?

    2020-07-26 14:01

  • 9***@qq.com

    怎么监听这个全局组件?

    2021-08-27 10:58

熏烧鹅猪头肉

熏烧鹅猪头肉

留个标记,好像没有解决方法。

2***@qq.com

2***@qq.com - 小飞猪

都快两年了这问题还没解决方案么。。

3***@qq.com

3***@qq.com

简单得很,在components下创建组件目录,命名跟组件文件一致,然后把该组件放到对应的目录下,就可以直接在页面中使用了,不需要引入。同理,有多少个组件就创建多少个目录,记住:目录命名一定要跟组件命名一致

7***@qq.com

7***@qq.com - life is a fucking movie

使用插槽slot可解决这个问题

Gushxi

Gushxi

https://blog.csdn.net/weixin_44810066/article/details/116060159?spm=1001.2014.3001.5501

非良

非良

https://ext.dcloud.net.cn/plugin?id=2560 也就这样比较好了。

1***@qq.com

1***@qq.com

以下在App.vue中修改 h5可以正常使用,其他平台没有试过,而且App.vue中不能写v-model,只能用:value代替

<template>  
    <view>  
        <router-view />  
        <u-popup :value="true">哈哈</u-popup>  
    </view>  
</template>  
<script>  
    import uPopup from "@/uview-ui/components/u-popup/u-popup.vue";  
    export default {  
        components: {  
            'u-popup': uPopup  
        },  
        onLaunch: function() {  
            console.log('App Launch')  
        },  
        onShow: function() {  
            console.log('App Show');  
        },  
        onHide: function() {  
            console.log('App Hide')  
        }  
    }  
</script>  

<style lang="scss">  
    @import "uview-ui/index.scss";  
</style>  
  • 1***@qq.com

    但是还有一个问题,需要控制显示隐藏的变量放哪啊,不能使用data(){return{}},会冲突

    2021-09-15 17:11

  • 1***@qq.com

    h5可以用,app不能

    2023-06-30 10:05

1***@qq.com

1***@qq.com

借鉴 > https://ext.dcloud.net.cn/plugin?id=2560 也就这样比较好了。的方法
在App.vue中引用全局组件
App.vue代码如下:

<template>  
    <globe-page></globe-page>  
</template>  
<script>  
    import globePage from "@/components/globe-page.vue";  
    export default {  
        components: {  
            'globe-page': globePage  
        },  
        onLaunch: function() {  
            console.log('App Launch')  
        },  
        onShow: function() {  
            console.log('App Show');  
        },  
        onHide: function() {  
            console.log('App Hide')  
        }  
    }  
</script>

globe-page.vue代码如下:

<template>  
    <view>  
        <router-view />  
        <u-popup ref="popup" v-model="show">哈哈</u-popup>  
    </view>  
</template>  

<script>  
    import uPopup from "@/uview-ui/components/u-popup/u-popup.vue";  
    export default {  
        components: {  
            'u-popup': uPopup  
        },  
        name:"globe-page",  
        data() {  
            return {  
                show: false  
            };  
        }  
    }  
</script>  

<style>  

</style>  

关于如何在App.vue 的中onShow中改变 globe-page.vue中的 show,有多种方法可以实现,这里就不说了。

1***@qq.com

1***@qq.com

在vue.config.js中重写 vue-template-compiler 的 compile 方法可以解决

  • 愿随风丶飘雪

    请问怎么重写呢 有例子没 另外是在APP中使用的

    2022-02-17 16:13

  • 追光者

    回复 愿随风丶飘雪: 有个思路:类似官方的应用内版本升级,是一个透明的页面,进入这个页面时,跟弹框一模一样。

    2024-03-06 19:52

清茶涩

清茶涩

关注一个+10086

4***@qq.com

4***@qq.com

都已经22年了还没有好的解决方案吗...

1***@qq.com

1***@qq.com

已经放弃治疗了, 因为目前APP每个page都是单独的很少有全局像PC端这样的个性化全局头部, 取而代之的是app的navbar

霜冷九州

霜冷九州

2023 蹲一个好的方案..

  • 愿随风丶飘雪

    +1

    2023-05-04 09:14

  • 1***@qq.com

    +1

    2023-05-06 17:51

  • r***@foxmail.com

    +1

    2023-06-05 17:24

  • 拦路雨偏似雪

    +1

    2023-06-14 10:23

  • 1***@qq.com

    +1

    2023-06-30 10:13

  • 2***@qq.com

    +1

    2023-07-03 11:04

  • 1***@qq.com

    可以参考这个,https://blog.csdn.net/cv1002420186/article/details/131542803

    2023-07-05 08:18

  • 4***@qq.com

    +1

    2023-07-17 15:06

  • W***@163.com

    +1

    2023-09-02 16:08

  • 1***@qq.com

    +1, 只想自定义一个message

    2023-11-13 18:16

  • 2***@qq.com

    +1

    2024-01-22 18:05

  • DCloud_UNI_OttoJi

    回复 2***@qq.com: 请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

  • DCloud_UNI_OttoJi

    回复 1***@qq.com: 请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

  • DCloud_UNI_OttoJi

    回复 W***@163.com: 请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

  • DCloud_UNI_OttoJi

    回复 W***@163.com: 请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:32

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:32

  • _Skiyee

    这里 -> https://github.com/uni-ku/root

    只需要写一次即可共享所有页面

    2024-09-10 17:38

1***@qq.com

1***@qq.com

  • 6***@qq.com

    大佬,按这个方法修改后会报错,无法正常编译到小程序,不知道哪里有问题,具体错误如下:

    [HBuilder] 19:02:12.579 ERROR Error: EINVAL: invalid argument, mkdir 'E:\uniAppProject\MyTest\unpackage\dist\build\mp-weixin\E:\uniAppProject\MyTest\components\test'

    [HBuilder] 19:02:12.579 Error: EINVAL: invalid argument, mkdir 'E:\uniAppProject\MyTest\unpackage\dist\build\mp-weixin\E:\uniAppProject\MyTest\components\test'

    2023-07-18 19:06

  • 5***@qq.com

    回复 6***@qq.com: 编译到小程序的时候,hbuilder添加的那个得去掉

    2023-11-09 12:03

y***@163.com

y***@163.com

乌鱼子

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

董路飞

董路飞 - 搜索小程序麻丝和 App 麻丝

此贴发布:【2019-05-08 18:58】

现在这个时间 【2023/08/28】,
只需要在根目录创建components文件夹,里面写要复用的组件,然后其他页面就可以直接使用这个组件了(不需要在项目配置文件里写配置,也不需要在页面文件引入此组件)
这不就相当于公共组件?

  • 3***@qq.com

    这样还是要每个页面都要引入,楼主的意思等于Layout布局那种效果。

    2023-09-19 12:36

  • 董路飞

    回复 3***@qq.com: 请阅读完我以上说的话:“只需要在根目录创建components文件夹,里面写要复用的组件,然后其他页面就可以直接使用这个组件了(不需要在项目配置文件里写配置,也不需要在页面文件引入此组件)”

    比如我在components写的自定义组件 ABC 那么直接在pages页面文件下 把ABC当标签一样使用就是相当于使用了自己自定义的名为ABC的组件,根本并不需要导入再使用,直接就可以使用,看来你没看完过 uni-app 的基础新手教程文档

    2023-09-19 18:05

  • 2***@qq.com

    回复 董路飞: 不懂装懂也就你了

    2023-10-13 13:49

  • HRK

    回复 董路飞: 他们的意思是:哪怕不使用这个ABC这个标签也要实现自动引入,刚开始我也不理解,多看看大家的回复你就懂了

    2023-11-13 19:41

2***@kingon.cn

2***@kingon.cn

就想实现一个this.$toast()这种都不支持,我服了

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

锦鲤丶接单丶

锦鲤丶接单丶 - 锦鲤丶接单丶18560000860丶10+年开发经验

补充一下哈,我的意思就是像uni.showToast()那样直接能使用而不用在页面上写<uni-toast>类似这种元素了.

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:31

Heng_vv

Heng_vv - -------------

不是,都准备2024了,还没有解决方案吗

Heng_vv

Heng_vv - -------------

都过去5年了,还没有好的解决方案,难搞哦

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:30

[已删除]

[已删除]

有大佬解决了吗

  • DCloud_UNI_OttoJi

    请看我楼上的回复,是否满足你的要求,解答你的疑问。如果不能,请补充你的具体使用场景。

    2024-01-31 15:30

s***@outlook.com

s***@outlook.com - rookie

2024年了还没一个官方的解决方案吗?我需要一个无网络的提示页面(注意是页面不是弹框),需要所有页面都可以使用,但是我现在有100个页面,能有方案只需要引入一次就可以全局使用吗?总不能我写一个组件,100个页面全部去引入一遍吧.

锦鲤丶接单丶

锦鲤丶接单丶 - 锦鲤丶接单丶18560000860丶10+年开发经验

我这边变相的算是实现了,就是自定义一个根组件,然后每个页面的第一级组件就放这个根组件,在根组件中放公共的header、footer、公共组件等元素、然后在写个默认的<slot> 来接收每个页面的内容

  • 1***@qq.com

    你这种适合刚开始开发的时候,其他人的需求是一个项目很多页面,不想每个页面都去改动

    2024-09-20 17:14

8***@qq.com

8***@qq.com

2024 年 还没解决;还没解决

  • 你算哪根聪

    可以看看楼下的我,我看你的回复日期挺接近我的

    2024-11-01 17:02

  • s***@163.com

    回复 你算哪根聪: 我用页面来做弹框也是可以的么?

    2024-11-05 20:07

  • coderH

    极光推送的插件有这个实现 但是不知道怎么翻看代码,页面没有引入任何组件,应该是调用原生的UI生成的

    2024-11-07 11:32

  • 你算哪根聪

    回复 s***@163.com: 可以的

    2024-11-11 14:44

你算哪根聪

你算哪根聪 - !!!

正好最近用 uni-app 做 app 端(H5 的小伙伴们可以走了),大概 OP 的需求跟我差不多,说多了都是空话,上代码(代码不用全看完,提供思路最重要)

1.调用代码

                this.$showModal({  
                    success: () => {  
                        console.log('success');  
                    }  
                })
  1. 新建一个 nvue 的页面(我就是复制粘贴,有些 css 引用就不要了,你们就当伪代码看):
<template>  
    <view class="confirm-modal">  
        <view class="_confirm-modal" :style="{   
            padding: `${r32}px`,  
            borderRadius: `${r16}px`  
        }" @tap.stop>  
            <text class="_confirm-modal-title" :style="{  
                fontSize: `${r28}px`,  
                lineHeight: `${r32}px`  
            }">{{ title }}</text>  
            <text class="_confirm-modal-text" :style="{  
                fontSize: `${r26}px`,  
                lineHeight: `${r30}px`,  
                margin: `${r32}px 0 ${r48}px 0`  
            }">{{ text }}</text>  
            <view class="_confirm-modal-button">  
                <text class="_confirm-modal-ok" @click="handleConfirm()" :style="{  
                    width: `${r260}px`,  
                    height: `${r80}px`,  
                    lineHeight: `${r80}px`,  
                    fontSize: `${r26}px`,  
                    borderRadius: `${r40}px`  
                }">{{ confirmText }}</text>  
                <text class="_confirm-modal-cancel" @click="handleCancel()" :style="{  
                    width: `${r260}px`,  
                    height: `${r78}px`,  
                    lineHeight: `${r78}px`,  
                    fontSize: `${r26}px`,  
                    borderRadius: `${r40}px`,  
                    marginLeft: `${r16}px`,  
                    border: `${r1}px solid #999999`  
                }">{{ cancelText }}</text>  
            </view>  
        </view>  
    </view>  
</template>  

<script>  
    export default {  
        data() {  
            return {  
                title: '提示',  
                text: '提示内容',  
                confirmText: '确认',  
                cancelText: '取消',  
                r1: uni.upx2px(1),  
                r16: uni.upx2px(16),  
                r26: uni.upx2px(26),  
                r28: uni.upx2px(28),  
                r30: uni.upx2px(30),  
                r32: uni.upx2px(32),  
                r40: uni.upx2px(40),  
                r48: uni.upx2px(48),  
                r78: uni.upx2px(78),  
                r80: uni.upx2px(80),  
                r260: uni.upx2px(260),  
            }  
        },  
        beforeCreate() {  
            const domModule = uni.requireNativePlugin('dom')  
            domModule.addRule('fontFace', {  
                'fontFamily': "PingFang-SC-Medium",  
                'src': "url('/static/fonts/PingFang-SC-Medium.ttf')"  
            });  
        },  
        methods: {  
            handleConfirm() {  
                uni.$emit('handleModalConfirm')  
            },  
            handleCancel() {  
                uni.$emit('handleModalCancel')  
            }  
        }  
    }  
</script>  

<style lang="scss" scoped>  
    .confirm-modal {  
        display: flex;  
        align-items: center;  
        justify-content: center;  
        position: fixed;  
        top: 0;  
        left: 0;  
        right: 0;  
        bottom: 0;  
        background-color: rgba(0, 0, 0, 0.3);  

        ._confirm-modal {  
            background-color: $white;  

            ._confirm-modal-title {  
                color: $black;  
                text-align: center;  
                font-weight: 500;  
                font-family: $font-m;  
            }  

            ._confirm-modal-text {  
                color: #757575;  
                text-align: center;  
            }  

            ._confirm-modal-button {  
                display: flex;  
                flex-direction: row;  
                justify-content: center;  
                align-items: center;  

                ._confirm-modal-ok {  
                    text-align: center;  
                    display: flex;  
                    justify-content: center;  
                    align-items: center;  
                    color: $white;  
                    font-weight: 500;  
                    font-family: $font-m;  
                    background-color: $p-color;  
                }  

                ._confirm-modal-cancel {  
                    text-align: center;  
                    display: flex;  
                    justify-content: center;  
                    align-items: center;  
                    color: $p-color12;  
                    font-weight: 500;  
                    font-family: $font-m;  
                    background-color: $white;  
                }  
            }  
        }  
    }  
</style>

3.把这个弹窗的 nvue 页面注册到 pages.json,然后再把页面路径注册到 subNvues:

"subNVues": [{  
                "id": "bModal",  
                "path": "pages/modal/modal",  
                "type": "popup",  
                "style": {  
                    "background": "transparent"  
                }  
            }]

4.就是在 App.vue 里面注册 this.$showModal

<script>  
    import {  
        mapGetters  
    } from 'vuex'  

    let modalInstance = null  

    export default {  
        onLaunch: function() {  
            console.log('App Launch')  
            this.initModal()  
        },  
        onShow: function() {  
            console.log('App Show')  
        },  
        onHide: function() {  
            console.log('App Hide')  
        },  
        computed: {  
            ...mapGetters(['showModal'])  
        },  
        watch: {  
            showModal: {  
                handler(val) {  
                    if (!modalInstance) {  
                        modalInstance = uni.getSubNVueById('bModal')  
                    }  
                    if (val) {  
                        modalInstance.show()  
                    } else {  
                        modalInstance.hide()  
                    }  
                },  
                deep: true  
            }  
        },  
        methods: {  
            // 基础弹窗  
            initModal() {  
                let modalSuccess = null  
                uni.$on('handleModalConfirm', () => {  
                    if (modalSuccess) {  
                        modalSuccess()  
                    }  
                })  
                uni.$on('handleModalCancel', () => {  
                    this.$store.commit('SET_SHOW_MODAL', false)  
                })  
                Vue.prototype.$showModal = (({ success }) => {  
                    modalSuccess = success  
                    this.$store.commit('SET_SHOW_MODAL', true)  
                })  
            }  
        }  
    }  
</script>  

<style lang="scss">  
    /*每个页面公共css */  

    /* 禁用网页默认的橡皮筋效果 */  
    * {  
        overscroll-behavior: none;  
    }  

    /* 注意要写在第一行,同时给style标签加入lang="scss"属性 */  
    @import "@/uni_modules/uview-ui/index.scss";  
</style>

要回复问题请先登录注册