Vue 前后端实战:组件通信、JWT 登录与接口权限控制

发布时间:2026/10/18 14:54:59

Vue 前后端实战:组件通信、JWT 登录与接口权限控制 一、组件通信组件之间默认拥有独立的数据作用域。父子组件不能直接共享data需要通过明确的通信方式传值。清晰的数据流可以让组件更容易调试也能避免一个组件随意修改另一个组件内部状态。二、父传子props父组件在子组件标签上绑定属性子组件使用props接收。Props 是单向数据流父组件可以更新传入值子组件不应该直接修改 props而应通过事件通知父组件修改源数据。!-- ParentView.vue -- template div classparent h1父组件/h1 Child :namename :is-viptrue / /div /template script import Child from /components/Child.vue export default { name: ParentView, components: { Child }, data() { return { name: 彭于晏 } } } /script!-- components/Child.vue -- template div classchild p姓名{{ name }}/p p v-ifisVip会员用户/p /div /template script export default { name: Child, props: { name: { type: String, required: true }, isVip: { type: Boolean, default: false } } } /scriptHTML 属性使用短横线命名is-vip在 JavaScript 中对应驼峰形式isVip。使用对象形式声明 props 可以增加类型、必填和默认值校验比简单数组更容易维护。三、子传父自定义事件子组件不能直接修改父组件的数据可以通过$emit派发自定义事件并把需要传递的值作为参数。父组件监听事件后更新自己的data。!-- ParentView.vue -- template div p子组件传来的内容{{ message }}/p ChildEditor submit-messagereceiveMessage / /div /template script import ChildEditor from /components/ChildEditor.vue export default { components: { ChildEditor }, data() { return { message: } }, methods: { receiveMessage(value) { this.message value } } } /script!-- ChildEditor.vue -- template div input v-model.trimtext placeholder输入内容 button clicksubmit发送给父组件/button /div /template script export default { data() { return { text: } }, methods: { submit() { this.$emit(submit-message, this.text) } } } /script事件名称需要与父组件监听的名称一致。可以把$emit理解为“子组件发出通知”而不是直接调用父组件方法这样组件之间的依赖更松散。四、ref 与 parentref可以让父组件在挂载后获取 DOM 元素或子组件实例。它适合聚焦输入框、读取 DOM 尺寸、调用子组件公开方法等命令式操作但不应取代 props 和事件这种声明式通信。template div input refsearchInput ChildPanel refchildPanel / button clickoperate执行操作/button /div /template script import ChildPanel from /components/ChildPanel.vue export default { components: { ChildPanel }, methods: { operate() { // 普通标签的 ref 是 DOM 对象。 this.$refs.searchInput.focus() // 组件的 ref 是子组件实例可以调用它公开的方法。 this.$refs.childPanel.changeTitle(父组件设置的标题) } } } /script$refs在mounted之后才可靠可用。子组件中的this.$parent可以取得父组件实例但会造成强耦合实际项目应优先使用 props、事件或状态管理工具。五、Django 跨域与 JWT 登录前端开发服务器和 Django API 常运行在不同端口浏览器会按同源策略拦截跨域请求。Django 可以使用django-cors-headers添加 CORS 响应头。pipinstalldjango-cors-headers djangorestframework-simplejwt# settings.pyINSTALLED_APPS[# ...corsheaders,rest_framework,]MIDDLEWARE[corsheaders.middleware.CorsMiddleware,# ...]# 开发环境可以临时允许前端开发服务器生产环境应列出明确来源。CORS_ALLOWED_ORIGINS[http://localhost:8080,]JWT 登录通常是前端提交用户名密码后端通过 Django Auth 校验成功后签发 access token前端保存 token后续请求在Authorization: Bearer token中携带。不要把密码保存到浏览器或直接拼到 URL 中。1. 自定义登录返回格式# app01/serializers.pyfromrest_framework_simplejwt.serializersimportTokenObtainPairSerializerclassLoginSerializer(TokenObtainPairSerializer):defvalidate(self,attrs):datasuper().validate(attrs)return{code:100,msg:登录成功,access:data[access],refresh:data[refresh],}# settings.pySIMPLE_JWT{TOKEN_OBTAIN_SERIALIZER:app01.serializers.LoginSerializer,}如果项目还需要统一处理异常应保留 HTTP 状态码信息不要把所有失败都返回 200。前端既可以读取业务code也应根据 HTTP 状态码处理未授权和服务器错误。2. 电影接口# app01/views.pyimportjsonfromrest_framework.responseimportResponsefromrest_framework.viewsetsimportViewSetfromrest_framework.decoratorsimportactionclassFilmViewSet(ViewSet):action(methods[GET],detailFalse,url_pathlist)deflist_films(self,request):withopen(films.json,encodingutf-8)asfile:datajson.load(file)returnResponse(data)# urls.pyfromdjango.urlsimportpathfromrest_framework.routersimportSimpleRouterfromrest_framework_simplejwt.viewsimportTokenObtainPairViewfromapp01.serializersimportLoginSerializerfromapp01.viewsimportFilmViewSet routerSimpleRouter()router.register(films,FilmViewSet,basenamefilms)urlpatterns[path(login/,TokenObtainPairView.as_view(serializer_classLoginSerializer)),]urlpatternsrouter.urlsRouter 会根据 ViewSet 自动生成接口路径。实际项目更推荐使用 Serializer 和 ModelViewSet 管理数据库数据而不是在视图中直接读取 JSON 文件。六、Vue 登录与带 Token 请求1. 路由配置// router/index.jsconstroutes[{path:/login,name:login,component:LoginView},{path:/films,name:films,component:FilmView}]2. 登录页面template form submit.preventlogin input v-model.trimusername placeholder用户名 input v-modelpassword typepassword placeholder密码 button :disabledloading{{ loading ? 登录中... : 登录 }}/button p v-iferror{{ error }}/p /form /template script import axios from axios export default { data() { return { username: , password: , loading: false, error: } }, methods: { async login() { this.loading true this.error try { const response await axios.post(http://127.0.0.1:8000/login/, { username: this.username, password: this.password }) if (response.data.code 100) { localStorage.setItem(access, response.data.access) localStorage.setItem(refresh, response.data.refresh) this.$router.push(/films) } else { this.error response.data.msg || 登录失败 } } catch (err) { this.error 用户名或密码错误 } finally { this.loading false } } } } /script示例使用localStorage保存 access token适合课堂演示。生产环境需要根据安全要求评估 XSS、刷新 token、退出登录和存储位置不能盲目把敏感凭证长期保存在浏览器。3. 请求电影数据template div h1最新电影/h1 p v-iferror{{ error }}/p article v-forfilm in films :keyfilm.id h3{{ film.name }}/h3 p{{ film.synopsis }}/p img :srcfilm.poster :altfilm.name width200 /article /div /template script import axios from axios export default { data() { return { films: [], error: } }, async created() { try { const token localStorage.getItem(access) const response await axios.get(http://127.0.0.1:8000/films/list/, { headers: { Authorization: Bearer ${token} } }) this.films response.data.results || response.data } catch (err) { this.error 电影数据加载失败或登录已过期 } } } /script实际项目可以创建 axios 实例和请求拦截器自动附加 token收到 401 时统一清理凭证并跳转登录页避免每个页面重复写请求头。七、scoped 样式在style上添加scoped后Vue 会为当前组件的元素生成特殊属性并把样式选择器转换为只匹配当前组件的形式减少样式互相污染。template h1 classtitle当前组件标题/h1 /template style scoped .title { color: #409eff; } /stylescoped不是安全隔离也不会自动隔离第三方组件内部样式。全局重置样式、主题变量和公共布局可以写在不带scoped的全局样式文件中。八、Element UI 集成Element UI 是面向 Vue 2 的桌面端组件库Vue 3 应使用 Element Plus。Vant 更适合移动端Ant Design Vue 适合企业级后台等场景。选择组件库时要先确认 Vue 版本和目标平台。# Vue 2 项目npminstallelement-ui--save// main.jsimportVuefromvueimportElementUIfromelement-uiimportelement-ui/lib/theme-chalk/index.cssimportAppfrom./App.vueVue.use(ElementUI)newVue({render:hh(App)}).$mount(#app)之后可以按照官方文档使用el-button、el-table、el-form等组件。按需引入可以减少打包体积大型项目还应统一主题和组件使用规范。九、props 的进阶校验简单数组写法适合快速示例正式项目建议使用对象写法声明类型、必填和默认值。validator可以增加自定义校验但它主要用于开发期提示不应替代后端校验。exportdefault{props:{name:{type:String,required:true},count:{type:Number,default:0,validator(value){returnvalue0}},enabled:{type:Boolean,default:false}}}布尔属性、数字属性和对象属性都应按真实数据类型传递。例如:enabledtrue传入布尔值而enabledtrue只是字符串。父组件传递对象时子组件也不应直接修改其内部属性必要时复制为本地数据或通过事件通知父组件。十、总结与练习父传子使用 props子传父使用$emitref和$parent属于命令式访问应谨慎使用。JWT 登录包括认证、签发 token、前端保存和后续请求携带四个步骤token 过期要统一处理。scoped适合组件局部样式Element UI 和 Element Plus 要根据 Vue 版本选择。Props 对象声明可以提供类型、必填、默认值和校验增强组件的可维护性。练习实现一个登录后访问电影列表的 Vue Django 项目并补充退出登录、401 跳转和 token 刷新逻辑。
延伸阅读

更多相关文章

2026/10/17 2:45:35

限流实战:令牌桶与滑动窗口

TL;DR 核心要点速览 GORM是Go最流行的ORM框架 Redis缓存策略:穿透用布隆过滤器,击穿用互斥锁 go-redis/v9支持连接池和管道 Go操作MongoDB用official driver 数据库迁移用goose或migrate工具 本篇是Go数据层模块,含缓存策略实战 摘要:本文详细介绍令牌桶与滑动窗口,涵盖核心原…

2026/10/18 14:53:20

C++手写UDP客户端实战:从socket到超时重传的完整指南

1. 从一个实际需求说起:为什么要手写UDP客户端很多人第一次接触网络编程,都是从TCP开始的。三次握手、可靠传输、面向连接,这些概念听起来就让人安心。但真到了实际项目里,你会发现UDP出现的频率远比想象中高。游戏同步、音视频推…

2026/10/18 14:53:20

高压取电防外破警示装置:技术原理、安装调试与运维实战

线路运维的老哥应该都有过这种经历:凌晨两三点电话响,调度通知某条110千伏线路跳闸,重合闸不成功,强送也不成功。第二天一早带人带着望远镜沿线找故障点,最后发现是附近工地一台吊车起臂时没注意安全距离,碰…

2026/10/18 14:53:20

AI数据中心吉瓦时代:核电压舱,能源竞赛升级

做数据中心基础设施这行,最近两年最直观的一个变化是:大家聊功率的单位,从“兆瓦”直接跳到了“吉瓦”。我前阵子跟几个做算力供应链的朋友通电话,对方张口就是“这期项目规划了1.2吉瓦”,我愣了一下才反应过来&#x…

2026/10/18 14:53:20

cpp算法题目整理——贪心篇2

最短距离 题目描述: 在一条一维的直线上,存在着 n 台显示器和 n 个电源插座。老师给小蓝布置了个任务:负责将每台显示器通过电源线与一个插座相连接(每个插座最多只能给一台显示器供电);同时,…

2026/10/18 14:48:19

Whisper离线部署实战:编译whisper.cpp与量化模型优化指南

简介:一套基于whisper.cpp深度定制的离线语音识别完整工程,面向需要在本地或内网环境部署语音转写能力的开发者、嵌入式及桌面应用工程师。资源包将C推理引擎与Go服务端无缝衔接,通过CGO调用封装,配合预编译的tiny、base、small三…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/18 0:01:50

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