Web前端-Vue2+Vue3基础入门到实战项目-Day4(组件的三大组成部分, 组件通信, 案例-组件版小黑记事本, 进阶语法)

Web前端-Vue2+Vue3基础入门到实战项目-Day4

  • 组件的三大组成部分(结构/样式/逻辑)
    • scoped样式冲突
    • data是一个函数
  • 组件通信
    • 组件通信语法
    • 父传子
    • 子传父
    • props详解
      • 什么是props
      • props检验
      • props与data的区别
    • 非父子(扩展)
      • 事件总线 (event bus)
      • provide - inject
  • 案例 - 小黑记事本(组件版)
    • App.vue
    • TodoHeader.vue
    • TodoMain.vue
    • TodoFooter.vue
  • 进阶语法
    • v-model详解
      • v-model原理
      • 表单类组件封装
      • v-model简化代码
    • sync修饰符
    • ref和$refs
    • $nextTick
  • 来源

组件的三大组成部分(结构/样式/逻辑)

scoped样式冲突

  • 全局样式: 默认的style样式, 会作用于全局
  • 局部样式: 加上scoped属性的style样式, 只会作用于当前组件
  • scoped原理:
    1. 给当前组件模板的所有元素, 添加一个自定义属性
      data-v-hash值: 根据hash值区分不同的组件
    2. css选择器后面, 被自动处理, 添加上了属性选择器
      div[data-v-hash]
<template><div class="base-one">BaseOne</div>
</template><script>
export default {}
</script><style scoped>
div {border: 3px solid blue;margin: 30px;
}
</style>

data是一个函数

  • data必须是一个函数 -> 保证每个组件实例, 维护独立的一个数据对象
  • 每次创建新的组件实例, 都会新执行一次data函数, 得到一个新对象
<template><div class="base-count"><button @click="count--">-</button><span>{{ count }}</span><button @click="count++">+</button></div>
</template><script>
export default {data() {return {count: 100,}},
}
</script><style>
.base-count {margin: 20px;
}
</style>

组件通信

组件通信语法

  • 组件关系和对应的通信方案
    • 父子关系: props, $emit
    • 非父子关系: provide, injecteventbus
    • 通用方案: vuex
  • 父子通信方案的核心流程
    • 父传子props:
      1. 父中给子添加属性传值
      2. 子props接收
      3. 使用
    • 子传父$emit
      1. 子$emit发送消息
      2. 父中给子添加消息监听
      3. 父中实现处理函数

父传子

<template><div class="app" style="border: 3px solid #000; margin: 10px">我是APP组件<!-- 1.给组件标签,添加属性方式 赋值 --><Son :title="myTitle"></Son></div>
</template><script>
import Son from "./components/Son.vue"
export default {name: "App",components: {Son,},data() {return {myTitle: "学前端,就来黑马程序员",}},
}
</script><style>
</style><!-- Son.vue -->
<template><div class="son" style="border:3px solid #000;margin:10px"><!-- 3.直接使用props的值 -->我是Son组件 {{title}}</div>
</template><script>
export default {name: 'Son-Child',// 2.通过props来接受props: ['title']
}
</script><style></style>

子传父

