Vue Router路由库的使用:
在router/index.ts配置路由,能根据url地址在前端路由而不需要请求后端刷新
<a-layout-content class="content"> <router-view /> </a-layout-content>
组件化开发
Vue是基于组件化的,所以小的组件例如顶部栏,我们都需要放在components目录下,
<RouterLink to="/">Go to Home</RouterLink>
// RouoterLink 也是跳转链接,但是RouterLink使用的是路由
RouterView组件可以使Vue根据路由渲染对应的路由组件
关联路径和路由组件
const routes = { path: '/', component: HomeView }, { path: '/about', component: AboutView },
const router = createRouter({ history: createMemoryHistory(), routes, })
// 使用createRouter创建真正路由对象(路由器实例)
history 选项控制了路由和 URL 路径是如何双向映射的
createMemoryHistory(),它会完全忽略浏览器的 URL 而使用其自己内部的 URL。
通常,你应该使用 createWebHistory() 或 createWebHashHistory()
注册路由器插件
一旦创建了我们的路由器实例 ,我们就需要将其注册为插件,这一步骤可以通过调用 use() 来完成。
createApp(App).use(router).mount('#app')
和大多数的 Vue 插件一样,use() 需要在 mount() 之前调用。
如果你好奇这个插件做了什么,它的职责包括:
-
全局注册
RouterView和RouterLink组件。 -
添加全局
$router和$route属性。 -
启用
useRouter()和useRoute()组合式函数。 -
触发路由器解析初始路由。
Vue Router 可以使用组合式 API 或选项式 API 。在必要时,示例将会同时使用两种风格,组合式 API 示例通常会使用 <script setup>,而不是显式的 setup 函数。
Vue的h函数
h 在这里怎么用
h 是 Vue 提供的函数,用法是:
h(组件或标签, 属性对象, 子内容)
这里有两种用法:
用法 1:渲染图标组件
icon: () => h(HomeOutlined),
-
HomeOutlined是从@ant-design/icons-vue导入的图标组件 -
h(HomeOutlined)的意思就是:创建一个HomeOutlined图标的虚拟节点 -
外面套了一个
() =>是因为 Ant Design 的菜单icon属性要求传一个函数,调用时才渲染
相当于在模板里写:
<HomeOutlined />
router.push 是异步的!
router.push('/home')
// 这行代码只是"发出请求",路由还没真正跳转完
// 下一行代码执行时,路由可能还在跳转中...
doMenuClick({ key }: { key: string })
🧱 前置理解
这里用了 TypeScript 的解构 + 类型注解,看起来有点复杂,拆开来看:
// 原始写法(不解构)
const doMenuClick = (item: { key: string }) => {
router.push({ path: item.key })
}
// 解构写法(等价)
const doMenuClick = ({ key }: { key: string }) => {
router.push({ path: key })
}
{ key } 从哪来?
这个函数是给 Ant Design Vue 的 <a-menu> 用的,当你点击菜单项时,它会自动把 { key, keyPath, item } 这个对象传进来:
ref 包裹的变量,在 <script> 里读写必须用 .value。
ES6 Promise
通过Promise的改写上面的代码
doSomething().then(function(result) {
return doSomethingElse(result);
})
.then(function(newResult) {
return doThirdThing(newResult);
})
.then(function(finalResult) {
console.log('得到最终结果: ' + finalResult);
})
.catch(failureCallback);
瞬间感受到promise解决异步操作的优点:
-
链式操作减低了编码难度
-
代码可读性明显增强
下面我们正式来认识promise:
#状态
promise对象仅有三种状态
-
pending(进行中) -
fulfilled(已成功) -
rejected(已失败)
#特点
-
对象的状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态
-
一旦状态改变(从
pending变为fulfilled和从pending变为rejected),就不会再变,任何时候都可以得到这个结果
二、用法
Promise对象是一个构造函数,用来生成Promise实例
const promise = new Promise(function(resolve, reject) {});
Promise`构造函数接受一个函数作为参数,该函数的两个参数分别是`resolve`和`reject
-
resolve函数的作用是,将Promise对象的状态从"未完成"变为"成功" -
reject函数的作用是,将Promise对象的状态从"未完成"变为"失败"
实例方法
Promise构建出来的实例存在以下方法:
-
then()
-
catch()
-
finally()
#then()
then是实例状态发生改变时的回调函数,第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数
then方法返回的是一个新的Promise实例,也就是promise能链式书写的原因
getJSON("/posts.json").then(function(json) {
return json.post;
}).then(function(post) {
// ...
});
全局状态管理
pinia是一个主流的状态管理库,不只局限在某个页面中
例如适合作为全局状态管理的数据:已登录用户信息(每个页面几乎都要用)
Store 是什么?
Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态 。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念 ,state、getter 和 action,我们可以假设这些概念相当于组件中的 data、 computed 和 methods。
跨域问题
在后端使用docker-compose部署完毕之后,前端仍然出现网络访问错误,经过claude解决
问题根因和解决方案总结:
根因 :前端 http://localhost:8081 直接请求 http://localhost:8080,触发浏览器 CORS 跨域拦截,后端返回 Invalid CORS request,Axios 拿不到响应就报 Network Error。
解决方式:
-
vue.config.js加了 devServer 代理,所有/api/*请求由 webpack 开发服务器转发到http://localhost:8080 -
request.ts的baseURL改为/,请求走同源,浏览器不会触发 CORS
重启开发服务器后生效(代理配置需要重启才能读取):
所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
npm run serve
重启后请求路径变为:浏览器 → localhost:8081/api/user/current → 代理转发 → localhost:8080/api/user/current,CORS 问题消失。
注意:这个方案只在开发环境有效
devServer.proxy 是 Vue CLI 开发服务器提供的功能,打包上线后就没有了。
生产环境通常需要后端配置 CORS 响应头 ,或者用 Nginx 做反向代理来解决跨域。
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
"/api": {
target: "http://localhost:8080",
changeOrigin: true,
},
},
},
});
响应式变量接受表单输入的值
如何知道是哪个用户登录了?
javaweb 这一块的知识
-
连接服务器端后,得到一个 session 状态(匿名会话),返回给前端
-
登录成功后,得到了登录成功的 session,并且给该session设置一些值(比如用户信息),返回给前端一个设置 cookie 的 "命令"
-
前端接收到后端的命令后,设置 cookie,保存到浏览器内
-
前端再次请求后端的时候(相同的域名),在请求头中带上cookie去请求
-
后端拿到前端传来的 cookie,找到对应的 session
-
后端从 session 中可以取出基于该 session 存储的变量(用户的登录信息、登录名)