提交 e091902c 编写于 作者: Y yewenwen

feat: menu

上级 33082612
......@@ -180,6 +180,15 @@ export const nav = [
show: true,
desc: '头像',
author: 'ailululu'
},
{
name: 'Menu',
sort: 8,
cName: '菜单',
type: 'component',
show: true,
desc: '菜单',
author: 'vickyYE'
}
]
},
......
<template>
<div class="demo">
<h2>基础用法</h2>
<nut-menu>
<nut-menu-item
:menuList="menuList"
:title="title1"
@on-checked="getChecked"
></nut-menu-item>
<nut-menu-item
:menuList="menuList2"
title="最新商品"
multiLine="2"
></nut-menu-item>
<nut-menu-item
:menuList="menuList2"
title="筛选"
disabled
></nut-menu-item>
</nut-menu>
</div>
</template>
<script lang="ts">
import { ref, reactive, toRefs } from 'vue';
import { createComponent } from '@/utils/create';
const { createDemo } = createComponent('menu');
export default createDemo({
props: {},
setup() {
const title1 = ref('标题1');
const resData = reactive({
menuList: [
{
value: '标签一'
},
{
value: '标签二标签二标签二标签二'
},
{
value: '标签三'
}
],
menuList2: [
{
value: '标签1'
},
{
value: '标签2'
},
{
value: '标签3'
}
]
});
const getChecked = (info: any) => {
console.log(11, info.value);
};
// function changeList() {
// resData.editList.push({
// title: '标签' + resData.editList.length
// });
// }
// function switchTab(activeInddex: number, event: MouseEvent) {
// console.log(activeInddex, event);
// }
return {
...toRefs(resData),
title1
// changeList,
// switchTab
};
}
});
</script>
<style lang="scss" scoped>
.nut-menu {
}
</style>
# Menu 菜单组件
### 介绍
基于 xxxxxxx
### 安装
``` javascript
import { createApp } from 'vue';
import { Menu } from '@nutui/nutui';
const app = createApp();
app.use(Menu);
```
## 代码演示
### 基础用法1
`Menu` 属性支持传入menu列表数据和title名称。
```html
<nut-menu>
<nut-menu-item :menuList="menuList" :title="title1"></nut-menu-item>
<nut-menu-item :menuList="menuList2" :title="title1"></nut-menu-item>
</nut-menu>
```
### 基础用法2
`Icon``name` 属性支持传入图标名称或图片链接。
```html
<nut-temp name="wifi"></nut-temp>
<nut-temp name="mail"></nut-temp>
```
### 基础用法3
`Icon``name` 属性支持传入图标名称或图片链接。
```html
<nut-temp name="wifi"></nut-temp>
<nut-temp name="mail"></nut-temp>
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| name | 图标名称或图片链接 | String | - |
| color | 图标颜色 | String | - |
| size | 图标大小,如 `20px` `2em` `2rem` | String | - |
| class-prefix | 类名前缀,用于使用自定义图标 | String | `nutui-iconfont` |
| tag | HTML 标签 | String | `i` |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|----------------|--------------|
| click | 点击图标时触发 | event: Event |
.nut-menu {
background: #fff;
display: flex;
align-items: center;
position: relative;
height: 46px;
}
<template>
<view class="nut-menu">
<slot></slot>
</view>
</template>
<script lang="ts">
import { toRefs } from 'vue';
import { createComponent } from '@/utils/create';
import { useChildren } from '@/utils/useRelation/useChildren';
export const MENU_KEY = 'nutMenu';
const { componentName, create } = createComponent('menu');
export default create({
props: {
disabled: {
//是否显示
type: Boolean,
default: false
},
type: {
//单选 simple 多选 multiple
type: String,
default: 'simple'
}
},
components: {},
emits: ['click'],
setup(props, { emit }) {
console.log('componentName', componentName);
// const { name, txt } = toRefs(props);
const handleClick = (event: Event) => {
emit('click', event);
};
// return { name, txt, handleClick };
}
});
</script>
<style lang="scss">
@import 'index.scss';
</style>
.nut-menu-item {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0 5px;
&.disabled {
color: #999;
}
&.nut-menu-active {
.nut-menu-title {
font-weight: bold;
.icon {
background: url('https://img10.360buyimg.com/imagetools/jfs/t1/156044/7/582/372/5fd990b5Ea62c2694/551e7f58d421a9ae.png')
no-repeat;
transition: all ease 0.3s;
transform: rotate(-360deg);
background-size: contain;
}
}
.nut-menu-panel {
display: block;
}
}
}
.nut-menu-title {
font-size: 14px;
display: flex;
align-items: center;
.title-name {
white-space: nowrap;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
display: inline-block;
width: 6px;
height: 6px;
background: url('https://img13.360buyimg.com/imagetools/jfs/t1/152898/12/10149/452/5fd990b5Ec7c12d70/3bf06076b758bed1.png')
no-repeat;
background-size: contain;
transform: rotate(0deg);
transition: all ease 0.3s;
margin: 0 2px;
}
}
.nut-menu-panel {
display: none;
width: 100%;
position: absolute;
left: 0;
top: 46px;
color: #2d2d2d;
overflow: hidden;
background-color: #fff;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
z-index: 9998;
border-top: 1px solid #f7f8fa;
border-radius: 0 0 15px 15px;
box-shadow: 0 4px 5px 0px rgba(236, 236, 236, 0.25);
// &.active{
// display: block;
// }
}
.menu-list {
display: flex;
padding: 10px 24px;
flex-direction: column;
&.bubble-line {
flex-flow: wrap;
.menu-option {
width: 50%;
}
}
&.three-line {
flex-flow: wrap;
.menu-option {
width: 32%;
}
}
.menu-option {
min-height: 24px;
line-height: 48px;
font-size: 14px;
color: #1a1a1a;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.check-icon {
width: 14px;
height: 14px;
margin-right: 5px;
color: #fa2c19;
}
}
<template>
<view
class="nut-menu-item"
:class="[{ disabled: disabled }, { 'nut-menu-active': showPanel }]"
>
<view class="nut-menu-title" @click="handleMenuPanel">
<view class="title-name" v-html="menuTitle"></view>
<i class="icon" name="arrow-down"></i>
</view>
<view class="nut-menu-panel" ref="menuPanel">
<view
class="menu-list"
:class="[
{ 'bubble-line': multiLine == 2 },
{ 'three-line': multiLine == 3 }
]"
>
<view
class="menu-option"
v-for="(item, index) in menuList"
:key="index"
@click="checkMenus(item, index)"
><nut-icon
class="check-icon"
v-if="currMenu == index"
name="dongdong"
size="14px"
></nut-icon
>{{ item.value }}</view
>
</view>
</view>
</view>
</template>
<script lang="ts">
import {
reactive,
toRefs,
onMounted,
ref,
nextTick,
computed,
watch,
onUnmounted
} from 'vue';
import { createComponent } from '@/utils/create';
import { useParent } from '@/utils/useRelation/useParent';
import { MENU_KEY } from './../menu/index.vue';
import Icon from '@/packages/icon/index.vue';
const { create } = createComponent('menu-item');
export default create({
props: {
title: {
type: String,
default: ''
},
value: {
type: [String, Number],
default: ''
},
disabled: {
type: Boolean,
default: false
},
menuList: {
type: Array,
default: () => {
return [];
}
},
isVisible: {
//是否显示
type: Boolean,
default: false
},
multiLine: {
type: [String, Number],
default: 1 //可选值1、2、3
}
},
emits: ['on-checked'],
setup(props, { emit }) {
const { menuList, multiLine } = toRefs(props);
const menuTitle = ref(props.title);
const menu = useParent(MENU_KEY);
const parent: any = reactive(menu.parent as any);
const index: any = reactive(menu.index as any);
const state = reactive({
showPanel: false,
currMenu: 0
// menuTitle:''
});
const handleMenuPanel = () => {
//禁用
if (props.disabled) return;
state.showPanel = !state.showPanel;
};
//menu列表浮层展示和隐藏
const handleShowAndHide = (event: any) => {
const menuBox = document.querySelectorAll('.nut-menu-active')[0];
if (menuBox && state.showPanel) {
if (!menuBox.contains(event.target)) {
state.showPanel = false;
}
}
};
const checkMenus = (item: any, index: number) => {
console.log(item);
menuTitle.value = item.value;
state.currMenu = index;
emit('on-checked', menuTitle.value);
};
onMounted(() => {
document.addEventListener(
'mouseup',
(event: any) => {
handleShowAndHide(event);
},
false
);
});
onUnmounted(() => {
document.removeEventListener('mouseup', (event: any) => {
handleShowAndHide(event);
}),
false;
});
return {
...toRefs(state),
...toRefs(parent),
handleMenuPanel,
checkMenus,
menuTitle,
multiLine
};
}
});
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册