<template>
<!-- 列表1 -->
<view class="list">
<view class="item" v-for="(item, index) in containerShow" @click="touch(item)">
显-{{ item.id }}
</view>
</view>
<!-- 列表2 -->
<view class="list">
<view class="item" v-for="(item, index) in containerHide" @click="touch(item)">
隐-{{ item.id }}
</view>
</view>
<!-- 底部控制器 -->
<view class="content">
<button @click="reSet" v-show="isShow">还原(正常的)</button>
<!-- 依赖 computed 计算状态-->
<uni-transition mode-class="fade" :show="isShow">
<view class="btn-container">
<view class="btn-item">
<button @click="reSet">还原(transition 异常computed)</button>
</view>
</view>
</uni-transition>
<!-- 依赖 ref 控制状态-->
<uni-transition mode-class="slide-bottom" :show="showRef">
<view class="btn-container">
<view class="btn-item">
<button @click="reSet">还原(transition 异常showRef)</button>
</view>
</view>
</uni-transition>
</view>
</template>
<script setup>
import { ref, reactive, computed, watch, toRaw } from "vue";
/** 原始数据列 */
const list = reactive(
Array(5)
.fill({})
.map((item, index) => ({
id: index * 2,
flage: true
}))
);
/** 操作记录栈 */
const stack = reactive([]);
/** 状态标记:当操作记录栈不为空时true */
const isShow = computed(() => {
let state = stack.length > 0;
console.log("计算状态", state);
return state;
});
/** 点击切换状态 并存入记录 */
const touch = ({ id }) => {
let index = list.findIndex((v) => v.id == id);
// 获取源数据 存入记录栈
let history = JSON.parse(JSON.stringify(toRaw(list[index])));
stack.push(history);
// 切换状态
list[index].flage = !list[index].flage;
};
/** 计算显示的列表 */
const containerShow = computed(() => {
return list.filter((v) => v.flage);
});
/** 计算隐藏的列表 */
const containerHide = computed(() => {
return list.filter((v) => !v.flage);
});
/** 还原初始状态 */
const reSet = () => {
list.forEach((v) => {
v.flage = true;
});
stack.splice(0, stack.length);
};
const showRef = ref(false);
/** 监控操作栈 */
watch(stack, (newVal) => {
let state = newVal.length > 0;
console.log("当前操作记录栈", toRaw(newVal), `长度是否>0:${state}`);
showRef.value = state;
});
</script>
<style lang="scss" scoped>
.list {
width: 80%;
margin: 30rpx auto;
padding: 20rpx;
border: 2rpx solid #dadada;
border-radius: 20rpx;
background-color: #efefef;
display: flex;
justify-content: space-around;
.item {
padding: 30rpx;
background: #fff;
}
}
.content {
position: fixed;
bottom: 0;
width: 100vw;
z-index: 10;
.btn-container {
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
background-color: #d6d6d6b0;
display: flex;
align-self: center;
justify-content: space-around;
}
}
</style>
- 发布:2023-12-04 19:22
- 更新:2023-12-05 11:16
- 阅读:385
产品分类: uniapp/H5
PC开发环境操作系统: Windows
PC开发环境操作系统版本号: win10
HBuilderX类型: 正式
HBuilderX版本号: 3.98
浏览器平台: Chrome
浏览器版本: 119.0.6045.200
项目创建方式: HBuilderX
示例代码:
操作步骤:
正常在H5浏览器运行(Edge、Chrome均可),点击上方容器按钮
正常在H5浏览器运行(Edge、Chrome均可),点击上方容器按钮
预期结果:
show传参正确控制底部uni-transition显示、隐藏
show传参正确控制底部uni-transition显示、隐藏
实际结果:
H5中 show=true时 uni-transition 仅显示一次 后续show为true时则关闭,微信小程序中正常
H5中 show=true时 uni-transition 仅显示一次 后续show为true时则关闭,微信小程序中正常
爱豆豆 - 办法总比困难多
看了下组件源码 按照官方的书写逻辑 其实H5是正常的 组件的opacity属性在初始化后就固定修改为了0 所以H5端组件show属性发生改变后 组件样式中的opacity就生效为0 然后消失的
小程序没有消失时因为uni-transition组件样式中有个默认的opacity: 1;(在调试器中可以看到) 所以才没有消失
// uni-transition源码
// 传false 时 opacity 为 0
let { opacity, transform } = this.styleInit(false)
如果你想实现图中小程序的效果 不要使用计算属性修改组件show属性的值 可以在show发生改变时在修改他的值
你可以试试下面的代码
<template>
<!-- 列表1 -->
<view class="list">
<view class="item" v-for="(item, index) in containerShow" @click="touch(item)">
显-{{ item.id }}
</view>
</view>
<!-- 列表2 -->
<view class="list">
<view class="item" v-for="(item, index) in containerHide" @click="touch(item)">
隐-{{ item.id }}
</view>
</view>
<!-- 底部控制器 -->
<view class="content">
<button @click="reSet" v-show="isShow">还原(正常的)</button>
<!-- 依赖 computed 计算状态-->
<uni-transition mode-class="fade" :show="isShow">
<view class="btn-container">
<view class="btn-item">
<button @click="reSet">还原(transition 异常computed)</button>
</view>
</view>
</uni-transition>
<!-- 依赖 ref 控制状态-->
<uni-transition mode-class="fade" :show="showRef">
<view class="btn-container">
<view class="btn-item">
<button @click="reSet">还原(transition 异常showRef)</button>
</view>
</view>
</uni-transition>
</view>
</template>
<script setup>
import { ref, reactive, computed, watch, toRaw } from "vue";
/** 原始数据列 */
const list = reactive(
Array(5)
.fill({})
.map((item, index) => ({
id: index * 2,
flage: true
}))
);
/** 操作记录栈 */
const stack = reactive([]);
const isShow = ref(false)
// 检测显示状态
const isComputed = () => {
let state = stack.length >=1;
if(isShow.value !== state) {
isShow.value = state;
showRef.value = state;
}
}
/** 点击切换状态 并存入记录 */
const touch = ({ id }) => {
let index = list.findIndex((v) => v.id == id);
// 获取源数据 存入记录栈
let history = JSON.parse(JSON.stringify(toRaw(list[index])));
stack.push(history);
// 切换状态
list[index].flage = !list[index].flage;
// 检测显示状态
isComputed()
};
/** 计算显示的列表 */
const containerShow = computed(() => {
return list.filter((v) => v.flage);
});
/** 计算隐藏的列表 */
const containerHide = computed(() => {
return list.filter((v) => !v.flage);
});
/** 还原初始状态 */
const reSet = () => {
list.forEach((v) => {
v.flage = true;
});
stack.splice(0, stack.length);
// 检测显示状态
isComputed()
};
const showRef = ref(false);
</script>
<style lang="scss" scoped>
.list {
width: 80%;
margin: 30rpx auto;
padding: 20rpx;
border: 2rpx solid #dadada;
border-radius: 20rpx;
background-color: #efefef;
display: flex;
justify-content: space-around;
.item {
padding: 30rpx;
background: #fff;
}
}
.content {
position: fixed;
bottom: 0;
width: 100vw;
z-index: 10;
.btn-container {
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
background-color: #d6d6d6b0;
display: flex;
align-self: center;
justify-content: space-around;
}
}
</style>
DefterYu (作者)
哦 原来还可以这样
2023-12-05 18:46