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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/81017.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】基础指令(Ⅱ)

目录 1. mv指令 2. cat指令 3.echo指令 补&#xff1a;输出重定向 4. more指令 5. less指令 6. head指令和tail指令 7.date指令 时间戳&#xff1a; 8. cal指令 9. alias指令 10.grep指令 1. mv指令 语法&#xff1a;mv [选项]... 源文件/目录 目标文件/目录 …

docker及docker-compose安装及使用

docker compose &#x1f517;官网地址 一、为什么要使用docker compose 1. 简化管理 • 通过一个 YAML 文件定义和管理多容器应用。 • 简化服务间的编排与协调&#xff0c;方便环境的管理与复制。 2. 提升协作效率 • 配置文件易于共享&#xff0c;便于开发、运维等团队协…

JVM学习专题(二)内存模型深度剖析

目录 1.JVM结构体系 ​编辑 2.跨平台特性 3.JVM整体结构及内存模型 1.栈内存 1、栈帧&#xff1a; 1.局部变量表 2.操作数栈 3.动态链接 4.方法出口 2、创建对象 2.程序计数器&#xff1a; 3.方法区 ​4.堆 5.本地方法区 6.总结 1.JVM结构体系 JDK、JRE 和 JVM…

Flink之Table API

Apache Flink 的 Table API 是 Flink 提供的一种高级抽象&#xff0c;用于以声明式方式处理批处理和流处理数据。它是基于关系模型的 API&#xff0c;用户可以像编写 SQL 一样&#xff0c;以简洁、类型安全的方式编写数据处理逻辑。 一、基本概念 1. 什么是 Table API&#xf…

基于Vue3.0的高德地图api教程005:实现绘制线并编辑功能

文章目录 6、绘制多段线6.1 绘制多段线6.1.1 开启绘制功能6.1.2 双击完成绘制6.1.3 保存到数据库6.2 修改多段线6.2.1 点击线,进入编辑模式6.2.2 编辑线6.3 完整代码6、绘制多段线 6.1 绘制多段线 6.1.1 开启绘制功能 实现代码: const changeSwitchDrawPolyline = ()=>…

“redis 目标计算机积极拒绝,无法连接” 解决方法,每次开机启动redis

如果遇到以上问题 先打开“服务” 找到App Readiness 右击-启动 以管理员身份运行cmd&#xff0c;跳转到 安装redis的目录 运行&#xff1a;redis-server.exe redis.windows.conf 以管理员身份打开另一cmd窗口&#xff0c;跳转到安装redis的目录 运行&#xff1a;redis-…

Java 大视界——Java 大数据在智慧交通智能停车诱导系统中的数据融合与实时更新

面对城市停车资源错配导致的30%以上交通拥堵问题&#xff0c;本文以某新一线城市智慧交通项目为蓝本&#xff0c;深度解析Java大数据技术如何实现多源停车数据融合、动态路径规划与诱导策略优化。通过构建“感知-计算-决策”全链路系统&#xff0c;实现车位状态更新延迟<200…

牛客周赛 Round 92(再现京津冀蓝桥杯???)

1. 小红的签到题 现在小红希望你写出一个长度为 nnn 的、使用了下划线命名法命名的变量。为了显出特征&#xff0c;请保证该变量至少由两个单词组成。 输入描述: 输入一个正整数 n(3≦n≦100)&#xff0c;代表需要构造的变量长度。 输出描述: 输出一个长度为 n 的字符串&#x…

2025-05-11 Unity 网络基础11——UnityWebRequest

文章目录 1 UnityWebRequest 介绍2 搭建 HTTP 服务器3 常用操作3.1下载资源3.1.1 下载文本3.1.2 下载图片3.1.3 下载 AB 包 3.2 上传资源3.2.1 上传数据类3.2.2 POST 上传3.3.3 PUT 上传 4 自定义操作4.1 下载资源4.1.1 Unity 内置 Handler4.1.2 自定义 Handler 4.2 上传资源4.…

GitHub 趋势日报 (2025年05月09日)

