公司动态
Vue2-week3
Vue2 插槽 (slot) 笔记整理插槽作用实现父组件向子组件指定位置插入 HTML 结构属于组件通信父组件 → 子组件。三种插槽默认插槽、具名插槽、作用域插槽1. 默认插槽没有名字的slot父组件传入的内容会填充到子组件 slot 位置 如果父组件不传内容则显示slot标签内部写的默认后备内容。子组件 Category.vuetemplate div classcategory h3分类标题/h3 !-- 插槽位置父组件内容放这里没传就显示“暂无内容” -- slot暂无内容/slot /div /template script export default { name:Category } /script父组件 App.vue 使用template div Category !-- 这里的html会塞进子组件slot里面 -- div我是父组件传进来的内容/div /Category /div /template2. 具名插槽name当子组件有多个插槽位置给 slot 设置name名字父组件通过名字匹配对应插槽。Vue2 语法旧写法slot名字新写法v-slot:名字只能写在template标签上子组件 Category.vuetemplate div slot namecenter中间默认内容/slot slot namefooter底部默认内容/slot /div /template父组件Category !-- 旧语法 slotcenter -- template slotcenter p这是中间区域/p /template !-- 新语法 v-slot:footer -- template v-slot:footer p这是底部区域/p /template /Category简写v-slot:footer可以简写为#footer→template #footer3. 作用域插槽重点难点核心理解数据在子组件渲染什么样式 / 结构由父组件决定。 子组件把自己的数据绑定到 slot 属性上传给父组件父组件接收数据自定义 html 结构。普通插槽数据来自父组件子组件只负责占位作用域插槽数据在子组件把数据抛给父组件父组件决定长什么样子Vue2 接收插槽数据两种语法scopexxx旧版slot‑scopexxxVue2 推荐写法子组件 Category.vue数据在这里template div !-- :games把子组件数据抛出去给父组件 -- slot :gamesgames/slot /div /template script export default { name:Category, data() { return { games:[红色警戒,穿越火线,劲舞团,超级玛丽] } } } /script父组件 App.vue接收数据自定义渲染结构template div !-- 第一种用法渲染ul列表 -- Category template slot-scopescopeData !-- scopeData 是子组件slot传过来的所有对象scopeData.games拿到数组 -- ul li v-forg in scopeData.games :keyg{{g}}/li /ul /template /Category !-- 第二种用法同样子组件数据父组件渲染成h4标题 -- Category template slot-scopescopeData h4 v-forg in scopeData.games :keyg{{g}}/h4 /template /Category /div /template对象解构写法简写常用Category template slot-scope{games} span v-forg in games :keyg{{g}}/span /template /Category插槽对比总结表表格插槽类型使用场景关键点默认插槽子组件只有一处需要填充内容slot/slot父组件直接写标签具名插槽子组件多处位置区分不同区域slot namexxx父组件 template 指定名字作用域插槽数据在子组件结构父组件定子组件slot :数据名子组件数据父组件slot‑scope接收易错点具名插槽v‑slot只能写在template标签不能直接写 div作用域插槽数据源头是子组件不要在父组件 data 定义这份数据Vue3 废弃了slot、slot‑scope语法全部统一v‑slot这份是 Vue2 写法。Vue2 Vuex 核心笔记梳理Vuex 是 Vue 的集中式状态管理插件实现任意组件之间共享数据通信。1. 概念作用集中管理多个组件共享的数据支持读、写操作。使用场景多个组件需要共用一份数据。通信范围任意组件之间。2. 搭建 Vuex 环境① 创建src/store/index.jsimport Vue from vue import Vuex from vuex Vue.use(Vuex) // actions处理业务、异步逻辑ajax、定时器不能直接改state const actions {} // mutations唯一可以修改state数据的地方 const mutations {} // state存放共享的状态数据 const state {} export default new Vuex.Store({ actions, mutations, state })② main.js 注册 storeimport Vue from vue import App from ./App.vue import store from ./store new Vue({ el:#app, render:hh(App), store // vm身上就有 $store })3. 基础使用store/index.jsimport Vue from vue import Vuex from vuex Vue.use(Vuex) const actions { jia(context,value){ // context是小型store调用commit交给mutations context.commit(JIA,value) } } const mutations { JIA(state,value){ state.sum value } } const state { sum:0 } export default new Vuex.Store({ actions, mutations, state })组件内操作读取 state 数据$store.state.sum修改数据两种写法有异步 / 业务逻辑this.$store.dispatch(jia, 5)→ 走 actions → commit 到 mutations无异步逻辑可以跳过 actions 直接 committhis.$store.commit(JIA,5)✨流程总结 组件dispatch→actions异步、判断 →commit→mutations修改state→ 页面响应式更新4. getters对 state 数据做计算加工相当于 store 里面的计算属性不修改 state只做返回加工后结果。const getters { bigSum(state){ return state.sum * 10 } } export default new Vuex.Store({ actions,mutations,state,getters })组件读取$store.getters.bigSum5. 四个 map 辅助方法简化代码写在 computed /methods需要先导入import {mapState,mapGetters,mapActions,mapMutations} from vuexmapState映射 state 数据 → 计算属性 computedcomputed:{ // 对象写法 ...mapState({sum:sum,school:school}), // 数组写法名字完全一致时用 ...mapState([sum,school]) }mapGetters映射 getters → 计算属性 computedcomputed:{ ...mapGetters({bigSum:bigSum}), ...mapGetters([bigSum]) }mapActions生成 dispatch 方法 → methods用来调用 actions传参要在模板事件上传递methods:{ // 对象 ...mapActions({incrementOdd:jiaOdd}), //数组 ...mapActions([jiaOdd]) }mapMutations生成 commit 方法 → methods用来直接调用 mutations同样参数在模板传。methods:{ ...mapMutations({increment:JIA}), ...mapMutations([JIA]) }⚠️重点坑mapActions、mapMutations 自动生成的函数如果需要传参要在模板clickincrement(5)传不写参数拿到的是事件对象。6. 模块化与命名空间 modules目的拆分 store代码好维护分模块管理不同业务的数据。必须写namespaced:true开启命名空间否则 map 方法识别不到模块// 模块1countAbout const countAbout { namespaced:true, state:{sum:0}, mutations:{}, actions:{}, getters:{ bigSum(state){return state.sum*10} } } //模块2personAbout const personAbout { namespaced:true, state:{ list:[] }, mutations:{}, actions:{} } export default new Vuex.Store({ modules:{ countAbout, personAbout } })开启命名空间之后组件用法读取 state//原生写法 this.$store.state.countAbout.sum //mapState第一个参数写模块名 ...mapState(countAbout,[sum])读取 getters//原生 this.$store.getters[countAbout/bigSum] //mapGetters ...mapGetters(countAbout,[bigSum])dispatch 调用 actions//原生 this.$store.dispatch(countAbout/jiaOdd, 3) //mapActions第一个参数模块名 ...mapActions(countAbout,{incrementOdd:jiaOdd})commit 调用 mutations//原生 this.$store.commit(countAbout/JIA,5) //mapMutations ...mapMutations(countAbout,{increment:JIA})Vuex 核心思维导图总结表格对象作用能不能修改 statestate存放共享原始数据❌不能直接改actions处理异步、业务判断❌不能直接改调用 commitmutations唯一修改 state✅允许修改 stategettersstate 的加工计算只读❌只读不能改数据高频易错点mutations 里面只能写同步代码异步定时器、axios写在 actions模块化忘记写namespaced:truemapState/mapActions 全部失效。mapActions/mapMutations 传参不要写在 methods 函数里面要在模板事件传参。Vue2 用vuex3Vue3 用vuex4版本不匹配会报错。Vue‑Router 完整笔记总结Vue2 vue‑router3核心概念route路由key(路径) → value(组件)的映射规则router路由器管理所有 route 的实例整个项目只有一个 router1. 基础使用步骤安装npm i vue-router3Vue2 必须用 3 版本注册插件Vue.use(VueRouter)新建router/index.js配置routes数组导出 router 实例在main.js引入 router挂载到 new Vue 中页面router-link做导航切换router-view是组件渲染出口 相当于slot插槽使用!--导航active-class设置激活高亮类名-- router-link active-classactive to/aboutAbout/router-link !--组件显示位置-- router-view/router-view注意点路由组件放pages文件夹普通组件放components路由切换时组件默认销毁需要保留状态用keep‑alive缓存$route当前路由信息对象path、query、params、meta 等每个组件都有$router路由器实例负责跳转 push/replace/go全局唯一2. 多级路由children子路由path不要加/写相对路径注意注意跳转to必须写完整路径routes:[ { path:/home, component:Home, children:[ { path:news, component:News }, //不能写 /news { path:message, component:Message } ] } ]router-link to/home/news新闻/router-link3. 路由传参两种方式✅ query 参数url?xxxyyy传参!--对象写法path/name都可以-- router-link :to{ path:/home/message/detail, query:{id:666,title:hello} }跳转/router-link获取$route.query.id✅ params 参数路径占位符/detail/:id/:title⚠️重点坑对象写法传 params不能写 path只能用 name路由配置占位符注意 路由命名的名字及name{ name:detail, path:detail/:id/:title, component:Detail }传递!-- 跳转路由并携带params参数to的对象写法 -- router-link :to{ name:xiangqing, params:{ id:m.id, title:m.title } } {{m.title}} /router-linkrouter-link :to{ name:detail, //必须name写path params失效 params:{id:666,title:hello} }跳转/router-link获取$route.params.id4. props 配置简化接收路由参数写在路由规则里面3 种写法{ name:xiangqing, path:detail/:id, component:Detail, //写法1对象写死静态数据很少用 // props:{a:100} //写法2布尔true → 把params参数传给组件props 没什么大用 // props:true //写法3函数可以拿query/params返回对象传给组件props props($route){ return { id:$route.query.id, title:$route.query.title } } props({query}){ return { id:query.id, title:query.title } } props({query{id,title}){ return { id, title } } }组件直接用props:[id,title]接收不用写$route.xxx解耦组件。5. replace 属性控制浏览器历史默认push追加历史记录可以回退replace替换当前历史记录不能回退到上一页router-link replace to/aboutAbout/router-link6. 编程式导航JS 跳转不用 router‑linkthis.$router调用 API//push追加历史 this.$router.push({ name:xiangqing, params:{id:1,title:hi} }) //replace替换历史 this.$router.replace({ name:xiangqing, query:{id:2} }) this.$router.back() //后退 this.$router.forward() //前进 this.$router.go(n) //n正数前进负数后退7. keep‑alive 缓存路由组件路由切换默认销毁组件缓存后组件不销毁保留表单输入、滚动位置!--include写组件名只缓存指定组件不写include缓存全部路由组件-- //单个// keep-alive includeNews router-view/router-view /keep-alive //多个需要解析模版// keep-alive :include[News,Message] router-view/router-view /keep-alive路由专属生命周期钩子配合 keep‑aliveactivated组件被激活显示触发deactivated组件失活隐藏触发只有被keep‑alive缓存的路由组件才会触发这两个钩子8. 路由守卫权限控制①全局守卫写在 router/index.jsbeforeEach afterEach保护路由放在路由暴露之前 所有路由切换时使用路由源信息程序员校验自定义属性 配置到meta里边 meta时对象//前置守卫路由切换【之前】执行权限校验最常用 router.beforeEach((to,from,next){ //to:要去往的路由from离开的路由next()放行 if(to.meta.isAuth){ //meta元信息标记该路由需要鉴权 if(localStorage.getItem(school) atguigu){ next() //放行 }else{ alert(没有权限) // next({name:home}) //强制跳转 } }else{ next() //不需要权限直接放行 } }) //后置守卫路由切换【完成之后】没有next适合改网页标题 前置路由不通过时名字title不变 router.afterEach((to,from){ document.title to.meta.title || 我的网站 })②独享守卫写在单个路由规则内只针对当前路由beforeEnter{ path:/about, component:About, beforeEnter(to,from,next){ //进入该路由前校验权限参数用法和beforeEach完全一样 } }③组件内守卫写在组件 script 中beforeRouteEnter beforeRouteLeaveexport default { //通过路由进入当前组件触发 beforeRouteEnter(to,from,next){}, //离开当前组件触发 beforeRouteLeave(to,from,next){} }执行顺序beforeEach(全局前置)→beforeEnter(独享)→beforeRouteEnter(组件内进入)→组件挂载 →afterEach(全局后置)什么叫 “通过路由进入当前组件”简单说浏览器地址栏发生路由跳转路由规则匹配到这个组件把这个组件渲染出来就叫 “通过路由进入组件”。✅会触发 beforeRouteEnter 的情况通过路由进入点击router-link to/myPage跳转来到这个组件页面this.$router.push(/myPage)/this.$router.replace()编程式导航跳转过来浏览器输入 URL 地址、刷新页面地址匹配该路由加载组件本质vue‑router 路由系统把组件挂载渲染出来这就是 “通过路由进入”。❌不会触发 beforeRouteEnter 的情况不是路由进入组件 A 在模板里直接写MyComponent /标签引入组件父子组件嵌套直接标签使用。这种只是普通组件渲染不走路由不会执行 beforeRouteEnter。举例子 路由配置routes:[ { path:/demo, component: Demo } ]访问/demo→ 路由匹配 Demo 组件 →通过路由进入→触发beforeRouteEnter在别的组件里面写Demo /直接把 Demo 嵌在页面里URL 地址没变只是普通组件复用 →不触发 beforeRouteEnter再结合 beforeRouteEnter 的特点beforeRouteEnter只有路由第一次渲染这个组件的时候执行。 补充一个容易混淆场景 如果组件已经显示只是路由参数改变比如/demo/1→/demo/2复用同一个 Demo 组件组件没有销毁重建。✅不会执行beforeRouteEnter不是 “进入新组件”组件实例已经存在✅此时触发的是beforeRouteUpdate组件内更新守卫通俗大白话总结“通过路由进入” 靠 URL 地址变化vue-router 把组件加载显示出来。 不是靠别的组件标签直接引用。配套理解 beforeRouteLeave“离开当前组件”路由要跳转到别的地址当前组件会被销毁卸载就触发beforeRouteLeave。 比如你在/demo页面点链接跳到/home此时要把 Demo 组件销毁触发离开守卫。小坑如果只是弹窗、v‑if 隐藏组件URL 没变没有发生路由跳转beforeRouteLeave不会执行。Vue 组件内路由守卫写在组件script的导出对象里面属于组件自己的路由钩子只对当前这个组件生效。两个钩子beforeRouteEnter(to, from, next)触发时机即将通过路由进入该组件之前⚠️重点此时组件实例this还没有创建拿不到 this 如果想要访问组件实例要在next回调里面拿beforeRouteEnter(to,from,next){ next(vm{ // vm 就是当前组件的this实例 }) }beforeRouteLeave(to, from, next)触发时机离开当前组件跳转到别的路由之前✅可以直接使用this常见用途离开前确认是否保存表单、提示用户是否放弃编辑。参数说明三个守卫参数都一样to目标路由对象要去到哪里from源路由对象从哪里来next路由放行函数必须调用next()正常放行跳转next(false)取消跳转留在当前页next(/xxx)强制跳转到指定路由完整示例export default { // 进入组件前触发this不可用 beforeRouteEnter(to, from, next) { console.log(准备进入组件,to,from) next() //放行 }, // 离开组件触发可以访问this beforeRouteLeave(to, from, next) { console.log(准备离开组件,to,from) //示例表单未保存提示 if(this.isEdit){ if(confirm(表单还没保存确定离开吗)){ next() }else{ next(false) //阻止离开 } }else{ next() } } }补充还有一个组件内守卫beforeRouteUpdate当复用组件路由参数变化时触发例如/user/1→/user/2同一个组件仅 id 改变组件不会销毁重建beforeRouteUpdate(to,from,next){ // 可以拿到this在这里重新获取数据 next() }三类路由守卫简单区分表格守卫类型写在哪里全局守卫router/index.js 路由实例上beforeEach路由独享守卫routes 数组的每一项路由配置里面组件内守卫组件 script export default 对象内部本图讲的易错点beforeRouteEnter不能直接用 this组件还没创建只能next(vm{})回调访问实例。所有路由守卫一定要调用 next ()不写页面会卡住不动。beforeRouteLeave适合做离开确认比如表单页面防止误跳转丢失输入内容。9. 两种工作模式const router new VueRouter({ mode:history, //hash / history routes:[...] })hash 模式默认url 带## 后面内容不会发给后端兼容性好缺点地址带 #不好看history 模式url 干净无#上线后端必须配置否则刷新页面出现 404Vue2 项目上线打包部署完整流程开发写完代码本地跑没问题要给外网用户访问分两步打包 → 部署一、打包生成上线文件Vue‑cli 创建的 Vue2 项目执行打包命令npm run build执行完成项目根目录会多出一个dist文件夹✨dist 就是上线需要的全部文件html、css、js、图片资源。本地开发的 src 源代码不需要上传服务器常见打包配置问题重点路由模式如果你的路由用了mode:history去掉 url 里 #号上线服务器必须额外配置否则刷新页面 404// router/index.js const router new VueRouter({ mode:history, // history模式上线要服务器配置 routes:[...] })mode:hashurl 带 #不需要服务器额外配置打包直接丢服务器就能跑简单省事。二、dist 文件夹部署3 种常用方式方式 1部署到 Nginx 服务器公司后端服务器最常用把 dist 里面全部文件上传到 nginx 网页目录。history 模式 nginx 关键配置解决刷新 404location / { root /usr/share/nginx/html; #放dist文件的目录 index index.html; try_files $uri $uri/ /index.html; #核心history模式必须加 }修改配置后重启 nginx。方式 2部署宝塔面板新手虚拟主机网站根目录把 dist 内所有文件上传进去如果是 history 模式网站设置 →伪静态选择 vue 历史模式规则。方式 3静态托管免费如 vercel、gitee pages、github pages适合练习项目不需要买服务器。注意github pages 只支持 hash 模式history 模式会刷新 404。三、上线常见坑汇总❗打包后页面空白原因vue.config.js中 publicPath 路径错误。// vue.config.js module.exports{ publicPath:./ //写相对路径不要写 / }改完必须重新执行npm run build重新打包❗刷新页面 404路由 mode:history服务器没有配置重定向到 index.html。临时快速解决改成mode:hashurl 出现 #号不用服务器配置。❗接口请求跨域注意vue.config.js 的 devServer 代理只在本地开发生效打包上线不生效上线不能靠前端代理两种方案 ①后端配置 CORS 跨域 ②nginx 反向代理。❗静态图片打包丢失尽量用require()引入本地图片不要直接写相对路径。四、完整上线简易步骤修改vue.config.js设置publicPath: ./确认路由模式不想折腾服务器就用mode:hashnpm run build生成 dist将 dist 文件夹里面所有文件上传服务器网站根目录访问域名测试。补充开发环境 vs 生产环境开发环境npm run serve本地电脑运行有热更新devServer 代理生效生产环境上线npm run build输出 dist没有 devServer 代理。小提示上线前记得把 console.log 调试日志清理掉。高频易错点汇总子路由 children 里面 path 不要写开头/跳转 to 写完整绝对路径params 对象跳转只能用 name不能 pathpath 写了 params 会丢失区分$route路由信息读参数和$router路由器做跳转keep‑alive 的include填组件 name 属性不是路由 path守卫一定要调用next()不调用页面卡住不动history 模式上线后端配置解决刷新 404独享守卫beforeEnter写在路由配置不是组件里面Vue2 对应 vue‑router 版本 3Vue3 对应 vue‑router 版本 4免费开源组件库带官方网址MIT 协议可商用️ PC 网页中后台管理系统Element Plus饿了么Vue3 后台首选 官网https://element-plus.org/zh-CN/中文文档完善表单、表格、弹窗全套组件国内项目用的最多。Ant Design Vue阿里 官网https://antdv.com/企业级组件库组件数量多适合大型后台系统。Arco Design Vue字节跳动开源 官网https://arco.design/vue现代 UI 风格主题定制强大大厂广泛使用。TDesign‑Vue腾讯开源 官网https://tdesign.tencent.com/vue/overview支持暗色模式同时覆盖 PC 和移动端。Naive UI官网https://www.naiveui.com/zh-CN/light全 TS 编写界面简约清爽自定义主题方便。移动端 H5手机网页Vant有赞移动端首选 官网https://vant-ui.github.io/vant/#/zh-CN电商 H5 神器轻量下拉刷新、轮播、表单组件齐全。NutUI京东开源 官网https://nutui.jd.com/#/电商风格支持 H5、小程序多端适配。跨框架组件库不绑定 Vue/ReactdaisyUI基于 Tailwind CSS 官网https://daisyui.com/纯 CSS 组件复制 class 即可使用不限前端框架。FlowbiteTailwind 生态 官网https://flowbite.com/大量现成表单、卡片、弹窗模板。专项功能开源库ECharts百度数据可视化图表 官网https://echarts.apache.org/zh/index.html折线图、柱状图、饼图、大屏可视化。wangEditor轻量富文本编辑器 官网https://www.wangeditor.com/中文友好后台文章编辑常用。Quill富文本编辑器 官网https://quilljs.com/可扩展性很强的开源编辑器。React 栈常用Ant DesignReact 企业后台 官网https://ant.design/Mantine现代 React 组件库 官网https://mantine.dev/选型快速参考后台管理系统 →Element Plus手机 H5 电商页面 →VantTS 项目简约风格 →Naive UI图表大屏可视化 →ECharts提示全部为 MIT 协议可以商用修改源码不需要公开自己业务代码。项目不要混用多个 UI 库会出现样式冲突。