当前位置: 首页 > article >正文

18前端项目----Vue项目收尾优化|重要知识

收尾/知识点汇总

  • 项目收尾
    • 二级路由
    • 未登录全局路由守卫
    • 路由独享守卫
    • 图片懒加载
    • 路由懒加载
    • 打包上线
  • 重要知识点汇总
    • 组件通信方式
      • 1. props
      • 2. 自定义事件
      • 3. 全局事件总线
      • 4. 订阅与发布pubsub
      • 5. Vuex
      • 6. 插槽
    • sync修饰符
    • attrs和listeners属性
    • children和parent属性
    • mixin混入
    • 作用域插槽
      • 在vue3中

项目收尾

二级路由

个人中心采用二级路由

{
path: '/center',
component: Center,
//重定向
redirect:'/center/myorder',
// 添加元信息meta
meta: { show: true },
//二级路由组件children: [{//要么全写'/center/myorder',要么全不写'myorder'path: '/center/myorder',component:MyOrder,},{path: 'mygroup',component:MyGroup,},]
},

未登录全局路由守卫

else{next();
}

未登录:不能去交易相关(trade)、支付相关(pay/paysuccess)、不能去个人中心(center/……)

 let toPath = to.path;//字符串类型
if (toPath.indexOf('/trade') != -1 || toPath.indexOf('/pay') != -1 || toPath.indexOf('/center')) {next('/login');
}

但是情况:如果用户未登录,然后点击个人中心,然后跳转到登录,登录完应该回到最初点击的个人中心页面,而不是每次都是home主页

  • 那么就需要先存储点击的路径,然后再登录完回到该路径
  1. 修改为:next('/login?redirect='+toPath)
    toPath为/center/myorder

  2. 跳到登录,此时路由为/login?redirect=%2Fcenter%2Fmyorder
    这是进行编码后的,实际上编译过来=/center/myorder

  3. 可见进入登录页添加了query参数
    那么在点击登录时需要判断一下是否有query参数,有则进行该路由跳转,没有才都是回到home首页

//Login组件内userLogin修改//存储需要跳转的路径(query参数中),没有则是/home
let toPath = this.$route.query.redirect||'/home';
this.$router.push(toPath);

路由独享守卫

  1. 交易页必须是从购物车页点击结算才能跳转到,而不是可以直接在地址栏输入就可以进入.( 支付页也同理,必须是从交易页pay而来)
{path: '/trade',component: Trade,// 添加元信息metameta: { show: true }, //独享守卫:只管跳到trade路由的守卫beforeEnter: (to, from, next) => {if (from.path == '/shopcart') {next();} else {//从其他路由而来的,停留在当前next(false);}}
},

