uni-app弹出层uni-popup使用以及修改默认样式

uni-popup官方文档

我这里的背景是弹出一个选择规格的菜单。使用vue3+ts,使用组合式api

首先看看在vue3+ts+setup下的使用:

<template>
    <!-- 定义一个按钮,用于打开弹出层 -->
    <view style="width: 200px">
        <button @click="openSpecs">弹出</button>
    </view>
    <!-- 弹出层视图,注意这里的ref="popup",这里背景特意标红了,方便看到效果 -->
    <uni-popup class="updatePopup" background-color="red" ref="popup" type="center"> 你好 </uni-popup>
</template>

<script setup lang="ts">
    import { ref } from "vue";

    // 这里的这个变量名,必须和上面的ref="popup"的变量名相同,这样就相当于绑定了这个元素了
    const popup = ref(null);

    // 按钮调用该方法打开弹出层
    function openSpecs() {
        popup.value.open();
    }
</script>

<style>
</style>

从这里可以看出来,弹出层的整体是透明的,而主界面是随着内部的元素大小自适应的。

现在在弹出层中编写复杂的效果

我新建了一个selectSpecs.vue:

<template>
    <view class="background">
        <!-- 标题 -->
        <view style="text-align: center">
            <text class="title">{{ title }}</text>
        </view>
        <!-- 区域滚动视图 -->
        <scroll-view scroll-y="true" :style="'height:' + scrollH + 'px'">
            <!-- 结合分组和数据选择器展示数据,不是本文的重点 -->
            <uni-group mode="card" top="0" v-for="item in specsList" :key="item.key" :title="item.text"  id="group">
                <uni-data-checkbox mode="tag" :v-model="item.value" :localdata="item.option"></uni-data-checkbox>
            </uni-group>
        </scroll-view>
    </view>
</template>
<script setup lang="ts">
    import { onMounted, ref } from "vue";

    // 下面都是一些生成数据的逻辑,可以不关心。
    let title = "标题测试";

    interface iOption {
        key: number;
        text: string;
        disable: boolean;
        value: number;
    }

    interface iSpecs {
        key: number;
        text: string;
        value: number;
        option: iOption[];
    }

    const specsList: iSpecs[] = new Array<iSpecs>(3);
    for (let i = 0; i < 10; i++) {
        const optionList: iOption[] = new Array<iOption>(i + 1);
        for (let j = 0; j < i + 1; j++) {
            optionList[j] = {
                key: j,
                text: "属性" + j,
                disable: false,
                value: j,
            };
        }
        specsList[i] = {
            key: i,
            text: "规格" + i,
            value: i,
            option: optionList,
        };
    }

    // 这里是为了确定滚动区域的高度,不给高度不滚动的,这里的效果或许还有点问题。
    const scrollH = ref(0);
    onMounted(() => {
        let group = uni.createSelectorQuery().select("#group"); //根据id获取一个规格组的高度
        // prettier-ignore
        group.boundingClientRect((data) => {
            //计算高度:高度控制在3个规格组的高度以内,即3个组以内不需要滚动,+10是因为实测获取的高度比真实高度少一点,不加的话就会需要小范围的滚动一下
            if (specsList.length<3){
                scrollH.value=(data.height+10)* specsList.length
            }else{
                scrollH.value=(data.height+10)*3
            }
            }).exec();
    });
</script>
<style>
    .background {
        background-color: white;
        border-radius: 10px;
    }
    .title {
        font-size: x-large;
        font-family: "Times New Roman", Times, Cursive;
        text-align: center;
    }
</style>

这里内容看似很长,其实都是为了展示效果,可以不看细节。可以看看我对滚动区域的高度的设置方法。

引入的方式是将上面“你好”改为如下:

<uni-popup background-color="red" ref="popup" type="center">
     <SelectSpecs></SelectSpecs>
</uni-popup>

当然组件也是要import的:

<script setup lang="ts">
    import { ref } from "vue";
    import SelectSpecs from "../goods/view/selectSpecs.vue"; //导入组件
	.......
</script>

当我数据小的时候,他的效果是这样的:
uni-app弹出层uni-popup使用以及修改默认样式_第1张图片
那个四个红角就是背景的颜色。这个效果还可以

当我数据多了之后:
uni-app弹出层uni-popup使用以及修改默认样式_第2张图片
因为宽度自适应,所以宽度是占满了整个屏幕的宽度。你看属性9都换行了。而我希望我的弹出层上下左右都留出一点空间,这样才好看。

我首先想到的是,给这个宽度限制一个最大百分比,用max-width: 80%;,加在background 样式的里面,因为这是整个背景的视图嘛,结果效果是这样的:
uni-app弹出层uni-popup使用以及修改默认样式_第3张图片
红色背景依然是整个屏幕的宽度,但内容跑左边去了,这不是我想要的效果。再看看数据量小的效果:
uni-app弹出层uni-popup使用以及修改默认样式_第4张图片
这看起来是白色框框占红色背景的80%呀,并不是内容占屏幕的80%呀。还不会居中了。

看来是我的样式加的位置不对,但是uni-popup也没提供这个参数。在uni-popup嵌套一层 view来控制样式:

<template>
    <!-- 定义一个按钮,用于打开弹出层 -->
    <view style="width: 200px">
        <button @click="openSpecs">弹出</button>
    </view>
    <!-- 弹出层视图,注意这里的ref="popup",这里背景特意标红了,方便看到效果 -->
    <view style="max-width: 80%">
        <uni-popup background-color="red" ref="popup" type="center">
            <SelectSpecs></SelectSpecs>
        </uni-popup>
    </view>
</template>

这样也没效果。

于是debug发现,真正控制弹出层主窗体大小的样式是“.uni-popup__wrapper”,难道我要去修改源代码吗?这样不太好,不利于代码移植。

于是就想着有没有办法从子组件修改父组件的样式的方法,结果没找到,倒是找到了父组件修改子组件的样式的方法,于是代码稍微修改一下:

    <uni-popup class="updatePopup" background-color="red" ref="popup" type="center">
        <SelectSpecs></SelectSpecs>
    </uni-popup>

增加了一个样式:

<style scoped>
    .updatePopup :deep(.uni-popup__wrapper) {
        max-width: 80%;
    }
</style>

这里注意.vue文件允许有多组