本文最后更新于:6 个月前
                  
                
              
            
            
              
                
                前言 Ant Design Pro 
什么是Ant Design Pro?按我的理解,这是一个前端框架,却又不仅仅是一个前端框架 Ant Design Pro的语言是React,它基于Ant Design设计体系,提供了丰富的页面模板、组件和功能,非常适合快速搭建前台页面 下面是比较官方的定义:  
1 Ant Design  Pro 是一个开箱即用的企业级中后台前端/设计解决方案,基于 Ant Design  设计体系,内置了丰富的页面模板、组件和功能,旨在帮助开发者快速搭建企业级中后台应用。
1 2 3 4 5 Ant Design  Pro 提供了完整的前端开发工作流和最佳实践,具有以下特点和优势:1. 高度定制化:Ant Design  Pro 提供了可灵活配置的模板,可以根据项目需求自定义布局和功能,非常适合快速定制企业级应用。2. 丰富的模板和组件:Ant Design  Pro 内置了多个精心设计的页面模板和丰富的 UI 组件,包括表单、表格、图表、地图等,使开发者可		 以快速构建复杂的中后台应用。3. 系统化的工作流程:Ant Design  Pro 提供了完善的开发工作流程,包括开发环境、测试环境和生产环境的配置、代码检查、测试和构建	   等,使开发者能够便捷地进行前端开发。4. 功能丰富的插件集成:Ant Design  Pro 集成了常用的中后台应用所需的功能,包括菜单权限管理、数据请求、国际化、登录认证等,可       以快速构建完整的、稳定的企业级应用。
Ant Design Vue 
Vite 
写作目标 
脚手架的搭建固然简单,在脚手架的基础上,我们可以更方便地改造代码、对接后端代码、编写我们自己的业务逻辑 但前提是我们要理清框架的目录结构,以及相关的逻辑代码 Ant Design Pro内置了独特的登录页面、欢迎页面、表格页面,我们要理清登录校验逻辑、发送请求到自己的后端接口、重定向到login页的逻辑、管理员校验、页面路由配置等等,这些都是必须熟练掌握的 将来开发个人网站,或者开发个人项目,都可以基于Ant Design Pro框架,更快捷、更高效  
正文 Vite 开发思路 
使用 vite工具快速构建Vue开发框架来从零开发,要做什么?一定是做到以下几点:(2023/08/01午) 
vite 快速构建框架,启动项目 配置启动端口 全局axios配置,开发全局请求拦截和相应拦截器,做好跨域请求处理  
 
