「10」next-shopping:admin页面布局、用户组件调整

我们先来调整一下C端页面,把app/(normal-layout) 改名叫app/(client-layout),虽然对实际没有影响,但是对开发者更好识别

我们现在可以把layout抽成通用的:

新建components/Layouts/ClientLayout.jsx

jsx 复制代码
import { Navbar } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <Navbar />
      {children}
    </>
  )
}

这是客户端的页面通用布局,header部分需要nav

新建components/Layouts/DashboardLayout.jsx

jsx 复制代码
export default function Layout({ children }) {
  return <div>{children} </div>
}

目前仅最简单的包一层,后面会添加NavFooter

新建components/Layouts/ProfileLayout.jsx

jsx 复制代码
export default function Layout({ children }) {
  return <div>{children}</div>
}

这个个人中心也是组简单的布局

components/index.js中导出

jsx 复制代码
export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'

然后我们用ClientLayout来代替app/(main)/(client-layout)/layout.js的布局

jsx 复制代码
'use client'

import { ClientLayout } from '@/components'
import { useRefreshToken } from '@/hooks'

export default function Layout({ children }) {
  useRefreshToken()
  return (
    <>
      <ClientLayout>{children}</ClientLayout>
    </>
  )
}

效果如下:

然后我们新建app/(dashboard-layout)/layout.js

jsx 复制代码
'use client'

import { DashboardLayout } from '@/components'

export default function Layout({ children }) {
  return (
    <>
      <DashboardLayout>{children}</DashboardLayout>
    </>
  )
}

新建app/(dashboard-layout)/dashboard/page.jsx

jsx 复制代码
export default function Page() {
  return <div>这是管理页面</div>
}

效果如下:

注销页面

我们先来实现两个通用组件BoxLinkArrowLink

新建components/share/BoxLink.jsx

jsx 复制代码
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { Icons } from '@/components'

export default function BoxLink({ children, path, name }) {
  const router = useRouter()

  return (
    <div
      className={`transition-colors hover:bg-gray-200 px-3 ${
        router.asPath === path ? 'border-r-4 border-red-600' : 'border-r-4 border-white'
      }`}
    >
      <Link href={path}>
        <span className="flex justify-between mx-4 py-4 gap-x-2 border-t border-gray-300">
          {children}
          <span className="ml-auto mr-3">{name}</span>
          <Icons.ArrowLeft className="icon" />
        </span>
      </Link>
    </div>
  )
}

新建components/share/ArrowLink.jsx

jsx 复制代码
import Link from 'next/link'
import { Icons } from '@/components'

export default function ArrowLink({ children, path }) {
  return (
    <Link href={path}>
      <span className="inline-flex items-center text-blue-400 text-sm max-w-max">
        <span className="uppercase">{children}</span>
        <Icons.ArrowLeft className="icon text-blue-400" />
      </span>
    </Link>
  )
}

然后我们来写退出登录组件:

新建components/Logout.jsx

jsx 复制代码
import { useRouter } from 'next/navigation'
import { useDispatch } from 'react-redux'
import { userLogout } from '@/store/slices/authSlice'
import { Icons } from '@/components'
import alert from '@/utils/alert'

export default function Logout() {
  const dispatch = useDispatch()
  const router = useRouter()

  const handleLogout = () => {
    router.push('/')
    dispatch(userLogout())
    alert('success', '退出成功')
  }

  return (
    <div className="transition-colors hover:bg-gray-200 px-3">
      <div
        role="button"
        className="flex justify-between cursor-pointer py-4 gap-x-2 mx-4  border-t border-gray-300"
        onClick={() => handleLogout()}
      >
        <Icons.Logout className="icon text-black" />
        <span className="ml-auto mr-3">其他组织者</span>
      </div>
    </div>
  )
}

先在components/index.js中导出组件:

jsx 复制代码
export { default as Icons } from './share/Icons'
export { default as Loading } from './share/Loading'
export { default as DisplayError } from './share/DisplayError'
export { default as Navbar } from './Navbar'
export { default as User } from './User'
export { default as Cart } from './Cart'
export { default as Search } from './Search'
export { default as ClientLayout } from './Layouts/ClientLayout'
export { default as DashboardLayout } from './Layouts/DashboardLayout'
export { default as ProfileLayout } from './Layouts/ProfileLayout'
export { default as ArrowLink } from './share/ArrowLink'
export { default as BoxLink } from './share/BoxLink'
export { default as Logout } from './Lagout'

现在来修改User组件,我们先看看当前的效果:

修改components/User.jsx

jsx 复制代码
import Image from 'next/image'
import Link from 'next/link'
import { useState } from 'react'

import { useSelector } from 'react-redux'
import { BoxLink, Icons, Logout } from './index'

export default function User() {
  const { user } = useSelector(state => state.auth)

  const [isOpen, setIsOpen] = useState(false)

  if (!user) {
    return (
      <div className="flex items-center gap-x-2 lg:border lg:border-gray-300 lg:rounded-md lg:py-2 lg:px-3 text-sm">
        <Link href="/login">
          <span className="flex items-center gap-x-1">
            <Icons.Login className="icon" />
            登录
          </span>
        </Link>
        <span className="hidden lg:block lg:border lg:border-gray-300 lg:h-6"></span>
        <Link href="/register">
          <span className="hidden lg:block px-2">注册</span>
        </Link>
      </div>
    )
  }

  return (
    <>
      <div className="lg:hidden">
        <Link href="/profile">
          <span>
            <Icons.User className="icon" />
          </span>
        </Link>
      </div>
      <div
        className={`hidden lg:cursor-pointer lg:relative lg:flex lg:rounded lg:p-1.5 lg:transition ${isOpen && 'bg-red-100'}`}
        onClick={() => setIsOpen(!isOpen)}
      >
        <Icons.User className="icon" />
        <Icons.ArrowDown className="icon" />
        <div
          className={` bg-white shadow-md rounded overflow-hidden absolute top-full left-0 w-60
                   border border-gray-100 ${isOpen ? 'block' : 'hidden'}`}
        >
          <BoxLink path="/profile" name={user.name} className="border-t-0">
            <div className="realative w-6 h-6">
              <Image src={'/avatar.png'} alt="user" width={200} height={200} />
            </div>
          </BoxLink>
          <Logout />
        </div>
      </div>
    </>
  )
}

主要是用BoxLink套了一层,省略很多代码,然后把退出登录的逻辑单独抽出来的Logout.jsx

代码地址:github.com/liyunfu1998...

相关推荐
Python私教2 小时前
yggjs_rlayout框架v0.1.2使用教程 02 TechLayout 布局组件
react.js
盛夏绽放6 小时前
jQuery 知识点复习总览
前端·javascript·jquery
胡gh8 小时前
依旧性能优化,如何在浅比较上做文章,memo 满天飞,谁在裸奔?
前端·react.js·面试
大怪v8 小时前
超赞👍!优秀前端佬的电子布洛芬技术网站!
前端·javascript·vue.js
胡gh9 小时前
你一般用哪些状态管理库?别担心,Zustand和Redux就能说个10分钟
前端·面试·node.js
项目題供诗9 小时前
React学习(十二)
javascript·学习·react.js
无羡仙9 小时前
Webpack 背后做了什么?
javascript·webpack
roamingcode10 小时前
Claude Code NPM 包发布命令
前端·npm·node.js·claude·自定义指令·claude code
码哥DFS10 小时前
NPM模块化总结
前端·javascript
灵感__idea11 小时前
JavaScript高级程序设计(第5版):代码整洁之道
前端·javascript·程序员