本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1voideditor/void⭐ 1879⭐ 15214TypeScript2ruanyf/weekly科技爱好者周刊&…

.NET MAUI 基础知识

文章目录 什么是 .NET MAUI&#xff1f;MAUI的核心特点与Xamarin.Forms的区别 开发环境搭建安装Visual Studio 2022安装必要组件配置Android开发环境配置iOS开发环境验证安装 创建第一个MAUI应用创建新项目MAUI项目结构解析理解关键文件运行应用程序简单修改示例使用热重载 MAU…

卷积神经网络全连接层详解:特征汇总、FCN替代与性能影响分析

【内容摘要】 本文聚焦卷积神经网络&#xff08;CNN&#xff09;的全连接层&#xff0c;详细介绍其将二维特征图转化为一维向量的过程&#xff0c;阐述全卷积网络&#xff08;FCN&#xff09;如何通过转置卷积替代全连接层以实现像素级分类&#xff0c;并分析全连接层对图像分类…

在C++中进行套接字编程时,主要使用以下头文件

目录 一.基本套接字头文件<sys/socket.h><netinet/in.h><arpa/inet.h><unistd.h><netdb.h> 二. 完整示例头文件包含三. 注意事项 在C中进行套接字编程时&#xff0c;主要使用以下头文件&#xff1a; 一.基本套接字头文件 <sys/socket.h>…

【Linux网络】HTTP

应用层协议 HTTP 前置知识 我们上网的所有行为都是在做IO&#xff0c;&#xff08;我的数据给别人&#xff0c;别人的数据给我&#xff09;图片。视频&#xff0c;音频&#xff0c;文本等等&#xff0c;都是资源答复前需要先确认我要的资源在哪台服务器上&#xff08;网络IP&…

JAVA异常体系

在 Java 里&#xff0c;异常体系是其错误处理机制的核心内容&#xff0c;它能够帮助开发者有效应对程序运行时出现的各种意外状况。 异常体系的基本架构 它主要包含两个重要分支&#xff1a; Error&#xff08;错误&#xff09;&#xff1a;这类异常是程序自身无法处理的严重…

vue 去掉右边table的下拉条与下面的白色边框并补充满

::v-deep table {width: 100% !important; } ::v-deep .el-table::after, .el-table::before {display: none !important; }/* 隐藏滚动条但保留滚动功能 */ ::v-deep .el-table__body-wrapper::-webkit-scrollbar {width: 0 !important;height: 0 !important; }::v-deep .el-t…

uniapp+vue3+uview来开发我们的项目

前言&#xff1a; 就像我们vue的web的框架element、iview等一样&#xff0c;我们的uni-app开发也有适合的他的框架&#xff0c;除了他本身的扩展组件以外&#xff0c;第三方好用的就是就是uview了。 实现效果&#xff1a; 官网信息&#xff1a; vue2版本&#xff1a;uview-ui …

数据仓库:企业数据管理的核心引擎

一、数据仓库的由来 数据仓库&#xff08;Data Warehouse, DW&#xff09;概念的诞生源于企业对数据价值的深度挖掘需求。在1980年代&#xff0c;随着OLTP&#xff08;联机事务处理&#xff09;系统在企业中的普及&#xff0c;传统关系型数据库在处理海量数据分析时显露出明显瓶…

YOLOv12模型部署(保姆级)

一、下载YOLOv12源码 1.通过网盘分享的文件&#xff1a;YOLOv12 链接: https://pan.baidu.com/s/12-DEbWx1Gu7dC-ehIIaKtQ 提取码: sgqy &#xff08;网盘下载&#xff09; 2.进入github克隆YOLOv12源码包 二、安装Anaconda/pycharm 点击获取官网链接(anaconda) 点击获取…

一篇解决Redis:持久化机制

目录 认识持久化 持久化方案 RDB&#xff08;Redis DataBase&#xff09; 手动触发 自动触发 小结 AOF(Append-Only File) AOF缓冲区刷新机制 AOF重写机制 AOF重写流程 ​编辑 混合持久化 认识持久化 我们都知道Mysql有四大特征&#xff0c;原子性&#xff0c;持久…