提交 e8674538 编写于 作者: M mehaotian

feat: 新增折叠面板效果

上级 ff31beac
......@@ -124,7 +124,9 @@
.uni-navigate-item:active {
background-color: #f8f8f8;
}
.is--active {
background-color: #f8f8f8;
}
.uni-navigate-text {
color: #000000;
font-size: 14px;
......
<template>
<view class="uni-collapse-item">
<view class="uni-collapse-item__title" :class="{'open--active':is_open}" @click="openCollapse(!this.is_open)">
<text class="uni-collapse-item__title-text" :class="{'is-disabled':disabled}">{{title}}</text>
<view class="down_arrow" :class="{'down_arrow--active': is_open}"></view>
</view>
<view ref="boxRef" class="uni-collapse-item__content">
<view ref="contentRef" class="uni-collapse-item__content-box">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
import { $dispatch } from './util.uts'
export default {
name: "UniCollapseItem",
props: {
// 列表标题
title: {
type: String,
default: ''
},
open: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
}
},
data() {
return {
height: 0,
is_open: this.open as boolean,
boxNode: null as INode | null,
contentNode: null as INode | null,
};
},
watch: {
open(value: boolean) {
// this.is_open = value
if (this.boxNode != null) {
this.openCollapse(value)
}
}
},
created() {
$dispatch(this, 'UniCollapse', 'init', this)
},
mounted() {
this.boxNode = this.$refs['boxRef'] as INode;
this.contentNode = this.$refs['contentRef'] as INode;
// this.openCollapse(this.open)
},
methods: {
// 开启或关闭折叠面板
openCollapse(open: boolean) {
if (this.disabled) return
// 关闭其他已打开
$dispatch(this, 'UniCollapse', 'cloceAll')
this.is_open = open
this.oepnOrClose(open)
},
oepnOrClose(open: boolean) {
const boxNode = this.boxNode?.style!;
const contentNode = this.contentNode?.style!;
let hide = open ? 'flex' : 'none';
let ani_transform = open ? 'translateY(0)' : 'translateY(-100%)';
boxNode.setProperty('display', hide);
this.$nextTick(() => {
contentNode.setProperty('transform', ani_transform);
})
}
}
}
</script>
<style scoped>
.uni-collapse-item {
background-color: #fff;
}
.uni-collapse-item__title {
flex-direction: row;
align-items: center;
line-height: 22px;
padding: 12px;
background-color: #fff;
}
.open--active {
background-color: #f0f0f0;
}
.down_arrow {
width: 8px;
height: 8px;
transform: rotate(45deg);
border-right: 1px #999 solid;
border-bottom: 1px #999 solid;
margin-top: -3px;
transition-property: transform;
transition-duration: 0.2s;
}
.down_arrow--active {
transform: rotate(-135deg);
margin-top: 0px;
}
.uni-collapse-item__title-text {
flex: 1;
color: #000;
font-size: 14px;
font-weight: 400;
}
.is-disabled {
color: #999;
}
.uni-collapse-item__content {
display: none;
position: relative;
}
.uni-collapse-item__content-box {
width: 100%;
transition-property: transform;
transition-duration: 0.3s;
transform: translateY(-100%);
}
</style>
\ No newline at end of file
// import { ComponentPublicInstance } from 'vue'
// 查找父组件实例
export function $dispatch(
context : ComponentPublicInstance,
componentName : string,
eventName : string,
...params : any | null
) {
let parent = context.$parent
let name = parent?.$options?.name
while (parent != null && (name == null || componentName != name)) {
parent = parent.$parent
if (parent != null) {
name = parent?.$options?.name
}
}
if (parent != null) {
parent.$callMethod(eventName, ...params)
}
}
\ No newline at end of file
<template>
<!-- 父组件暂时无用,后续子组件联动需要使用到父组件 -->
<view>
<slot></slot>
</view>
</template>
<script>
// import { ComponentPublicInstance } from 'vue'
export default {
name: "UniCollapse",
props: {
// 是否开启手风琴效果
accordion: {
type: Boolean,
default: true
}
},
data() {
return {
child_nodes: [] as Array < ComponentPublicInstance >
};
},
methods: {
init(child: ComponentPublicInstance) {
this.child_nodes.push(child)
},
// 关闭所有
cloceAll() {
// 开启手风琴效果才回关闭其他
if (this.accordion && this.child_nodes.length > 0) {
this.child_nodes.forEach((item) => {
const is_open = item.$data.get('is_open') as boolean
// TODO 暂时无法获取子组件上的属性和方法,暂时使用绕过方案
if (is_open) {
item.$data.set('is_open', false)
item.$callMethod('oepnOrClose', false)
}
})
}
}
}
}
</script>
<style>
</style>
\ No newline at end of file
......@@ -8,50 +8,38 @@
</view>
<view class="uni-hello-text">
<text class="hello-text">以下将演示uni-app接口能力,详细文档见:</text>
<u-link
:href="'https://uniapp.dcloud.io/api/'"
:text="'https://uniapp.dcloud.io/api/'"
:inWhiteList="true"
></u-link>
<u-link :href="'https://uniapp.dcloud.io/api/'" :text="'https://uniapp.dcloud.io/api/'" :inWhiteList="true"></u-link>
</view>
<view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view
class="uni-panel-h"
:class="item.open ? 'uni-panel-h-on' : ''"
@click="triggerCollapse(index, item)"
>
<text
class="uni-panel-text"
:class="item.enable == false ? 'text-disabled' : ''"
>{{ item.name }}</text
>
<image
:src="
item.pages.length > 0
<uni-collapse>
<template v-for="item in list" :key="item.id">
<uni-collapse-item :title="item.name" class="item">
<view class="uni-navigate-item" :hover-class="page.enable == false?'':'is--active'" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</uni-collapse-item>
</template>
</uni-collapse>
<!-- <view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view class="uni-panel-h" :class="item.open ? 'uni-panel-h-on' : ''" @click="triggerCollapse(index, item)">
<text class="uni-panel-text" :class="item.enable == false ? 'text-disabled' : ''">{{ item.name }}</text>
<image :src="
item.pages.length >
? item.open
? arrowUpIcon
: arrowDownIcon
: arrowRightIcon
"
class="uni-icon"
></image>
" class="uni-icon"></image>
</view>
<view class="uni-panel-c" v-if="item.open">
<view
class="uni-navigate-item"
v-for="(page, key) in item.pages"
:key="key"
@click="goDetailPage(page)"
>
<text
class="uni-navigate-text"
:class="page.enable == false ? 'text-disabled' : ''"
>{{ page.name }}</text
>
<view class="uni-navigate-item" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</view>
</view>
</view> -->
</view>
<!-- #ifdef APP -->
</scroll-view>
......@@ -59,20 +47,20 @@
</template>
<script lang="ts">
type Page = {
name: string
enable?: boolean
url: string
}
type ListItem = {
id: string
name: string
open: boolean
pages: Page[]
url?: string
enable?: boolean
}
export default {
type Page = {
name : string
enable ?: boolean
url : string
}
type ListItem = {
id : string
name : string
open : boolean
pages : Page[]
url ?: string
enable ?: boolean
}
export default {
data() {
return {
list: [
......@@ -130,7 +118,7 @@ export default {
{
name: '下拉刷新',
url: 'pull-down-refresh',
// enable: false,
enable: false,
},
{
name: '将页面滚动到指定位置',
......@@ -481,9 +469,9 @@ export default {
}
},
methods: {
triggerCollapse(index?: number, item: ListItem) {
triggerCollapse(index ?: number, item : ListItem) {
if (item.pages.length == 0) {
const page: Page = {
const page : Page = {
name: item.name,
enable: item.enable,
url: item.url!,
......@@ -499,7 +487,7 @@ export default {
}
}
},
goDetailPage(e: Page) {
goDetailPage(e : Page) {
if (e.enable == false) {
uni.showToast({
title: '暂不支持',
......@@ -514,9 +502,14 @@ export default {
})
},
},
}
}
</script>
<style>
@import '../../common/uni-uvue.css';
@import '../../common/uni-uvue.css';
.item {
margin-bottom: 12px;
}
</style>
\ No newline at end of file
......@@ -7,53 +7,37 @@
<image class="uni-header-image" src="/static/cssIndex.png"></image>
</view>
<view class="uni-hello-text">
<text class="hello-text"
>uni-app x目前已支持的CSS属性,展示样式仅供参考,文档详见:</text
>
<u-link
:href="'https://uniapp.dcloud.io/component/'"
:text="'https://uniapp.dcloud.io/component/'"
:inWhiteList="true"
></u-link>
<text class="hello-text">uni-app x目前已支持的CSS属性,展示样式仅供参考,文档详见:</text>
<u-link :href="'https://uniapp.dcloud.io/component/'" :text="'https://uniapp.dcloud.io/component/'" :inWhiteList="true"></u-link>
</view>
<view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view
class="uni-panel-h"
:class="item.open ? 'uni-panel-h-on' : ''"
@click="triggerCollapse(index, item)"
>
<text
class="uni-panel-text"
:class="item.enable == false ? 'text-disabled' : ''"
>{{ item.name }}</text
>
<image
:src="
<uni-collapse>
<template v-for="item in list" :key="item.id">
<uni-collapse-item :title="item.name" class="item">
<view class="uni-navigate-item":hover-class="page.enable == false?'':'is--active'" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</uni-collapse-item>
</template>
</uni-collapse>
<!-- <view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view class="uni-panel-h" :class="item.open ? 'uni-panel-h-on' : ''" @click="triggerCollapse(index, item)">
<text class="uni-panel-text" :class="item.enable == false ? 'text-disabled' : ''">{{ item.name }}</text>
<image :src="
item.pages.length > 0
? item.open
? arrowUpIcon
: arrowDownIcon
: arrowRightIcon
"
class="uni-icon"
></image>
" class="uni-icon"></image>
</view>
<view class="uni-panel-c" v-if="item.open">
<view
class="uni-navigate-item"
v-for="(page, key) in item.pages"
:key="key"
@click="goDetailPage(page)"
>
<text
class="uni-navigate-text"
:class="page.enable == false ? 'text-disabled' : ''"
>{{ page.name }}</text
>
<view class="uni-navigate-item" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</view>
</view>
</view> -->
</view>
<!-- #ifdef APP -->
</scroll-view>
......@@ -61,20 +45,20 @@
</template>
<script lang="ts">
type Page = {
name: string
enable?: boolean
url?: string
}
type ListItem = {
id: string
name: string
open: boolean
pages: Page[]
url?: string
enable?: boolean
}
export default {
type Page = {
name : string
enable ?: boolean
url ?: string
}
type ListItem = {
id : string
name : string
open : boolean
pages : Page[]
url ?: string
enable ?: boolean
}
export default {
data() {
return {
list: [
......@@ -336,9 +320,9 @@ export default {
}
},
methods: {
triggerCollapse(index?: number, item: ListItem) {
triggerCollapse(index ?: number, item : ListItem) {
if (item.pages.length == 0) {
const page: Page = {
const page : Page = {
name: item.name,
enable: item.enable,
url: item.url,
......@@ -354,7 +338,7 @@ export default {
}
}
},
goDetailPage(e: Page) {
goDetailPage(e : Page) {
if (e.enable == false) {
uni.showToast({
icon: 'none',
......@@ -368,9 +352,12 @@ export default {
})
},
},
}
}
</script>
<style>
@import '../../common/uni-uvue.css';
@import '../../common/uni-uvue.css';
.item {
margin-bottom: 12px;
}
</style>
\ No newline at end of file
......@@ -4,59 +4,40 @@
<!-- #endif -->
<view class="uni-container">
<view class="uni-header-logo">
<image
class="uni-header-image"
src="/static/componentIndex.png"
></image>
<image class="uni-header-image" src="/static/componentIndex.png"></image>
</view>
<view class="uni-hello-text">
<text class="hello-text"
>uni-app内置组件,展示样式仅供参考,文档详见:</text
>
<u-link
:href="'https://uniapp.dcloud.io/component/'"
:text="'https://uniapp.dcloud.io/component/'"
:inWhiteList="true"
></u-link>
<text class="hello-text">uni-app内置组件,展示样式仅供参考,文档详见:</text>
<u-link :href="'https://uniapp.dcloud.io/component/'" :text="'https://uniapp.dcloud.io/component/'" :inWhiteList="true"></u-link>
</view>
<view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view
class="uni-panel-h"
:class="item.open ? 'uni-panel-h-on' : ''"
@click="triggerCollapse(index, item)"
>
<text
class="uni-panel-text"
:class="item.enable == false ? 'text-disabled' : ''"
>{{ item.name }}</text
>
<image
:src="
<uni-collapse>
<template v-for="item in list" :key="item.id">
<uni-collapse-item :title="item.name" class="item">
<view class="uni-navigate-item" :hover-class="page.enable == false?'':'is--active'" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</uni-collapse-item>
</template>
</uni-collapse>
<!-- <view class="uni-panel" v-for="(item, index) in list" :key="item.id">
<view class="uni-panel-h" :class="item.open ? 'uni-panel-h-on' : ''" @click="triggerCollapse(index, item)">
<text class="uni-panel-text" :class="item.enable == false ? 'text-disabled' : ''">{{ item.name }}</text>
<image :src="
item.pages.length > 0
? item.open
? arrowUpIcon
: arrowDownIcon
: arrowRightIcon
"
class="uni-icon"
></image>
" class="uni-icon"></image>
</view>
<view class="uni-panel-c" v-if="item.open">
<view
class="uni-navigate-item"
v-for="(page, key) in item.pages"
:key="key"
@click="goDetailPage(page)"
>
<text
class="uni-navigate-text"
:class="page.enable == false ? 'text-disabled' : ''"
>{{ page.name }}</text
>
<view class="uni-navigate-item" v-for="(page, key) in item.pages" :key="key" @click="goDetailPage(page)">
<text class="uni-navigate-text" :class="page.enable == false ? 'text-disabled' : ''">{{ page.name }}</text>
<image :src="arrowRightIcon" class="uni-icon"></image>
</view>
</view>
</view>
</view> -->
</view>
<!-- #ifdef APP -->
</scroll-view>
......@@ -64,20 +45,20 @@
</template>
<script lang="ts">
type Page = {
name: string
enable?: boolean
url?: string
}
type ListItem = {
id: string
name: string
open: boolean
pages: Page[]
url?: string
enable?: boolean
}
export default {
type Page = {
name : string
enable ?: boolean
url ?: string
}
type ListItem = {
id : string
name : string
open : boolean
pages : Page[]
url ?: string
enable ?: boolean
}
export default {
data() {
return {
list: [
......@@ -263,6 +244,23 @@ export default {
pages: [] as Page[]
}
*/
{
id: 'general-attr-event',
name: '通用属性和事件',
open: false,
pages: [
{
name: '通用属性',
url: 'general-attr',
enable: false,
},
{
name: '通用事件',
url: '/pages/component/general-event/general-event',
enable: true,
},
] as Page[],
},
] as ListItem[],
arrowUpIcon: '/static/icons/arrow-up.png',
arrowDownIcon: '/static/icons/arrow-down.png',
......@@ -270,9 +268,9 @@ export default {
}
},
methods: {
triggerCollapse(index?: number, item: ListItem) {
triggerCollapse(index ?: number, item : ListItem) {
if (item.pages.length == 0) {
const page: Page = {
const page : Page = {
name: item.name,
enable: item.enable,
url: item.url,
......@@ -288,7 +286,7 @@ export default {
}
}
},
goDetailPage(e: Page) {
goDetailPage(e : Page) {
if (e.enable == false) {
uni.showToast({
title: '暂不支持',
......@@ -303,9 +301,14 @@ export default {
})
},
},
}
}
</script>
<style>
@import '../../common/uni-uvue.css';
@import '../../common/uni-uvue.css';
.item {
margin-bottom: 12px;
}
</style>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册