next(false);中断当前的导航。如果浏览器的URL改变了(可能是用户手动或者浏览器后退按钮),那么URL地址会重置到from路由对应的地址

  1. 问题:
    当前页是shopcart,然后再手动输入trade仍然可以跳转,但是不对,应该只有点击<router-link class="sum-btn" to="/trade">结算</router-link>才能进入
  • 解决:
    在shopcart路由信息meta中加一个flag,初始值为false。当点击去结算按钮触发事件,flag置为true。然后在trade的独享路由守卫中判断一下flag是否为true,当flag为true时,则是通过点击去结算按钮跳转的,然后放行。
 {path: '/trade',
component: Trade,
// 添加元信息meta
meta: { show: true ,falg:false}, 
//独享守卫:只管跳到trade路由的守卫
beforeEnter: (to, from, next) => {if (from.path == '/shopcart' && from.mate.falg == true) {//跳转后需要将原来flag置为falsefrom.meta.flag = false;next();} else {next(false);}}
},

路由跳转写成编程式路由跳转

 methods: {toTrade() {this.$route.meta.flag = true;this.$router.push('/trade');}}

图片懒加载

当服务器数据没有返回时,页面上显示默认图。

主要目的是延迟加载图片,直到用户滚动到图片所在的位置时才加载。

查看vue-lazyload官方文档
main.js

//引入vue-lazyload插件
import VueLazyload from 'vue-lazyload';
import Karry from '@/assets/Karry.gif';
//use()实质上触发install安装插件的方法
Vue.use(VueLazyload, {//可添加配置//1. 懒加载默认图:(图片和json文件是默认对外暴露的loading: Karry,
});

组件中<img v-lazy="image.src" />

路由懒加载

当打包构建应用时,js包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

原先是在router中配置路由信息前import组件,现在是在配置路由信息component时import。—路由懒加载

 {path:"/home",component:()=>import ('@/pages/Home'),meta:{show:true}
},

只有当用户访问该路径时才执行箭头函数,引入组件。使得路由跳转更高效

打包上线

打包:npm run build
在这里插入图片描述
打包后(js文件夹),代码都是经过压缩加密的,如果运行时报错,输出的错误信息无法准确得知是哪里的代码报错。
有了map就可以像未加密的代码一样,准确输出是哪一行有错
在这里插入图片描述
map文件也可以去除
在vue.config.js配置productionSourceMap: false即可。

重要知识点汇总

组件通信方式

1. props

①(非函数) 父传子:
- 在父组件中如:<Floor v-for="floor in floorList" :key="floor.id" :list="floor" />在子组件上绑定属性list,传递floor数据,子组件props:['list']接收
- props接受数据方式:数组[]或对象{list:Array}、{list:Array,default:[]}
② (函数)子传父

// 子组件
<template>
<!--3.value双向数据绑定,渲染接收过来的数据-->
<!--4.绑定原生事件input事件触发updateValue回调--><input :value="value" @input="updateValue">
</template><script>
export default {
//2.子组件通过props接收数据props: ['value'],methods: {updateValue(event) {//5.输入数据:调用触发父组件的自定义input事件并传值给父组件this.$emit('input', event.target.value);}}
}
</script>// 父组件
<template><div><!--1. 父组件的 message 初始为空字符串通过 v-model 将message作为value传递给子组件子组件输入框显示空值--><child-component v-model="message"></child-component><p>{{ message }}</p></div>
</template><script>
import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {message: ''};}
}
</script>

📌 v-model常规写法(手动绑定 value 和 input)

<input	:value="message" 
@input="message = $event.target.value"
/>

✅ v-model 简写(推荐)

javascript <input v-model="message" />

完全等价于上面的写法! Vue 内部会自动将其编译成 :value + @input 的形式。

实现:父组件 →(通过 props)→ 子组件 →(通过 $emit)→ 父组件 → 循环更新。

注意:在组件身上@绑定事件会被当做自定义事件,而不是原生DOM事件。如果想把自定义事件变为原生DOM事件加上修饰符.native
(那么该组件任何位置都会触发click[假设绑定的是@click],原理其实是利用事件委派给该组件根标签绑定了该原生DOM事件)

总结:原生DOM节点(如<input>、<button>)—原生事件,自定义组件—自定义事件

2. 自定义事件

$on$emit:绑定事件、触发事件
上面例子用到$emit,但是没有用到$on,因为@input底层就是

this.$on('input', (value) => {this.message = value
})) // Vue 内部自动完成

3. 全局事件总线

main.js中:Vue.prototype.$bus = this
📌 为什么将this根实例挂载到$bus身上?
将根实例赋值给 Vue.prototype.$bus,使其成为全局可访问的事件总线。而且根实例的原型链上有$on$emit属性,使其可访问到。

4. 订阅与发布pubsub

在react中运用较多

5. Vuex

6. 插槽

可以实现父子组件通信,一般是结构

sync修饰符

父组件给子组件传值,而且给子组件绑定一个自定义事件(update:money)

<Child :money="money" @update:money="money = $event">

等价于

<Child :money.sync="money">

子组件props:[‘money’]接受,
第一种触发写法$emit('upate:money',money-100)
第二种$emit('update',money-100)

attrs和listeners属性

  1. $attrs:
    属于组件的一个属性,可以获取到父组件传递过来的props数据

注意:如果是通过props接受的数据,那么在$atters中是获取不到的

  • 应用:封装elementUI
    父组件:
