参考 B 站 --小霖同学-- 的教程入门一下quasar然后我们给示例项目搞个页面。以下是前后端连接大概流程记录。nvm alias default v24.12.0nvm use default把默认node版本切换到这个lts版本因为版本太老可能不行。在合适的位置npm init quasar来创建 quasar项目需要回答项目根目录名称、和vue3有关的配置等等。我们基本用默认选项只是组件选择把状态管理pinia、请求组件axios、i18n 和代码 linting 都选上我们用 JavaScript 不用 TypeScript。建完项目根据提示安装完依赖用 VSCode 添加项目根目录到工作区准备工作差不多完成了。默认用的是 vite 而非 webpack务必注意两个打包工具对应需要的在配置文件中的格式不一样可以从quasar官网文档查看各自不同cd PRJNAME, npx quasar dev启动本地web服务器就可以看到默认页面了。我们先观察一下项目目录结构src/router/routes.js 是项目包含的路由只有 / 和 404。/ 对应的组件是布局模板layouts/MainLayout.vue子组件包含页面pages/IndexPage.vue子组件对应 path 为空也就是布局模板里面的router-view /默认渲染这个子组件其实就是首页index。这里的 layouts 和 pages 划分和通常的想法一样也就是 pages的东西是嵌入layouts的一部分主体部分。参考 https://blog.csdn.net/weixin_43815091/article/details/124951953 修改api 的基础URLquasar.config.js 修改 axios基础url用相对路径如果用协议号http开始的绝对路径开发服务器就不会捕获并执行proxy代理。另外我们路径额外加一个/api前缀并在proxy重写规则中去掉如果用根目录/配置会复杂一些。使用相对路径后代理proxy会过滤请求对于匹配上的请求进行代理转发即请求不再是浏览器到后端服务器变成前端服务器到后端服务器这样就避开了跨域问题build: { ..................... env: { apiBaseUrl: ctx.dev ? /api : http://localhost:8000, }, ..................... devServer: { // https: true, open: true, // opens browser window automatically proxy: { /api: { target: http://localhost:8000, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ), }, }, },修改 boot/axios.js api 是一个axios实例const api axios.create({ baseURL: process.env.apiBaseUrl, timeout: 30000, })参考 https://help.crudapi.cn/guide.html 源码网址 https://gitee.com/crudapi/crudapi-admin-web/blob/master/src/api/user.js我们新建 src/api 目录差不多就是把 GoFrame 的 *.http 文件中的各API请求包装一下方便使用。文件 src/api/post.js 如下其中的Promise使用了 async/await 语法糖而非 then/catchimport { api } from boot/axios // axios 参考 https://axios-http.com/zh/docs/handling_errors const post { index: async function (params) { try { const response await api.get(/post/index, { params: params, }) console.log(response.data) return response.data } catch (error) { if (error.response) { // 请求成功发出且服务器也响应了状态码但状态代码超出了 2xx 的范围 console.log(error.response.data) console.log(error.response.status) console.log(error.response.headers) } else if (error.request) { // 请求已经成功发起但没有收到响应 // error.request 在浏览器中是 XMLHttpRequest 的实例 // 而在node.js中是 http.ClientRequest 的实例 console.log(error.request) } else { // 发送请求时出了点问题 console.log(Error, error.message) } console.log(error.config) } }, create: async function (params) { try { const response await api.post(/post/create, params) console.log(response.data) return response.data } catch (error) { console.log(error) } }, update: async function (id, params) { try { const response await api.post(/post/update/ id, params) console.log(response.data) return response.data } catch (error) { console.log(error) } }, view: async function (id) { try { const response await api.get(/post/view/ id) console.log(response.data) return response.data } catch (error) { console.log(error) } }, delete: async function (id) { try { const response await api.post(/post/delete/ id) console.log(response.data) return response.data } catch (error) { console.log(error) } }, } export { post }创建页面 src/pages/PostPage.vue 复习一下 script setup语法糖ref响应对象创建生命周期钩子 onMounted异步函数使用quasar表格基本使用template q-page classflex flex-center div classq-pa-md q-table title博客列表 :columnscolumns :rowsrows row-keyid / /div /q-page /template script setup import { post } from src/api/post import { onMounted, ref } from vue const columns [ { name: id, label: ID, field: id, }, { name: title, label: 标题, field: title, }, { name: content, label: 标题, field: content, format: (val) { return val.substr(0, 20) }, }, { name: tags, label: 标签, field: tags, }, { name: status, label: 状态, field: status, }, { name: createdAt, label: 创建时间, field: createdAt, sortable: true, }, { name: updatedAt, label: 更新时间, field: updatedAt, }, { name: authorId, label: 作者, field: authorId, }, ] const rows ref([]) onMounted(async () { let res await post.index() rows.value res.data.list }) /script路由 src/router/routes.js 添加const routes [ { path: /, component: () import(layouts/MainLayout.vue), children: [ { path: , component: () import(pages/IndexPage.vue) }, { path: /post, component: () import(pages/PostPage.vue) }, { path: /comment, component: () import(pages/CommentPage.vue) }, ], }, .........................布局模板 src/layouts/MainLayout.vue中的链接改掉const linksList [ { title: 博客, caption: 我的各种博客, icon: school, link: #/post, }, { title: 评论, caption: 用户浏览器后评论, icon: chat, link: #/comment, }, ...................然后 npx quasar dev 启动本地服务器浏览器自动打开点击“博客”菜单导航到 #/post主视图中就用表格显示了博客。不过表格右下角关于页的提示信息默认是英文的因为quasar框架的组件默认用英文我么改一下配置文件 quasar.config.js 如果要编写自己的支持i18n的组件可以参考https://quasar.dev/options/app-internationalizationframework: { config: {}, lang: zh-CN,作为GUI库我们大部分时候关心的是布局、可视组件、样式风格分别对应官网文档 Layout and Grid、Vue Components、Style and Identity。我们大概了解一下有哪些可视组件Ajax Bar 异步网络后台请求时我们可以用这个让页面边缘显示进度Avatar主要用于头像也可用作展示性小图标Badge徽章主要是突出显示吸引注意的文字比如待阅读的数量Banner旗帜条用于突出显示信息或者可选操作如“登录成功”Bar贴顶条用来容纳菜单最大化、最小化、关闭等按钮Breadcrumbs面包屑可以让人知道当前导航位置Button、Button Group、Button Dropdown按钮是最常用的可视化组件Card卡片这是常见的信息展示容器Carousel转盘可以在相对有限的空间用幻灯方式展示更多信息Chat Message聊天消息Chip一个界面块用来容纳头像、文本、图标等东西Circular Progress彩色的圆形进度指示器Color Picker颜色选择器Dialog对话框Editor编辑框Expansion Item可扩展项初始折叠点击后可展示隐藏的内容Floating Action Button悬浮的动作按钮在悬浮在主体内容的上面常常显示一个小圆圈点击可以弹出更多操作按钮表单组件 Input Textfield、Select、File picker、Form、Field装饰器、Radio、Checkbox、Toggle开关指示、Button Toggle选中指示、Option Group用于分组radio/checkbox/toggle、Slider滑动条表示数量、Ranger滑动条指示范围、Time Picker、Date PickerIcon方便在其他组件中嵌入图标Img方便嵌入图片有加载进度指示Infinite Scroll去穷滚动让用户滚动时加载新的内容Inner Loading长加载耗时的时候显示动画让用户可以看到应用在后台进行加载工作Intersection和 Intersection quasar指令相关主要是DOM对象进入和移出视口过程中能节约内存Knob圆形的数量展示可以用鼠标或触控改变它的值例如用于音量控制Linear Progress彩色的加载条用来提醒用户某个动作在背后发生List and List Items用来进行列表展示列表项可以是很复杂的Markup Table是对table的包装呈现为Material风格只用于少量简单的表格数据展示需要复杂分页、排序、过滤功能的表格应该用 QTable组件Menu菜单Resize Observer、Scroll Observer尺寸改变、滚动时激发相应消息Pagination分页组件Parallax视差滚动滚动时背景图片滚动略慢造成一定视觉效果Popup Edit弹出式在地编辑即点击要编辑目标编辑器就在那个位置打开Popup Proxy可以将弹出内容如QMenu、QTooltip、QDialog、自定义浮层、上下文菜单等与目标组件按钮、输入框等关联显示Pull to refresh下拉刷新Rating评级Responsive强制让内容保持纵横比Scroll Area可滚动区域可以有自己的滚动条而不是浏览器提供的Separator分隔条Skeleton动态效果占位符用于加载完之前显示Slide Item是列表项 QItem的增强版可以向左、向右、向下、向上拖拉以便触发特定动作Slide Transition作用于单个DOM的滑动过渡效果Space填充弹性盒子所有可用的空间quasar组件都是弹性盒子Spinners视觉特性让用户感觉系统持续在工作Splitter把容器分隔成可拖拉改变大小的部分Stepper用于展示步骤让人知道当前做了哪几步还剩几步Table表格Tabs选项页Tab Panels选项面板和Tabs有点像但它针对面板而非整页主要是为了在有限空间显示更多信息Timeline时间线Toolbar工具条最常用于页头和页脚Tooltip工具提示Tree树形结构用来展示层次数据Uploader对于简单上传一个不大的文件QFile更简单QUploader主要是复杂的控制例如多个文件添加头部Video方便嵌入视频Virtual Scroll只显示长列表中部分数据当用户在容器内滚动时更新可视数据这些组件可以慢慢学路由细节也可以慢慢学还有两个问题1、如何用pinia实现状态管理哪些东西需要进行状态管理2、登录获取令牌、在请求中携带令牌和令牌超时前刷新问题