<template><div class="app" style="border: 3px solid #000; margin: 10px">我是APP组件<!-- 2. 父组件, 对消息进行监听 --><Son :title="myTitle" @changeTitle="handleChange"></Son></div>
</template><script>
import Son from "./components/Son.vue"
export default {name: "App",components: {Son,},data() {return {myTitle: "学前端,就来黑马程序员",}},methods: {// 3. 提供处理函数, 提供逻辑handleChange(newTitle){this.myTitle = newTitle}}
}
</script><style>
</style><!-- Son.vue -->
<template><div class="son" style="border:3px solid #000;margin:10px">我是Son组件 {{title}}<button @click="changeFn">修改title</button></div>
</template><script>
export default {name: 'Son-Child',props: ['title'],methods: {changeFn(){// 1. 通过$emit, 向父组件发送消息通知this.$emit('changeTitle', "传智教育")}}
}
</script><style></style>

props详解

什么是props

  • 定义: 组件上注册的一些自定义属性
  • 作用: 向子组件传递数据
  • 特点:
    • 可以传递任意数量的prop
    • 可以传递任意类型的prop

父组件

<template><div class="app"><UserInfo:username="username":age="age":isSingle="isSingle":car="car":hobby="hobby"></UserInfo></div>
</template><script>
import UserInfo from './components/UserInfo.vue'
export default {data() {return {username: '小帅',age: 28,isSingle: true,car: {brand: '宝马',},hobby: ['篮球', '足球', '羽毛球'],}},components: {UserInfo,},
}
</script><style>
</style>

子组件

<template><div class="userinfo"><h3>我是个人信息组件</h3><div>姓名:{{username}} </div><div>年龄:{{age}} </div><div>是否单身:{{isSingle ? '是' : '否'}} </div><div>座驾:{{car.brand}} </div><div>兴趣爱好:{{hobby.join(', ')}} </div></div>
</template><script>
export default {props: ['username', 'age', 'isSingle', 'car', 'hobby']
}
</script><style>
.userinfo {width: 300px;border: 3px solid #000;padding: 20px;
}
.userinfo > div {margin: 20px 10px;
}
</style>

props检验

  • 作用: 为组件的prop指定验证要求, 不符合要求, 控制台会有错误提示
  • 语法
    1. 类型检验
    2. 非空检验
    3. 默认值
    4. 自定义检验

父组件

<template><div class="app"><BaseProgress :w="width"></BaseProgress></div>
</template><script>
import BaseProgress from './components/BaseProgress.vue'
export default {data() {return {width: 23,}},components: {BaseProgress,},
}
</script><style>
</style>

子组件

<template><div class="base-progress"><div class="inner" :style="{ width: w + '%' }"><span>{{ w }}%</span></div></div>
</template><script>
export default {// props: ["w"],// 1.基础写法(类型校验)// props: {//   w: Number // Number String Boolean Array Object// }// 2.完整写法(类型、是否必填、默认值、自定义校验)props: {w: {type: Number,// required: truedefault: 0,validator (value) {if(value >= 0 && value <= 100){return true}console.error('传入的prop w, 必须是0-100的数字')return false}}}
}
</script><style scoped>
.base-progress {height: 26px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;
}
.inner {position: relative;background: #379bff;border-radius: 15px;height: 25px;box-sizing: border-box;left: -3px;top: -2px;
}
.inner span {position: absolute;right: 0;top: 26px;
}
</style>

props与data的区别

  • 共同点: 都可以给组件提供数据
  • 区别:
    • data的数据是自己的 -> 随便改
    • prop的数据是外部的 -> 不能直接改, 要遵循单向数据流
  • 单向数据流: 父级prop的数据更新, 会向下流动, 影响子组件. 这个数据流动是单向的.

父组件

<template><div class="app"><BaseCount @changeCount="handleChange":count="count"></BaseCount></div>
</template><script>
import BaseCount from './components/BaseCount.vue'
export default {components:{BaseCount},data(){return {count:100}},methods:{handleChange(value){this.count = value}}
}
</script><style></style>

子组件

<template><div class="base-count"><button @click="handleSub">-</button><span>{{ count }}</span><button @click="handleAdd">+</button></div>
</template><script>
export default {// 1.自己的数据随便修改  (谁的数据 谁负责)// data () {//   return {//     count: 100,//   }// },// 2.外部传过来的数据 不能随便修改// 单向数据流: 父组件的prop更新, 会单向向下流动, 影响到子组件.props: {count: Number},methods: {handleAdd(){this.$emit('changeCount', this.count+1)},handleSub(){this.$emit('changeCount', this.count-1)}}}
</script><style>
.base-count {margin: 20px;
}
</style>

非父子(扩展)

事件总线 (event bus)

  • 作用: 非父子组件之间, 进行简易消息传递(复杂场景 -> vuex)
  • 语法:
    1. 创建一个都能访问的事件总线(空vue实例) -> utils/EventBus.js
    import Vue from 'vue'
    const Bus  =  new Vue()
    export default Bus
    
    1. A组件(接受方), 监听Bus实例的事件
    created() {Bus.$on('sendMsg', (msg) => {// console.log(msg)this.msg = msg})
    }
    
    1. B组件(发送方), 触发Bus实例的事件
    Bus.$emit('sendMsg', '今天天气不错,适合旅游')
    

provide - inject

  • 作用: 跨层级共享数据
  • 语法:
    1. 父组件provide提供数据
    provide() {return {// 简单类型 是非响应式的color: this.color,// 复杂类型 是响应式的userInfo: this.userInfo,}
    }
    
    1. 子/孙组件 inject 取值使用
    <script>
    export default {inject: ['color', 'userInfo'],
    }
    </script>
    

案例 - 小黑记事本(组件版)

核心步骤

  1. 拆分基础组件
    新建组件 -> 拆分存放结构 -> 导入注册使用
  2. 渲染待办任务
    提供数据(公共父组件) -> 父传子传递list -> v-for渲染
  3. 添加任务
    收集数据v-model -> 监听事件 -> 子传父传递任务 -> 父组件unshift
  4. 删除任务
    监听删除id -> 子传父传递id -> 父组件filter删除
  5. 底部合计和清空功能
    底部合计: 父传子list -> 合计展示
    清空功能: 监听点击 -> 子传父通知父组件 -> 父组件清空
  6. 持久化存储: watch监视数据变化, 持久化到本地

App.vue

<template><!-- 主体区域 --><section id="app"><TodoHeaderVue @add="handleAdd"></TodoHeaderVue><TodoMainVue @del="handleDel" :list="list"></TodoMainVue><TodoFooterVue @clear="handleClear" :list="list"></TodoFooterVue></section>
</template><script>
import TodoHeaderVue from './components/TodoHeader.vue'
import TodoMainVue from './components/TodoMain.vue'
import TodoFooterVue from './components/TodoFooter.vue'// 渲染功能:
// 1. 提供数据-> 提供在公共的父组件 App.vue
// 2. 通过父传子, 奖数据传递给 TodoMain
// 3. 利用v-for渲染// 添加功能
// 1. 收集表单数据 -> v-model
// 2. 监听事件 (回车 + 点击都要进行添加)
// 3. 子传父, 将任务名称传递给父组件App.vue
// 4. 进行添加 unshift// 删除功能
// 1. 监听事件 (监听删除的点击) 携带id
// 2. 子传父, 将删除的id传递给父组件App.vue
// 3. 进行删除 filter// 底部合计: 父传子list -> 渲染
// 清空功能: 子传父 通知父组件 -> 父组件进行清空
// 持久化存储: watch深度监视list的变化 -> 往本地存储 -> 进入页面优先读取本地存储
export default {data () {return {list: JSON.parse(localStorage.getItem('list')) || [{id: 1, name: '打篮球'},{id: 2, name: '看电影'},{id: 3, name: '逛街'},]}},methods: {handleAdd(todoName){this.list.unshift({id: +new Date(),name: todoName})},handleDel(id){this.list = this.list.filter(item => item.id!==id)},handleClear(){this.list = []}},watch: {list: {deep: true,handler(newValue){localStorage.setItem('list', JSON.stringify(newValue))}}},components: {TodoHeaderVue,TodoMainVue,TodoFooterVue}
}
</script><style></style>

TodoHeader.vue

<template><div><!-- 输入框 --><header class="header"><h1>小黑记事本</h1><input v-model.trim="todoName" @keyup.enter="handleAdd" placeholder="请输入任务" class="new-todo"/><button @click="handleAdd" class="add">添加任务</button></header></div>
</template><script>
export default {data(){return {todoName: ''}},methods: {handleAdd(){if(this.todoName.trim() === ''){alert('任务名称不能为空')return }this.$emit('add', this.todoName)this.todoName = ''}}
}
</script><style>
</style>

TodoMain.vue

<template><div><!-- 列表区域 --><section class="main"><ul class="todo-list"><li class="todo" v-for="(item, index) in list" :key="item.id"><div class="view"><span class="index"> {{index+1}}. </span> <label> {{item.name}} </label><button @click="handleDel(item.id)" class="destroy"></button></div></li></ul></section></div>
</template><script>
export default {props: {list: Array},methods: {handleDel(id){this.$emit('del', id)}}
}
</script><style></style>

TodoFooter.vue

<template><div><!-- 统计和清空 --><footer class="footer"><!-- 统计 --><span class="todo-count">合 计:<strong> {{list.length}} </strong></span><!-- 清空 --><button @click="clear" class="clear-completed">清空任务</button></footer></div>
</template><script>
export default {props: {list: Array},methods: {clear(){this.$emit('clear')}}
}
</script><style></style>

进阶语法

v-model详解

v-model原理

  • 原理: v-model本质上是一个语法糖. 例如应用在输入框上, 就是value属性和input事件的合写.
  • 作用: 提供数据的双向绑定
    1. 数据发生变化, 视图自动变化: value
    2. 视图发生变化, 数据自动变化: @input
  • $event: 用在模板中, 获取事件的形参
<div class="app"><input v-model="msg1" type="text" /> <br /><input :value="msg2" @input="msg2 = $event.target.value" type="text" >
</div>

表单类组件封装

实现子组件和父组件数据的双向绑定

  • 父传子: 数据 由父组件props传递, v-model拆解绑定数据
  • 子传父: 监听输入, 子传父传值给父组件修改

父组件

<template><div class="app"><BaseSelect :selectId="selectId" @change="selectId = $event"></BaseSelect></div>
</template><script>
import BaseSelect from './components/BaseSelect.vue'
export default {data() {return {selectId: '102',}},components: {BaseSelect,},methods: {}
}
</script><style>
</style>

子组件

<template><div><select :value="selectId" @change="handleChange"><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">广州</option><option value="105">深圳</option></select></div>
</template><script>
export default {props: {selectId: String},methods: {handleChange(e){this.$emit('change', e.target.value)}}
}
</script><style>
</style>

v-model简化代码

父组件v-model简化实现子组件和父组件数据双向绑定

  • 子组件: props通过value接收, 事件触发input
  • 父组件: v-model绑定数据 (:value + @input)

父组件

<template><div class="app"><BaseSelect v-model="selectId"></BaseSelect></div>
</template><script>
import BaseSelect from './components/BaseSelect.vue'
export default {data() {return {selectId: '102',}},components: {BaseSelect,},
}
</script><style>
</style>

子组件

<template><div><select :value="value" @change="handleChange"><option value="101">北京</option><option value="102">上海</option><option value="103">武汉</option><option value="104">广州</option><option value="105">深圳</option></select></div>
</template><script>
export default {props: {value: String},methods: {handleChange(e){this.$emit('input', e.target.value)}}
}
</script><style>
</style>

sync修饰符

  • 作用: 实现子组件与父组件的数据双向绑定, 简化代码
  • 特点: prop属性名, 可以自定义, 非固定为value
  • 场景: 封装弹框类的基础组件, visible属性 true显示 false隐藏
  • 本质: :属性名 + @update:属性名

父组件

<template><div class="app"><button @click="isShow = true">退出按钮</button><BaseDialog :visible.sync="isShow"></BaseDialog></div>
</template><script>
import BaseDialog from "./components/BaseDialog.vue"
export default {data() {return {isShow: false}},methods: {},components: {BaseDialog,},
}
</script><style>
</style>

子组件

<template><div v-show="visible" class="base-dialog-wrap"><div class="base-dialog"><div class="title"><h3>温馨提示:</h3><button @click="close" class="close">x</button></div><div class="content"><p>你确认要退出本系统么?</p></div><div class="footer"><button>确认</button><button>取消</button></div></div></div>
</template><script>
export default {props: {visible: Boolean},methods: {close(){this.$emit('update:visible', false)}}
}
</script><style scoped>
.base-dialog-wrap {width: 300px;height: 200px;box-shadow: 2px 2px 2px 2px #ccc;position: fixed;left: 50%;top: 50%;transform: translate(-50%, -50%);padding: 0 10px;
}
.base-dialog .title {display: flex;justify-content: space-between;align-items: center;border-bottom: 2px solid #000;
}
.base-dialog .content {margin-top: 38px;
}
.base-dialog .title .close {width: 20px;height: 20px;cursor: pointer;line-height: 10px;
}
.footer {display: flex;justify-content: flex-end;margin-top: 26px;
}
.footer button {width: 80px;height: 40px;
}
.footer button:nth-child(1) {margin-right: 10px;cursor: pointer;
}
</style>

ref和$refs

  • 作用: 通过ref$refs可以获取dom元素和组件实例
  • 使用:
    1. 目标组件 - 添加ref属性
    <div ref="test"></div>
    
    1. 通过this.$refs.ref属性值获取目标组件
    this.$refs.test
    
  • 获取dom
    <div ref="mychart" class="base-chart-box">子组件</div>const myChart = echarts.init(this.$refs.mychart)
    
  • 获取组件
    父组件
    <template><div class="app"><BaseForm ref="baseFrom"></BaseForm><button @click="handleGet">获取数据</button><button @click="handleReset">重置数据</button></div></template><script>
    import BaseForm from './components/BaseForm.vue'
    export default {components: {BaseForm,},methods: {handleGet(){console.log(this.$refs.baseFrom.getValues())},handleReset(){this.$refs.baseFrom.resetValues()}}
    }
    </script><style>
    </style>
    
    子组件
    <template><div class="app"><div>账号: <input v-model="username" type="text"></div><div>密码: <input v-model="password" type="text"></div></div>
    </template><script>
    export default {data() {return {username: 'admin',password: '123456',}},methods: {getValues() {return {username: this.username,password: this.password}},resetValues() {this.username = ''this.password = ''console.log('重置表单数据成功');},}
    }
    </script><style scoped>
    .app {border: 2px solid #ccc;padding: 10px;
    }
    .app div{margin: 10px 0;
    }
    .app div button{margin-right: 8px;
    }
    </style>
    

$nextTick

  • Vue是异步更新DOM的
  • $nextTick: 在DOM更新完成之后做某件事
<template><div class="app"><div v-if="isShowEdit"><input type="text" v-model="editValue" ref="inp" /><button>确认</button></div><div v-else><span>{{ title }}</span><button @click="handleEdit">编辑</button></div></div>
</template><script>
export default {data() {return {title: '大标题',isShowEdit: false,editValue: '',}},methods: {handleEdit(){// 1. 显示输入框 (异步dom更新)this.isShowEdit = true// 2. 让输入框显示焦点// console.log(this.$refs.inp) // undefinedthis.$nextTick(()=>{this.$refs.inp.focus()})}},
}
</script><style>
</style>

来源

黑马程序员. Vue2+Vue3基础入门到实战项目

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

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

相关文章

gRPC之gRPC Gateway

1、gRPC Gateway etcd3 API全面升级为gRPC后&#xff0c;同时要提供REST API服务&#xff0c;维护两个版本的服务显然不太合理&#xff0c;所以 grpc-gateway 诞生了。通过protobuf的自定义option实现了一个网关&#xff0c;服务端同时开启gRPC和HTTP服务&#xff0c; HTTP服…

京东数据接口:京东数据分析怎么做?

电商运营中数据分析的重要性不言而喻&#xff0c;而想要做数据分析&#xff0c;就要先找到数据&#xff0c;利用数据接口我们能够更轻松的获得比较全面的数据。因此&#xff0c;目前不少品牌商家都选择使用一些数据接口来获取相关电商数据、以更好地做好数据分析。 鲸参谋电商…

2023年中国云计算软件市场规模、市场结构及市场份额情况分析[图]

云计算是分布式计算的一种&#xff0c;指的是通过网络“云”将巨大的数据计算处理程序分解成无数个小程序&#xff0c;然后&#xff0c;通过多部服务器组成的系统进行处理和分析这些小程序得到结果并返回给用户。云计算软件类型分为三类&#xff0c;即基础设施即服务、平台即服…

点云从入门到精通技术详解100篇-基于多尺度深度特征分析的点云模型法向估计(续)

目录 3.3 网络结构与损失函数设计 3.3.1 网络结构 3.3.2 损失函数设计

Python算法练习 10.14

leetcode 2095 删除链表的中间节点 给你一个链表的头节点 head 。删除 链表的 中间节点 &#xff0c;并返回修改后的链表的头节点 head 。 长度为 n 链表的中间节点是从头数起第 ⌊n / 2⌋ 个节点&#xff08;下标从 0 开始&#xff09;&#xff0c;其中 ⌊x⌋ 表示小于或等于…

非类型模板参数+模板的特化

目录 一、非类型模板参数 二、模板的特化 &#xff08;一&#xff09;函数模板特化 &#xff08;二&#xff09;类模板举例 1. 全特化 2. 偏特化 一、非类型模板参数 模板参数分类&#xff1a;类型形参与非类型形参。类型形参即&#xff1a;出现在模板参数列表中&#x…

通过webpack创建并打包js库到npm仓库

1.创建项目并进行基本配置 webpack配置文件&#xff1a; webpack.build.js const path require(path);module.exports {mode:development,entry:./src/webpack-numbers.js,output: {filename: webpack-numbers.js,path: path.resolve(__dirname, dist),clean: true,},}; p…

使用docker搭建kafka集群、可视化操作台

单机搭建 1 拉取zookeeper镜像 docker pull wurstmeister/zookeeper 2 启动zookeeper容器 docker run -d --name zookeeper -p 2181:2181 -v /etc/localtime:/etc/localtime wurstmeister/zookeeper 3 拉取kafka镜像 docker pull wurstmeister/kafka 4 启动kafka镜像 docker…

【玩机】如何修改iPhone充电提示音!最详细简单保姆级教程~ 学费了可替换任意音频做你的专属充电提示音!——后厂村路灯

其实方法很简单&#xff0c;利用快捷指令&#xff0c;获得base64 位的音频文本&#xff0c;然后再充电时播放即可。 视频教程 【玩机】如何修改iPhone充电提示音&#xff01;最详细简单保姆级教程 具体操作如下&#xff1a; 1.首先&#xff0c;网上找到需要设定的音频&#xf…

一个单身狗 和 两个单身狗

一个单身狗 一个数组中只有一个数字是出现一次&#xff0c;其他所有数字都出现了两次。 编写一个程序找出这个只出现一次的数字。 方法1(异或) a ^ a 0a ^ 0 a^满足结合律 #include<stdio.h> int main() {int arr[] { 1,2,3,4,5,4,2,3,5};int i 0;int ret 0;in…

Linux grep 命令参数使用方法[-vE]

Linux grep 命令参数使用方法[-vE] grep 常用参数常用的g r e p选项使用grep匹配“与”或者“或”模式 grep 常用参数 参数 -v #排除条件-E #多个条件使用&#xff0c;或例子&#xff1a;排除#号和空格行内容 #grep命令去掉空格行和以#开头的行 grep -vE ^#|^$ filename“…

Flutter笔记:电商中文货币显示插件Money Display

Flutter笔记 电商中文货币显示插件 Money Display 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/1338…

Pulsar 之架构,客户端以及多区域容灾

Pulsar 之架构&#xff0c;客户端以及多区域容灾 架构BrokersClusters元数据存储配置存储区持久存储Apache BookKeeperLedgersLedgers读一致性托管Ledgers 日志存储 Pulsar 代理服务发现 Pulsar client(客户端)客户端设置阶段Reader interface 多区域容灾备份(GEO-REPLICATION)…

Apacheb Shiro 1.2.4反序列化漏洞(CVE-2016-4437)

Apache Shiro 1.2.4反序列化漏洞&#xff08;CVE-2016-4437&#xff09; 1 在线漏洞解读: https://vulhub.org/#/environments/shiro/CVE-2016-4437/2 环境搭建 cd /home/kali/vulhub/shiro/CVE-2016-4437启动&#xff1a; sudo docker-compose up -d # 拉取下载并启动sud…

AtCoder ABC324G 启发式合并

题意 传送门 AtCoder ABC324G Generate Arrays 题解 逆则操作顺序考虑&#xff0c;可以看作至多 n n n 个联通分量不断合并的过程&#xff0c;此时使用启发式合并&#xff0c;即规模较小的连通分量向规模较大的连通分量合并&#xff0c;以单个元素合并为基本运算&#xff0…

Knife4j Spring Boot:在线API文档

1.导入依赖 <dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>${knife4j-spring-boot.version}</version></dependency>2.再配置文件中打开日志 knife4j.en…

C# 解决从其他地方迁移项目,引用中大多数包是感叹号的问题

当在 Visual Studio 中复制别人的 C# 项目时&#xff0c;遇到许多包冒感叹号的问题通常是因为缺少相关的 NuGet 包或引用不正确导致的。这会在解决方案资源管理器中的引用下显示感叹号。 解决办法如下&#xff1a; 在 Visual Studio 中打开项目。 在解决方案资源管理器中&…

【更新】囚生CYの备忘录(202331014~)

文章目录 20221014 20221014 本以为下午怡宝的比赛至少是能跑到前三&#xff0c;结果连前五都没混到&#xff0c;赛前都知道路线不可能有5km&#xff0c;因为即便是绕着主校区最外沿跑一圈也才4km出头&#xff0c;我估摸着大概是2500米&#xff0c;结果实际上只有1700米&#x…

服务器数据恢复-DS5300存储raid5硬盘出现坏道离线的数据恢复案例

服务器数据恢复环境&#xff1a; 某单位一台DS5300存储&#xff0c;1个主机4个扩展柜&#xff0c;组建了2组RAID5&#xff08;一组27块硬盘&#xff0c;一组23块盘&#xff09;。27块盘的那组RAID5阵列存放Oracle数据库文件&#xff0c;存储系统一共分了11个卷。 服务器故障&a…

Unity基础课程之物理引擎3-碰撞检测案例-吃金币并加分显在UI文本框上

业务逻辑&#x1f4bc;&#xff1a; 这个脚本的主要功能是用于显示和更新主角的得分。在游戏中&#xff0c;玩家需要吃到金币来增加分数&#xff0c;而这个脚本就是负责将得分的变化实时显示在屏幕上的。 程序逻辑&#x1f4bb;&#xff1a; 1️⃣首先&#xff0c;在脚本的开始…