快速搭建 
修改tsconfig.json文件,添加如下配置:  
1 "moduleResolution" :  "Node" , 
如果依赖安装失败,可能是npm镜像源的问题,两种解决方法: 
1 npm set  registry  https://registry .npmjs.org/
启动项目:(2023/08/01早)  
启动端口 1 2 3 4 5 6 7 //  https:// vitejs.dev/config/ 7073 , //  修改为你想要的端口号
全局axios配置 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import  axios from  "axios" ;const  myAxios = axios.create ({baseURL : "http://localhost:8083/api" , withCredentials : true ,interceptors .request .use ((config ) =>  {return  config;(error ) =>  {return  Promise .reject (error);interceptors .response .use ((response ) =>  {return  response.data ;(error ) =>  {return  Promise .reject (error);export  default  myAxios;
组件样式BUG 
在做Memory-伙伴匹配时,一直有一个问题困扰着我:组件样式有问题 这次使用Vue从零开发壁纸网站时,终于彻查了这个不起眼的问题:  
1 2 3 4 5 6 7 import  { createApp } from  "vue" ;import  "vant/lib/index.css" ;import  Vant  from  "vant" ;import  App  from  "./App.vue" ;createApp (App ).use (Vant ).mount ("#app" );
没错,只需在main.ts下,引入 “vant/lib/index.css” 样式即可(2023/08/02早)  
请求头设置无效 
这个真恶心到我了,POST请求的请求头设置无效(2023/08/01晚) 本来是打算做一个前端上传图片文件,后端接收的功能,但这涉及到前端如何发送,后端如何接收的问题 做了大量的尝试,只有这种方法,才能在后端正常接收到图片文件:  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 const  res = await  myAxiospost ("/wallpaper/upload" , file, {headers : {"Content-Type" : "multipart/form-data" ,then (function  (response ) {if  (response.data ) {return  response.data ;catch (function  (error ) {console .log (error);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @PostMapping("/upload") public  String uploadFile (@RequestParam("file")  MultipartFile file)  {if  (file.isEmpty()) {return  "上传的文件为空" ;try  {byte [] bytes = file.getBytes();return  "文件上传成功" ;catch  (IOException e) {return  "文件上传失败" ;
Ant Design Pro 快速搭建 
我们可以按以下步骤,快速搭建Ant Design Pro脚手架: 在正确安装Node.js环境下的前提下,依次执行以下命令: 使用npm全局安装 pro-cli 构建工具(脚手架):  
1 npm  i @ant-design/pro-cli -g
至此,前端项目框架搭建完成,启动项目:(2023/07/21晚)  
页面路由报错 
在 config/routes.ts 下设置好页面路由后,一定要在对应组件下添加index.tsx文件:  
1 2 3 4 5 6 7 name : '接口详情' ,icon : 'user' ,path : '/interfaceInfo/info' ,component : './TableList/entireCommend' ,
页面路由跳转(1) 
使用 umi/router 实现路由跳转: 全局安装 umi:  
1 2 3 4 5 import  router from  'umi/router' ;function  goToListPage (push ('/list' );
1 2 3 4 5 import  Link  from  'umi/link' ;export  default  () => (<Link  to ="/list" > Go to list page</Link > 
OpenAI生成接口 
1 2 3 4 5 6 7 openAPI : [requestLibPath : "import { request } from '@umijs/max'" ,schemaPath : 'http://localhost:8104/api/v2/api-docs?group=壁纸分享' ,projectName : 'pic-memories' ,
执行以下命令,一键生成接口:(2023/08/09午)  
最简页面样式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 import  { listInterfaceInfoByPageUsingPOST } from  '@/services/memory-api/interfaceInfoController' ;import  { ProList  } from  '@ant-design/pro-components' ;import  { Button , Space  } from  'antd' ;import  React , { useEffect, useState } from  'react' ;import  { useHistory } from  'react-router-dom' ;const  InterfaceInfoList : React .FC  = (props ) =>  {const  [interfaceInfo, setInterfaceInfo] = useState<API .InterfaceInfo []>([]);const  fetchData  = async  (params: { pageSize?: number ; current?: number  } ) => {try  {const  res = await  listInterfaceInfoByPageUsingPOST ({console .log ('res = '  + res.data ?.records );if  (res.data ) {setInterfaceInfo (res.data .records );catch  (error) {console .error (error);const  history = useHistory ();const  handleButtonClick  = (push ('/TableList/entireCommend' );return  (useEffect (() =>  {console .log ('啊啊啊' );fetchData (1 , 5 );ProList <any >"name" "基础列表" "基础列表的配置" title : {dataIndex : 'name' ,description : {dataIndex : 'description' ,actions : {render : (text, row ) =>  {return  (<Space >                   <div >                      <Button  onClick ={handleButtonClick} > 跳转到目标页面</Button >                    </div >                  </Space >  export  default  InterfaceInfoList ;
改造框架 
今天我把API 接口开放平台的前端代码拉下来了,给PicMemories做一个管理员后台 怎么快速改造呢?不要惊慌,做到三点即可:(2023/08/11晚) 
修改接口文档地址,重新生成接口 
改造获取用户登录态接口 
改造登录接口 
改造获取表单信息接口 
 
 
路由配置错误 
1 2 3 4 5 6 7 8 9 10 11 12 13 PS D :\Project\星球项目\memory-api\memory-api-frontend> yarn start :dev.22 .19 D :\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\preset-umi\dist\features\tmpFiles\routes.js :61 :46 )D :\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\preset-umi\dist\features\appData\appData.js :51 :35 )D :\Project\星球项目\memory-api\memory-api-frontend\node_modules\@umijs\core\dist\service\service.js :136 :38  {code : 'MODULE_NOT_FOUND' in :D :\Project\星球项目\memory-api\memory-api-frontend\node_modules\.cache\logger\umi.loghttps ://github.com/umijs/umi/issuesin  3.83 s.
肯定是路由配置错误了,检查检查吧
好像上面的栏目提到过。。(2023/08/16午)  
可视化数据图表 
进入官网,找到相中的图表,在线调试,复制代码:(2023/08/25晚)  
最简页面2.0 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import {PageContainer} from '@ant-design/pro-components';
有时间就学学React框架语法了,挺有意思的,到时候总结点东西再记录下react的页面开发技巧(2023/08/25晚)  
区分管理员页面和普通用户页面 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 path : '/' ,access : 'canAdmin' ,name : 'admin' ,icon : 'smile' ,routes : [name : '用户信息' ,access : 'canAdmin' ,icon : 'user' ,path : '/user/list' ,component : './TableList/Admin/User' ,name : '接口信息' ,access : 'canAdmin' ,icon : 'user' ,path : '/interfaceInfo/list' ,component : './TableList/Admin/InterfaceInfo' ,name : '接口分析' ,icon : 'user' ,path : '/admin/interface_analysis' ,component : './TableList/Admin/InterfaceAnalysis' 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20  path : '/welcome' ,name : 'welcome' ,icon : 'smile' ,component : './Welcome' ,path : '/' ,redirect : '/welcome' ,path : '/' ,access : 'canAdmin' ,name : 'admin' ,
如上,这里的重定向一定要写在管理员页面路由的前面,这样才能正常跳转至/welcome(2023/09/27午)  
Prettier 美化配置 
配置生效文件 ,以及快速格式化时 ,使用 Prettier 帮助快速美化代码  (2023/10/08早)  
 
一条龙完成 Ant Design Pro 初始化 
框架初始化 
1 npm  i @ant-design/pro-cli -g
至此,前端项目框架搭建完成,启动项目:(2023/10/03晚)  
框架瘦身 
国际化移出
 
框架改造 
登录注册
登录请求 成功返回 失败捕获
保存全局状态
修改头像 水印
 
1 2 3 4 5 6 7 8 9 10 11 const  fetchUserInfo  = async  (const  userInfo = await  getLoginUserUsingGET ();if  (userInfo) {flushSync (() =>  {setInitialState ((s ) =>  ({currentUser : userInfo,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 const  handleSubmit  = async  (values: API.UserLoginRequest ) => {try  {const  res = await  userLoginUsingPOST ({ ...values, type  });if  (res.code  === 0 ) {const  defaultLoginSuccessMessage = intl.formatMessage ({id : 'pages.login.success' ,defaultMessage : '登录成功!' ,success (defaultLoginSuccessMessage);await  fetchUserInfo ();const  urlParams = new  URL (window .location .href ).searchParams ;push (urlParams.get ('redirect' ) || '/' );return ;catch  (error) {const  defaultLoginFailureMessage = '登录失败,请重试!' console .log (error);error (defaultLoginFailureMessage);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 export  async  function  getInitialState (Promise <{API .LoginUserVO ;const  fetchUserInfo  = async  (try  {const  res = await  getLoginUserUsingGET ({skipErrorHandler : true ,return  res.data ;catch  (error) {push (loginPath);return  undefined ;const  {location} = history;if  (location.pathname  !== loginPath) {const  currentUser = await  fetchUserInfo ();return  {return  {};
1 2 3 4 5 6 export  default  function  access (initialState: { currentUser?: API.LoginUserVO } | undefined  ) {const  { currentUser } = initialState ?? {};return  {canAdmin : currentUser && currentUser.userRole  === '0' ,
1 2 3 4 5 6 7 8 9 openAPI : [requestLibPath : "import { request } from '@umijs/max'" ,schemaPath : "http://localhost:8101/api/v2/api-docs" ,projectName : 'memory-bi' ,mock : false ,
这里踩了个很恶心的 BUG,执行完成 run openapi 之后,有些方法调用的路径会发生紊乱:  
1 import  { outLogin } from  '@//services/ant-design-pro/login' ;
开发一个页面的步骤 
创建路由和页面(2023/10/11晚) 获取需要的数据,定义 state 变量来存储数据,用于页面展示
先把最简单 、最直观 的数据展示给前端,再去调样式
引入 Ant Design  的 List 组件,复制示例代码
调整 List 组件中的内容为自己的(注意,获取用户头像可以从初始化状态中获取)
 
1 2 const  { initialState} = useModel ('@@initialState' );const  { currentUser } = initialState ?? {};
针对样式,对数据进行一些处理,比如统一隐藏自身的 title  
增加分页 (当前页码、每页展示数、总记录数 )、增加展示列  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <List
1 2 3 4 5 6 7 8 9 10 11 12 <Search
1 const  [loading, setLoading] = useState<boolean >(false )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const  loadData  = async  (setLoading (true );try  {const  res = await  listChartByPageUsingPOST (searchParams);if  (res.data ) {setChartList (res.data ?.records  ?? []);setTotal (res.data ?.total  ?? 0 );setLoading (false );else  {error ("获取我的图标失败" )catch  (e : any ) {error ("获取我的图标失败"  + e.message )
这里添加了一个 loading 效果,在执行搜索过程 中(即按下搜索后,到数据成功返回的时间段 ),搜索按钮的状态为转圈圈  
 
模拟低网速运行状态 
选中对应的网络状态,就可以模仿在该网络环境下发送请求 了 (2023/12/07晚)  
 
引入外部页面组件 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import  {PageContainer } from  "@ant-design/pro-components" ;import  {CaretRightFilled } from  "@ant-design/icons" ;import  {Button , Form , message, Input , Tag , Table } from  'antd' ;import  {ColumnsType } from  "antd/es/table" ;import  React , {useState} from  "react" ;import  initialState from  "@@/plugin-initialState/@@initialState" ;import  {invokeInterfaceInfoUsingPOST} from  "@/services/memory-api/interfaceInfoController" ;import  {useParams} from  "@@/exports" ;const  RandomPoem : React .FC  = () =>  {return  (<PageContainer >       .....................     </PageContainer >  export  default  RandomPoem ;
1 import  RandomPoem  from  "@/pages/TableList/InterfaceInfo/RandomPoem" ;
Ant Design Vue 
快速上手 
🍖 推荐阅读:Home | Vue CLI (vuejs.org) (2024/01/15晚) 
 
1 2 3 npm install -g @vue /cliglobal  add  @vue /cli
1 vue create  antd-demo  #项目名	 
1 npm  uninstall -g @vue/cli
1 npx @vue /cli create antd-demo	
引入Ant Design组件 
1 npm i  --save  ant-design-vue
在main.ts中如此配置,引入Ant Design组件:  
1 2 3 4 5 6 import  {createApp} from  'vue' import  App  from  './App.vue' import  router from  './router' import  Antd  from  'ant-design-vue' ;createApp (App ).use (router).use (Antd ).mount ('#app' )
配置路由 
1 2 3 4 5 6 7 8 9 10 11 12 const  routes : Array <RouteRecordRaw > = [path : '/' ,name : 'index' ,component : IndexPage path : '/about' ,name : 'about' ,component : () =>  import ( '../views/AboutView.vue' )
封装全局axios 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import  axios from  "axios" ;const  instance = axios.create ({baseURL : "http://localhost:8102/api" ,timeout : 10000 ,headers : {},interceptors .response .use (function  (response ) {const  data = response.data ;if  (data.code  === 0 ) {return  data.data ;console .error ("request error" , data);return  response.data ;function  (error ) {return  Promise .reject (error);export  default  instance;
路由嵌套 
app.vue中如此配置:(2023/08/27早)  
1 2 3 <template> <router-view/> </template> 
1 2 3 4 5 在Ant Design Vue中,App.vue是项目的根组件,是所有页面组件的父容器。在这段代码中,`<router-view/>`是一个特殊的组件标签,它用于显示路由器(router)根据当前路由匹配的页面组件。
比如说当前URL中的path路径为:/about 而我们配置的路由中:
 
1 2 3 4 5 {path : '/about' ,name : 'about' ,import ( '../views/AboutView.vue' )
那么就会展示/about下的组件内容了 我在主页面中引入了标签页组件:
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <a-tabs  v-model:activeKey ="activeKey" > <a-tab-pane  key ="文章"  tab ="文章" > <PostList  :post-list ="postList" /> </a-tab-pane > <a-tab-pane  key ="图片"  tab ="图片" > </a-tab-pane > <a-tab-pane  key ="用户"  tab ="用户" > </a-tab-pane > </a-tabs > 
可以看到在tab栏下,我引入了PostList组件,并传入了postList参数 那么PostList组件就会展示在该标签栏下,效果如下:(2023/08/27早)  
子页面嵌套 
纠正以下上面说明的页面组件的嵌套方法,正确的嵌套方法应该是这样的: 
在index页面下引入子组件: 
 
1 2 3 4 5 <script lang="ts"  setup="ts" >import  UserListPage  from  "@/components/userListPage.vue" ;
1 2 3 4 5 6 7 8 9 10 11 <template>
直接如此引用子组件(还可传递参数 ,可参考上面 路由嵌套  的实现方法) 
 
1 2 3 4 <a-tab-pane key="1" tab="用户列表">
1 2 3 4 5 <a-list
1 2 3 4 5 6 7 8 9 10 11 12 <script setup lang="ts" >import  {withDefaults, defineProps} from  "vue" ;interface  Props  {userInfoList : any [];const  props = withDefaults (defineProps<Props >(), {userInfoList : () =>  [],name : "UserListPage" 
完成,页面显示如下,子组件已成功显示在index页面中:  
配置启动端口 
在 vue.config.js 下,进行如下配置:(2023/09/09午)  
1 2 3 4 5 6 7 const  { defineConfig } = require ('@vue/cli-service' )module .exports  = defineConfig ({transpileDependencies : true ,devServer : {port : 7071 
双向绑定 
做登录页面时,一个简单的表单和数据双向绑定搞了半天,这里直接给出代码示例了:(2023/09/10午) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <a-form @submit="handleSubmit">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 const  userAccount = ref ("" );const  userPassword = ref ("" );const  handleSubmit  = (MyAxios .post ("/user/login" , {userAccount : userAccount.value ,userPassword : userPassword.value ,then ((values ) =>  {console .log ('表单数据:' , values);catch ((error ) =>  {console .error ('表单验证失败:' , error);
日常犯傻 
使用 Vue 的 ref() 语法时,容易忘记取.value(2023/09/13晚)  
1 const  currentUserId = currentUser.value .id ;
1 const  socketUrl = `ws://localhost:8081/api/websocket/${currentUserId} ` ;
处理JSON字符串 
前台获取服务器转发的消息后,需要解析出接收者,再判断接收者是否为当前用户,是则为该用户展示具体消息(2023/09/14晚)  
1 2 3 4 5 6 7 8 9 10 11 12 13 onmessage  = function  (msg ) {value  = msg.data ;console .log ("这条消息是发给: "  + receiveMsg.value  + " 的" )console .log ("这条消息是发给: "  + receiveMsg.value .receiverId  + " 的" )const  content = receiveMsg.value .content ;if  (receiverId === currentUserId) {setMessage ("服务端回应: "  + content + "发给: "  + receiverId);
前端返回的 mes 是 JSON字符串,我看见控制台输出的内容是,以为是个对象 ,结果取到的属性值是undefined: 
 
1 { "senderId" : "1657284783190523906" , "receiverId" : "1657284893320364034" , "content" : "阿发" , "sendTime" : "2023-09-14T13:29:11.309Z" } 
调试了半天,检查了下 mes 的类型,才发现是个JSON字符串 ,奶奶的 
 
1 console .log ("type of "  + typeof  (receiveMsg.value))
所以要将msg JSON字符串解析为对象后,才可以正常拿到属性值  
1 receiveMsg.value  = JSON.parse(msg.data)
最后优化代码,同时处理两种情况:服务器首次连接成功后的响应(普通字符串 ) / 服务器转发的消息(JSON字符串 ) 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 onmessage  = function  (msg ) {if  (typeof  (msg) === String ) {value  = JSON .parse (msg.data );value  = msg.data ;console .log ("这条消息是发给: "  + receiveMsg.value .receiverId  + " 的" )const  content = receiveMsg.value .content ;if  (receiverId === currentUserId) {setMessage ("服务端回应: "  + content + "发给: "  + receiverId);
各种坑都能踩到,不过好在花点时间排错,都能解决掉 👏👏👏(2023/09/14晚)  
页面路由跳转(2) 
1 2 3 4 5 {path : '/chat' ,name : 'chat' ,component : () =>  import ( '../pages/chatPage.vue' )
包含path(页面路由)、name(页面别名)、component(页面展示组件) 那么我们可以如此实现精准的页面跳转 和参数传递:
 
1 2 3 4 5 6 7 8 9 10 11 12 import  router from  "@/router" ;push ({name :"chat" ,path :"/chat" ,query : {chatUserId :12345 params :{id :"12345" 
也可以简单的改变当前页面的路由参数 ,而不进行页面跳转 :(适用于 Tab 页之间切换时,标记 tab页 ) 
 
1 2 3 4 5 6 7 import  router from  "@/router" ;push ({query : {name : "abab" 
那么跳转过去的页面该如何获取当前页面的路由地址 、携带的参数 等信息呢?引入Vue Router组件 :(2023/09/16早) 
 
1 2 3 4 5 6 7 8 import  {useRoute} from  'vue-router' ;const  route = useRoute ();onMounted (() =>  {console .log ('携带参数:' , route.query )console .log ('路由地址:' , route.path )console .log ('传递参数:' , route.params )
动态新增tab标签页 
1 2 3 4 5 6 <a-tabs v-model :activeKey="activeKey"  tab-position="left"  @change ="handleTabChange" ><a-tab-pane  v-for ="tab in tabs"  :key ="tab.key"  :tab ="tab.tab.chatTabName" >                {{ tab.content }}      </a-tab-pane >  
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 onMounted (() =>  {addTab ();const  addTab  = (value  = route.query const  newTab = {key : Date .now ().toString (), tab : chatTabName.value ,content : '新标签页内容' ,value .push (newTab);value  = newTab.key ; 
这样就轻松实现了(MemoryChat开放过程中的废弃想法 )(2023/09/16午)  
icon图标的使用 
看官网,首先下载安装相关依赖:(2023/09/17晚)  
1 npm  install --save @ant-design/icons-vue
引入相关 icon图标 组件 (这步操作,,WebStorm是不会自动给你引入这个组件的,怪不得我 tab标签页 的页面图标不显示,一个星期都没解决掉,这编译器害人不浅) 
1 import  { StarOutlined , StarFilled , StarTwoTone  } from  '@ant-design/icons-vue' ;
1 2 3 4 5 <div>
监听选中的Tab标签页 
我们选中Tab标签页后,如果绑定了activeKey,就会将该Tab页的Key值,给到activeKey 
 
1 2 3 4 <a-tab-pane v-model:activeKey="activeKey" v-for="tab in friendList" :key="tab.id" :tab="tab.username"
1 2 const  activeKey = ref (currentUserId);
1 const  activeKey = ref (currentUserId);
我们现在要实现:刷新页面后,仍然选中刚才选中的Tab标签页,即activeKey值需要更新,更新为刚才的key值 
但是,当页面刷新后activeKey的值就丢失了,所以我们要对active进行监听 ,随时保存它的值,如下: 
 
1 2 3 4 watch (activeKey, (value ) =>  {localStorage .setItem ('activeKey' , value);
1 2 3 4 5 6 7 onMounted (() =>  {value  = localStorage .getItem ('activeKey' )
点击跳转不同的页面 
1 2 3 4 <!--博文-->
1 2 3 4 5 6 7 8 9 10 11 const  goToRead  = (id: never  ) => {push ({name : "blogRead" ,path : "/blog/read" ,query : {articleId : id
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <template>
就这样简单地记录下思路吧(2023/09/24午)  
网页中支持Markdown语法写博客 
然后,在你的组件中,你可以导入并实例化markdown-it,将Markdown文本作为输入,使用.render()方法将其转换为HTML并展示在网页上 
 
1 2 3 4 5 6 7 import  MarkdownIt  from  'markdown-it' ;const  parsedContent = ref ()const  md = new  MarkdownIt ();value  = md.render (articleInfo.value .content );
1 2 3 <div v-html="parsedContent"
子组件绑定自己独有的属性 
Eslint 优化导致git代码推送失败 
这是我在今晚推送 Memory API接口开放平台时 遇到的报错。详情看下图: (2023/10/18晚)  
 
如上图所示,使用 git 推送代码竟然报错了,这是什么原因呢? 
我们简单罗列出以上的报错信息: 
 
这些错误和警告是由静态代码分析工具 ESLint 提供的。根据报错信息,您遇到了一些问题:
File ignored because of a matching ignore pattern. Use "--no-ignore" to override:这是一个警告,意味着某些文件被忽略了,因为它们匹配了 .eslintignore 文件中设定的忽略模式。您可以使用 --no-ignore 参数来覆盖这个忽略,让这些文件被检查。'loading' is assigned a value but never used @typescript-eslint/no-unused-vars:这是一个错误,提示您在 InterfaceInfo/index.tsx 文件中定义了 loading 变量,但是从未使用过。您可以删除没被使用的变量,或者使用变量来解决您需要的逻辑。Missing "key" prop for element in array react/jsx-key:这是两个错误,它们指出在您的组件 InterfaceInfo 的 renderDataSource 方法中,两个元素没有提供 key 属性。React 要求在渲染组件数组时,每个元素都要提供一个唯一的 key 属性,以便在更新列表时进行准确的 diff 操作。您需要为这两个元素添加一个适当的 key 属性。 
 
1 git  commit -m "接口调用页面优化 接口参数信息 接口文档预开发"  --no -verify
这里其实还有很多有关 ESLint 的配置管理 ,我就暂时不深究了,日后有机会再展开聊聊 
 
安装依赖 
导入外部插件时,要选择这个选项,嗖嗖嗖就安装好了(可能这个安装默认是 yarn 的缘故)(2023/11/11晚)  
但是点第一个或者执行以下命令就得卡住好一会儿,还下载安装失败: 
 
快速入门 Vue 指南 
🍖 推荐阅读:写给后端大忙人看的vue入门指南 - 掘金 (juejin.cn) 
还是非常推荐阅读的,我第一次学 Vue 就是跟着黑马的教程学的,这些操作也都过了一遍的
经常使用脚手架 (vite 、vue/cli  等)直接构建 Vue 项目 ,很方便很快捷
有时间再实操一遍吧,后端开发人员多了解一些 Vue 还是很有必要的(2023/11/11晚) 
 
栅格化布局 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div style="margin-top: 30px">
引入外部组件页面 
编写 ComprehensiveArticle.vue 页面: 
 
1 2 3 4 5 6 7 8 9 10 <template>
在 ArticleList.vue 中导入该页面组件: 
 
1 2 3 4 5 6 7 8 9 <div style="width: 500px">
1 2 3 4 <script setup lang="ts" >import  CompreArticleList  from  "@/components/CompreArticleList.vue" ;
引入外部组件页面并传参 
外部页面组件 ArticleList 携带参数,参数名为 compreList,参数值为 articleList 
 
1 2 3 4 5 6 7 <a-tabs v-model:activeKey="activeKey" tab-position="left">
编写内部组件 CompreArticleList,接收参数 compreList,使用 a-list组件展示 
 
1 2 3 4 5 6 7 8  <a-list
在 CompreArticleList 下指明接收参数名(2023/12/22早)  
 
1 2 3 4 5 6 7 8 9 10 11 12 13 <script setup lang="ts" >import  {defineProps, withDefaults} from  "vue/dist/vue" ;interface  Props  {compreList : any [];const  props = withDefaults (defineProps<Props >(), {compreList : () =>  [],
自定义 icon 图标 
1 npm install --save @ant-design/icons-vue
1 import  Icon  from  '@ant-design/icons-vue' ;
1 2 3 4 5 6 7 <Icon :style="{ color: 'hotpink'}">
组件  textarea 高度动态变化 
1 2 3 4 5 6 7 8 9 @Data public  class  Result  {private  int  height;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  Result getResultCommon (double  result, double  discount, String resultStr, int  height)  {double  afterDis  =  result * discount;Result  calResult  =  new  Result ();0.0D );0.0D );return  calResult;
使用 a-textarea 文本框组件,高度随接收参数值 height 动态变化:(2024/01/14晚)  
 
1 2 3 4 5 6 <a-form-item label="计算过程">
1 2 3 4 5 6 const  result = ref<ResultState >({beforeDis : 0 ,afterDis : 0 ,procedure : "" ,height : 5 
CSS 选择器巩固 1 2 3 4 5 6 7 8 9 Element  leftZhankai  =  doc.getElementById("leftZhankai" );Elements  heads  =  leftZhankai.select(".sons .cont div:nth-of-type(2)" );for  (Element head : heads) {Elements  title  =  head.select(">p:nth-of-type(2)" );"hhh"  + title.text());
熟悉 CSS 选择器 之后,解析 HTML 文档 获取标题、诗人和内容 就很轻松了: 
 
存在多个标签,随机选择五个:(2024/01/16晚)  
 
1 2 0 , 5 );
1 2 3 4 5 6 7 8 9 10 11 12 13 for  (Element item : selectedItems) {Elements  img  =  item.select("> a > img" );String  src  =  "https:"  + img.attr("data-src" );String  title  =  img.attr("title" );Picture  picture  =  new  Picture ();
MarkDown 编辑器 官方文档:bytedance/bytemd: ByteMD v1 repository (github.com) 
1 npm i @bytemd/plugin-highlight @bytemd/plugin-gfm
新建 Markdown 编辑器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <template><Editor  :value ="value"  :plugins ="plugins"  @change ="handleChange"  /> <script  setup  lang ="ts" > import  gfm from  "@bytemd/plugin-gfm" ;import  highlight from  "@bytemd/plugin-highlight" ;import  { Editor  } from  "@bytemd/vue-next" ;import  { withDefaults, defineProps, ref } from  "vue" ;interface Props  {   value : string;   mode?: string;   handleChange : (v: string ) =>  void ; } const  plugins = [  gfm (),   highlight (),    ]; const  value = ref ("" );const  handleChange  = (v: string ) => {  value.value  = v; }; </script > <style > </style > 
在 main.ts 下,引入样式:
1 import "bytemd/dist/index.css" ;
代码编辑器 总结