//引入的子组件
//传入静态属性:直接作为字符串写入DOM
<HintButton type="success" icon="el-icon-delete" size="mini" title="提示按钮"></HintButton>

子组件:

<template><div><!--a标签的额外属性title,可以鼠标悬停时,浏览器会自动显示 title 的内容作为提示文本--><a :title="title"><!--那么el-button会显示响应type属性的样式--><el-button :type="$attrs.type"></el-button></a></div>
</template>
<script>export default{name:"",props:["title"],mounted(){console.log(this.$attrs);//{type:'success',icon:'el-icon-delete',size:'mini'}}}
</script>

如果有大量属性
可以<el-button v-bind="$attrs"></el-button>将所有接受的数据作为el-button的属性。注意必须写v-bind全称,不能写冒号

  1. $listener:
    在父组件中给HintButton绑定自定义事件,子组件内可以通过$listener获取到该自定义事件
//触发自定义事件
<el-button v-on="$listener"></el-button>

同样v-on不能简写为@

children和parent属性

  1. $children

在父组件:

<!--ref:可以获取节点(组件标签)-->
<Son ref = "son"/>
<Girl ref="girl"/>

this.$refs.son就是子组件实例:
在这里插入图片描述

那么就可以通过ref获取到子组件里的数据

$children是组件的一个属性,可以获取当前组件的所有的子组件(Son和Girl)
打印:this.$children===>[VueComponent,VueComponent]
注意:该数组是无序的,this.$children[0]不一定是son

  1. $parent
    在某个子组件内可以通过$parent获取到该组件的父组件,那么就可以获取到父组件的数据/方法

mixin混入

逻辑复用:mixin,可以将多个组件共用的逻辑、数据、方法等提取到一个单独的对象中,然后在多个组件中混入使用

可以将mixin单独出一个模块然后对外暴露,在组件中直接import使用

// 定义一个 mixin
const myMixin = {data() {return {message: 'Hello from mixin!'}},methods: {greet() {console.log(this.message);}}
};// 在组件中使用 mixin
export default {mixins: [myMixin],created() {this.greet(); // 输出: Hello from mixin!}
};

作用域插槽

elementUI主要就是作用域插槽

父组件:

<!--父组件向List子组件传递 todos 数组-->
<List :todos="todos"><template slot-scope = "todo"><span :style="color:todo.todo.isComplete?'green':'red'}">{{todo.todo.text}}</span></template>
</List><!---->
<script>
export default{data(){return {todos:[{id: 1, text: 'AA', isComplete:false},{id: 2, text: 'BB', isComplete:true},{id: 3, text: 'CC', isComplete:false},]}}
}</script>

子组件:

<ul><li v-for="(item,index) in todos" :key="index"><!--每个 item 通过 slot 回传给父组件 --><slot :todo="item"></slot></li>
</ul><!--script中:List组件接收todos-->
props:['todos']
  1. 核心概念:
  • 子组件通过 <slot> 暴露数据给父组件( :todo=“item”)
  • 父组件通过 slot-scope = “todo” 接收子组件暴露的数据命名为todo
  1. 关键点:
    (1)slot-scope 的命名
    父组件中 slot-scope="todo"todo 是临时变量名,可以任意命名(如 scope、data)
    实际接收的是子组件 <slot :todo="item">:todo 绑定的数据
    (2)数据结构
    子组件传递给slot-scope变量todo的数据结构:
{ todo: { id: 1, text: 'AA', isComplete: false } }

因此父组件中访问的是 todo.todo.text(第一个 todo 是 slot-scope 变量第二个 todo 是子组件绑定的属性名[:todo=“item”])

总结:子组件的数据来源于父组件,子组件向父组件传递一个对象,父组件自定义子组件内部的部分渲染逻辑

在vue3中

在 Vue 3 中,slot-scope 被废弃,改用 v-slot:

<List :todos="todos"><template v-slot="todo"><span :style="{color: todo.todo.isComplete ? 'green' : 'red'}">{{ todo.todo.text }}</span></template>
</List>

或解构写法:

<template v-slot="{ todo }">  <!-- 解构 --><span :style="{color: todo.isComplete ? 'green' : 'red'}">{{ todo.text }}</span>
</template>

相关文章:

18前端项目----Vue项目收尾优化|重要知识

收尾/知识点汇总 项目收尾二级路由未登录全局路由守卫路由独享守卫图片懒加载路由懒加载打包上线 重要知识点汇总组件通信方式1. props2. 自定义事件3. 全局事件总线4. 订阅与发布pubsub5. Vuex6. 插槽 sync修饰符attrs和listeners属性children和parent属性mixin混入作用域插槽…...

仿RabbitMQ 模拟实现消息队列

文章目录 项目项目介绍开发环境技术选型 开始项目前第三方框架内容介绍muduo搭建服务端&#xff0c;客户端服务端&#xff1a;客户端&#xff1a;makefile muduo库protobuf通信服务端&#xff1a;客户端 sqlitegtest线程池future 认识&#xff0c;async使用promis使用package_t…...

基于Qt的app开发第八天

写在前面 笔者是一个大一下计科生&#xff0c;本学期的课程设计自命题完成一个督促学生自律的打卡软件&#xff0c;目前已经完成了待办和打卡部分功能&#xff0c;本篇要完成规划板块不需要存储就能实现的功能 需求分析 这一板块内容相比前两个板块还有一些特殊&#xff0c;因…...

Springboot之类路径扫描

SpringBoot框架中默认提供的扫描类为&#xff1a;ClassPathBeanDefinitionScanner。 webFlux框架中借助RepositoryComponentProvider扫描符合条件的Repository。 public class ClassPathScanningCandidateComponentProvider{private final List<TypeFilter> includeFilt…...

PNG图片转icon图标Python脚本(简易版) - 随笔

摘要 在网站开发或应用程序设计中&#xff0c;常需将高品质PNG图像转换为ICO格式图标。本文提供一份高效Python解决方案&#xff0c;利用Pillow库实现透明背景完美保留的格式转换。 源码示例 from PIL import Imagedef convert_png_to_ico(png_path, ico_path, size):"…...

数据分析-图2-图像对象设置参数与子图

from matplotlib import pyplot as mp mp.figure(A figure,facecolorgray) mp.plot([0,1],[1,2]) mp.figure(B figure,facecolorlightgray) mp.plot([1,2],[2,1]) #如果figure中标题已创建&#xff0c;则不会新建窗口&#xff0c; #而是将旧窗口设置为当前窗口 mp.figure(A fig…...

查询公网IP地址的方法:查看自己是不是公网ip,附内网穿透外网域名访问方案

本地搭建服务并提供互联网连接时&#xff0c;较为传统的方法是使用公网IP地址。因此&#xff0c;如何查询本地自己是不是公网IP&#xff0c;是必须要掌握的一种技巧。当面对确实无公网IP时&#xff0c;则可以通过内网穿透方案&#xff0c;如nat123网络映射工具&#xff0c;将本…...

MVCC:数据库并发控制的利器

在并发环境下&#xff0c;数据库需要处理多个事务同时访问和修改数据的情况。为了保证数据的一致性和隔离性&#xff0c;数据库需要采用一些并发控制机制。MVCC (Multi-Version Concurrency Control&#xff0c;多版本并发控制) 就是一种常用的并发控制技术&#xff0c;它通过维…...

Redis学习打卡-Day1-SpringDataRedis、有状态无状态

Redis的Java客户端 Jedis 以 Redis 命令作为方法名称&#xff0c;学习成本低&#xff0c;简单实用。Jedis 是线程不安全的&#xff0c;并且频繁的创建和销毁连接会有性能损耗&#xff0c;因此推荐使用 Jedis 连接池代替Jedis的直连方式。 lettuce Lettuce是基于Netty实现的&am…...

【行为型之访问者模式】游戏开发实战——Unity灵活数据操作与跨系统交互的架构秘诀

文章目录 &#x1f9f3; 访问者模式&#xff08;Visitor Pattern&#xff09;深度解析一、模式本质与核心价值二、经典UML结构三、Unity实战代码&#xff08;游戏物品系统&#xff09;1. 定义元素与访问者接口2. 实现具体元素类3. 实现具体访问者4. 对象结构管理5. 客户端使用 …...

Shell脚本实践(修改文件,修改配置文件,执行jar包)

1、前言 需要编写一个shell脚本支持 1、修改.so文件名 2、修改配置文件 3、执行jar包 2、代码解析 2.1、修改.so文件名 so_file_dir="/opt/casb/xxx/lib" # 处理.so文件 cd "$so_file_dir" || { echo "错误: 无法进入目录 $so_file_dir"; exit …...

React Native矢量图标全攻略:从入门到自定义iconfont的高级玩法

“你知道吗?在React Native应用中,仅仅通过一行代码就能召唤出上千个精美矢量图标,甚至还能把设计师精心制作的iconfont完美嵌入——但90%的开发者居然还在用图片方案!” 当我第一次发现同事的APP安装包比我的小了2.3MB,仅仅是因为他正确使用了react-native-vector-icons时…...

x-IMU matlab zupt惯性室内定位算法

基于x-IMU的ZUPT&#xff08;Zero Velocity Update&#xff0c;零速更新&#xff09;惯性室内定位算法是一种结合了惯性测量单元&#xff08;IMU&#xff09;数据和零速检测技术的室内定位方法。该算法通过检测行人静止状态下的零速区间&#xff0c;对惯性导航系统&#xff08;…...

hbase shell的常用命令

一、hbase shell的基础命令 # 版本号查看 [rootTest-Hadoop-NN-01 hbase]$ ./bin/hbase version HBase 2.4.0 Source code repository git://apurtell-ltm.internal.salesforce.com/Users/apurtell/src/hbase revision282ab70012ae843af54a6779543ff20acbcbb629# 客户端登录 […...

在企业级项目中高效使用 Maven-mvnd

1、引言 1.1 什么是 Maven-mvnd? Maven-mvnd 是 Apache Maven 的一个实验性扩展工具(也称为 mvnd),基于守护进程(daemon)模型构建,目标是显著提升 Maven 构建的速度和效率。它由 Red Hat 推出,通过复用 JVM 进程来减少每次构建时的启动开销。 1.2 为什么企业在构建过…...

iOS瀑布流布局的实现(swift)

在iOS开发中&#xff0c;瀑布流布局&#xff08;Waterfall Flow&#xff09;是一种常见的多列不等高布局方式&#xff0c;适用于图片、商品展示等场景。以下是基于UICollectionView实现瀑布流布局的核心步骤和优化方法&#xff1a; 一、实现原理 瀑布流的核心在于动态计算每个…...

Spring Spring Boot 常用注解整理

Spring & Spring Boot 常用注解整理 先理解核心概念&#xff1a;什么是注解&#xff08;Annotation&#xff09;&#xff1f;第一部分&#xff1a;IOC&#xff08;控制反转&#xff09;和 DI&#xff08;依赖注入&#xff09;1. Component2. Service, Repository, Controll…...

c#建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能

# financial_建筑行业 建筑行业财务流水账系统软件可上传记账凭证财务管理系统签核功能 # 开发背景 软件是给岳阳客户定制开发一款建筑行业流水账财务软件。提供工程签证单、施工日志、人员出勤表等信息记录。 # 财务管理系统功能描述 1.可以自行设置记账科目&#xff0c;做凭…...

让 Cursor 教我写 MCP Client

文章目录 1. 写在最前面2. 动手实现一个 MCP Client2.1 How 天气查询 Client2.1.1 向 Cursor 提问的艺术2.1.2 最终成功展示2.1.3 client 的代码 3. MCP 协议核心之一总结3.1 SSE vs WebSocket 4. 碎碎念5. 参考资料 1. 写在最前面 学习了 MCP Server 的实现后&#xff0c;刚好…...

反射, 注解, 动态代理

文章目录 单元测试什么是单元测试咱们之前是如何进行单元测试的&#xff1f; 有啥问题 &#xff1f;现在使用方法进行测试优点Junit单元测试的使用步骤删除不需要的jar包总结 反射认识反射、获取类什么是反射反射具体学什么&#xff1f;反射第一步&#xff1a;或者Class对象 获…...

vue vite 无法热更新问题

一、在vue页面引入组件CustomEmployeesDialog&#xff0c;修改组件CustomEmployeesDialog无法热更新 引入方式&#xff1a; import CustomEmployeesDialog from ../dialog/customEmployeesDialog.vue 目录结构&#xff1a; 最后发现是引入import时&#xff0c;路径大小写与目…...

【CustomPagination:基于Vue 3与Element Plus的高效二次封装分页器】

CustomPagination&#xff1a;基于Vue 3与Element Plus的高效二次封装分页器 在现代Web应用开发中&#xff0c;分页是处理大量数据列表时不可或缺的功能。Element Plus等UI库提供了基础的分页组件&#xff0c;但在大型项目中&#xff0c;为了追求极致的用户体验和视觉统一&…...

kafka connect 大概了解

kafka connect Introduction Kafka Connect is the component of Kafka that provides data integration between databases, key-value stores, search indexes, file systems, and Kafka brokers. kafka connect 是一个框架&#xff0c;用来帮助集成其他系统的数据到kafka…...

UniApp 在华为三折叠屏中的适配问题与最佳解决方案(rpx 实战指南)

随着折叠屏设备的普及&#xff0c;如华为 Mate Xs、Mate X3 等多形态设备越来越常见&#xff0c;开发者在 UniApp 项目中遇到的适配问题也变得复杂。本文将聚焦一个关键问题&#xff1a;在三折叠屏设备上&#xff0c;使用 px 单位造成页面显示异常&#xff0c;并给出最推荐的解…...

深度学习中的查全率与查准率:如何实现有效权衡

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型辅助生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认…...

Docker从0到1:入门指南

目录 什么是DockerDocker的核心概念 容器(Container)镜像(Image)镜像层(Image Layers)Dockerfile仓库(Repository)数据卷(Volume)网络(Network) Docker架构Docker安装Docker基本命令实际应用场景Docker生态系统最佳实践常见问题 什么是Docker Docker是一个开源的应用容器引擎…...

Windows玩游戏的时候,一按字符键就显示桌面

最近打赛伯朋克 2077 的时候&#xff0c;不小心按错键了&#xff0c;导致一按字符键就显示桌面。如下&#xff1a; 一开始我以为是输入法的问题&#xff08;相信打游戏的人都知道输入法和奔跑键冲突的时候有多烦&#xff09;&#xff0c;但是后来解决半天发现并不是。在网上搜…...

Gemini 2.5 Flash和Pro预览版价格以及上下文缓存的理解

Gemini 2.5 Flash和Pro预览版价格 Gemini 2.5 Flash 预览版就是 Google 的最新 AI 大模型&#xff0c;能处理巨量内容。可以免费体验&#xff0c;但有次数和功能上的限制&#xff1b;付费层级才开放全部高级功能。价格也比传统 API 略有不同&#xff0c;尤其在“思考预算”“上…...

vue2 头像上传+裁剪组件封装

背景&#xff1a;最近在进行公司业务开发时&#xff0c;遇到了头像上传限制尺寸的需求&#xff0c;即限制为一寸证件照&#xff08;宽295像素&#xff0c;高413像素&#xff09;。 用到的第三方库&#xff1a; "vue-cropper": "^0.5.5" 完整组件代码&…...

unity 鼠标更换指定图标

1.准备两张图 要求图片导入设置如下 将 Texture Type 改为 Cursor 确保 Read/Write Enabled 已勾选 取消勾选 Generate Mip Maps 将 Filter Mode 设为 Point (保持清晰边缘) 将 Compression 设为 None (无压缩) 2.创建脚本&#xff0c;把脚本挂到场景中 &#xff0c;该…...