react右键菜单 mock数据

在上一篇文章中我们创建了项目。现在我们在这个项目中完成右键的菜单实现
umi脚手架搭建项目

在项目创建好之后 运行 会自动打开welcome 界面,以及是基于antd的界面了。


这是我配置路由之后的图片

sumi项目中 src/pages 下的内容会自动生成路由。 (有很多是这么说的)

但是实际上你创建页面之后在项目 修改地址是会报 404 错误的
要想修改路由需要在 config / config.js 文件中修改哦


我在pages下面创建的目录

我修改了路由中welcome 改成了home 修改了component 的路径 此时 默认路由就是 Home 中的内容了

 routes: [
    {
      path: '/',
      component: '../layouts/BasicLayout',
      Routes: ['src/pages/Authorized'],
      authority: ['admin', 'user'],
      routes: [
        {
          path: '/',
          name: 'home',
          icon: 'smile',
          component: './Home/home',
        },
        {
          component: './404',
        }
        
      ],

需求是从后台读取列表数据,所以我们需要先用mock 模拟

services/apis.js

import request from '@/utils/request';
export async function getList() {
  return request('/api/rightlist');
}

mock/rightlist.js

const getList = (req,res) => {
    res.json([
        {
          id: '1',
          icon: 'copy',
          title: '添加到自定义',
        },
        {
          id: '2',
          icon: 'scissor',
          title: '剪切',
        },
        {
          id: '3',
          icon: 'snippets',
          title: '粘贴',
        },
        {
          id: '4',
          icon: 'delete',
          title: '删除',
        },
        {
          id: '5',
          icon: 'lock',
          title: '锁定',
        },
        {
          id: '6',
          icon: 'layout',
          title: '组合',
          children: [
              {
                id: '61',
                icon: 'build',
                title: '创建'
              },
              {
                id: '62',
                icon: 'appstore',
                title: '卡片'
              },
              {
                id: '63',
                icon: 'database',
                title: '列表'
              },
          ]
        },
        {
          id: '7',
          icon: 'vertical-align-top',
          title: '顺序',
          children: [
              {
                id: '71',
                icon: 'arrow-down',
                title: '后移'
              },
              {
                id: '72',
                icon: 'arrow-up',
                title: '前移'
              },
              {
                id: '73',
                icon: 'vertical-align-bottom',
                title: '置底'
              },
              {
                id: '74',
                icon: 'vertical-align-top',
                title: '置顶'
              }
          ]
        },

    ])
}

export default {
    'GET /api/rightlist': getList,
};

在models 中应该有请求以及操作

models/rightlist.js

import { getList } from '@/services/api'

export default {
    namespace: 'rightlist',
    state: {
        list: []
    },

    effects: {
        *fetchList({ callback }, { call, put }) {
          const response = yield call(getList);
          if (!response.error) {
            yield put({
              type: 'saveList',
              payload: response,
            });
          }
          if (callback && response) {
            callback(response);
          }
        },
    },
    reducers: {
      saveList(state, action) {
        return {
          ...state,
          list: action.payload,
        }
      },
    },
}

修改路径后我们创建组件 components/rightList 直接上代码了

components/rightList/index.js

import React, { Component } from 'react';
import { connect } from 'dva';
import { Menu, Dropdown, Icon } from 'antd';
import styles from './index.less';

const { SubMenu } = Menu;
@connect(({rightlist, global}) => ({
    rightlist, global
}))
class RightMenu extends Component {
    state = {
        content: '',
        visible: false,
        list: []
    }

    componentDidMount() {
        const { children } = this.props
        this.setState({
            content: children
        })
        this.getList()
        document.addEventListener('contextmenu', this.handleContextMenu)
        window.addEventListener('resize', this.resize);
        document.addEventListener('click', this.handleClick);
        document.addEventListener('scroll', this.handleScroll);
    }

    componentWillUnmount() {
        document.removeEventListener('contextmenu', this.handleContextMenu)
        window.removeEventListener('resize', this.resize);
        document.removeEventListener('click', this.handleClick);
        document.removeEventListener('scroll', this.handleScroll);
    }

    getList() {
        const { dispatch } = this.props;
        dispatch({
            type: 'rightlist/fetchList',
            callback: (res) => {
                this.setState({
                    list: res
                })
            }
        });
    }

    handleClick = (event) => {
        const { visible } = this.state;
        const wasOutside = !(event.target.contains === this.root);
    
        if (wasOutside && visible) this.setState({ visible: false, });
      };
    
      handleScroll = () => {
          const { visible } = this.state;
    
          if (visible) this.setState({ visible: false, });
      }

    runderMenu = () => {
        const { visible, list } = this.state
        console.log(list)
        const menu = list.map(item => {
            if (item.children) {
                return ({item.title}}  key={item.id}>
                    {item.children.map(i => {
                        return ({i.title})
                    })}
                )
            } else {
                return (
                    {item.title}
                )
            }
        })
        console.log(menu)
        return (
          visible && (
            
{ this.root = ref }} className={styles.contextMenuWrap}> { menu }
) ) } handleContextMenu = (event) => { event.preventDefault() this.setState({ visible: true }) // clientX/Y 获取到的是触发点相对于浏览器可视区域左上角距离 const clickX = event.clientX const clickY = event.clientY // window.innerWidth/innerHeight 获取的是当前浏览器窗口的视口宽度/高度 const screenW = window.innerWidth const screenH = window.innerHeight // 获取自定义菜单的宽度/高度 const rootW = this.root.offsetWidth const rootH = this.root.offsetHeight // right为true,说明鼠标点击的位置到浏览器的右边界的宽度可以放下菜单。否则,菜单放到左边。 // bottom为true,说明鼠标点击位置到浏览器的下边界的高度可以放下菜单。否则,菜单放到上边。 const right = (screenW - clickX) > rootW const left = !right const bottom = (screenH - clickY) > rootH const top = !bottom if (right) { this.root.style.left = `${clickX}px` } if (left) { this.root.style.left = `${clickX - rootW}px` } if (bottom) { this.root.style.top = `${clickY}px` } if (top) { this.root.style.top = `${clickY - rootH}px` } }; render() { return (
demo {this.state.content} {this.runderMenu()}
); } } export default RightMenu;

components/rightList/index.less

.rwrap{
    width: 100%;
    height: 100%;
    background: #5b5b5b;
}
.contextMenuWrap{
    z-index: 100;
    position: fixed;
    // background: linear-gradient(to right, #ffffff, rgba(190, 190, 190, 0.65));
    box-shadow: 0px 2px 5px #383737;
    border-radius: 4px;
    padding-top: 5px;
    .contextMenuOption{
      // padding: 0px 50px 2px 15px;
      min-width: 160px;
      cursor: default;
      font-size: 14px;
      &:hover {
        background: #9c9c9c;
        color: white;
      }
      &:active {
        color: #b5b7be;
        background: linear-gradient(to top, #555, #444);
      }
    }
    .contextMenuSeparator{
      width: 100%;
      height: 1px;
      background: rgba(0, 0, 0, 0.65);
      margin: 2px 0;
    }
  }

.hide{
  display: none;
}
.contextMenuOption{
  // padding: 0px 50px 2px 15px;
  min-width: 160px;
  cursor: default;
  font-size: 14px;
  &:hover {
    background: #9c9c9c;
    color: white;
  }
  &:active {
    color: #b5b7be;
    background: linear-gradient(to top, #555, #444);
  }
}

这样就可以实现 右键菜单的功能

效果图

你可能感兴趣的:(react右键菜单 mock数据)