vue3 知识点的补充 之 第一节

01 vue2与vue3的区别

vue2 采用object.defuneProperty()实现 对数组不友好 重写了数组的方法,同时无法监听数组length长度的改变。对于对象只能劫持设置好的数据 新增需要使用vue.set
vue3 采用proxy进行代理,不需要重写数组的方法 同时可以监听数组长度的变化
第二点区别:
对于DOM中静态的数据,不会再去进行对比, 对于{{}}动态的数据 id calss所有会发生改变的,会打一个标记去进行对比。比如文本会打text的标记 id如果会变的话就会增加props的标记。

02  如何使用vscode去开发vue3的项目

第一步 需要安装 volar的插件和Typescript Vue Plugin(Volar)插件, 同时需要将vue2的vetur

03 npm run dev执行的过程:

第一步 去找package.json文件中scripts中的dev的脚步执行第二步 node_modules中去找vite/pageage.json,然后再找bin目录下的vite.js去执行

04 DOM的点击事件也可以变成动态的

<div @[event]="btn"></div>      <script setup lang="ts">const event = 'click'</script>



05 虚拟DOM和diff算法

真实的DOM身上会有几百个属性和方法因此操作真实的DOM消耗性能

虚拟DOM就是通过js来生成一个AST语法树

diff算法分为有key和无key两种的模式:
无key的情况下:
新的虚拟DOM会一项一项的去替换旧的虚拟DOM。
到最后如果新的虚拟DOM多余旧的虚拟DOM,那么新的虚拟DOM就会增加到元素中,
如果最后旧的虚拟DOM多余新的虚拟DOM,那么就会把旧的多余的虚拟DOM进行删除。
有key的情况下:
1前序对比 拿A和A对比 B和B对比 到C的时候发现C和DDD不同就break跳出循环
2 尾序对比 拿D和D对比 C和C对比 发现B和DDD不同的时候跳出循环
3 发现多了一个就会增加
4 发现少了就会进行卸载
5 无序排列的:首先要对元素进行一个排序 记录新节点再旧节点的位置。新的增加 多的删除
如果出现交叉然后使用最长递归子序列算法

 

06关于Ref相关

如果传递给ref的是基本数据类型会直接返回,如果传递的是引用数据类型会调用reactive函数
第一种 关于 ref定义响应式的数据 const count = ref(10)
第二种 isRef 判断是否是ref的对象 console.log(isRef(count))
第三种shallowRef浅层式的ref,只到.value ,value后面的数据不再进行响应
注意:ref如果在shallowRef在同一个函数的作用域中被使用的时候ref会影响shallowRef
triggerRef() 会强制更新,如果使用shallowRef更新深层的数据视图不发生变化的时候,调用triggerRef(要更新的数据), 参数要更新的数据 然后视图也会强制更新。
customRef 自定义ref,参数是一个函数,函数的返回值是一个对象,对象包含了get和set方法:
const myRef = (value)=>{return  customRef((tarck,trigger)=>{     tarck收集依赖  trigger触发依赖return {get(){track()return value},set(newValue){。。。在这里可以做点别的事情 比如发送网络请求等value = newValuetrigger()}}})}



07 reactive只能传引用类型的数据

reactive proxy 不能直接赋值,否则会破坏响应式对象的,这是因为和内存有关,如果直接赋值的改变了内存的地址。比如 let list = reactive([])const add = ()=>{setTimeout(()=>{let res = [1,2,3,4]  list =  res )})} 这个时候页面是不会发生任何变化的第一种方案 const add = ()=>{setTimeout(()=>{let res = [1,2,3,4]  list.push(...res) )})} 页面发生变化第二中方案 let list = reactive({arr:[]}) 修改list为一个对象const add = ()=>{setTimeout(()=>{let res = [1,2,3,4] list.arr = res)})}



08 readonly为只读的

const read = readonly({a:1}) 
const add = ()=>{read.a = 2} // 无法进行修改
注意点readonly会受reactive的影响



09 shallowReactive浅层的 只会修改第一层的数据

const obj = shallowReactive({a:b:{c:2}}) //只能修改第一层的数据
同样也会受reactive的影响



10 toref 只能修改响应式对象的值,对非响应式对象的值没有办法进行视图的更新

const obj = {name:zs}const obj1 = reactive({name:'ls'})const name1 = toref(obj,'name')const name2 = toref(obj1,'name')const change  = ()=>{name = 'zs1', name2='ls1'}  这个时候name1视图不会发生变化 name2会发生变化



11 torefs将所有响应式的对象中的每一个属性都变成修改后是相应式的:
源码:

const torefs = (object)=>{const map = {}for (key in object) {map[key] = toref(object,key)
}
return map
}
const obj1 = reactive({a:1,b:2,c:3})
const {a,b} = torefs(obj1)
const change = ()=>{a=3,b=4}  // 响应式的


 

12 toRaw()将响应式的对象转化为原始对象 也就是非响应式的对象

const obj = reactive({a:1,b:2,c:3})
const obj2 = toRaw(obj) // 非响应式对象了


13 vue3响应式的原理

这里解释下:receiver这个参数和target相同都代表元素本身
Reflect是用方法的形式来获取和设置属性的值,相当于target[key]  target[key]=12 


14依赖收集: 收集的格式

副作用函数:

let activeEffect;
export  const effect = (fu:function)=>{const _effect = function(){activeEffect = _effectlet res = fn()return res}_effect()return _effect
}


收集依赖的方法:const obj = {name:'zs'}

const targetMap = new WeakMap() // 数据结构是 { {}:{} }
export const track = (target,key)=>{let depsMap = targetMap.ger(target)if(!depsMap) {depsMap = new Map()targetMap.set(target,depsMap)     // 数据结构 { {name:'zs'}: {} }}let deps = depsMap.get(key)if(!deps){deps = new Set()depsMap.set(key,deps)  // 此刻的数据结构 { {name:'zs'}:{name:[]} }}deps.add(activeEffect) // 收集副作用函数 // { {name:'zs'}:{name:[activeEffect]} }} 


依赖更新的方法

export const trigger = (targer,key)=>{const depsMap = targetMap.get(target)const deps = depsMap.get(key)deps.forEach(effect=>effect()) 
}


 

15  依赖收集和触发依赖 :

import {tarck,trigger} from './effect.js'const isObject = (res)=> res!==null && typeof res =='object'export const reactive = (target)=>{return new Proxy(target,{get(target,key,receiver){let res = reflect.get(target,key,receiver)tarck(target,key) // 收集依赖的方法if(isObject(res)){return reactive(res)} // 如果对象值是对象进行递归return res},set(target,key,value,receiver){let res = reflect.set(target,key,value,receiver)trigger(target,key) // 触发更新return res}})}

16 项目中index.html页面中使用effect

<div id="app"></div><script type="module">import {effect} from './effect.js'const user = reactive({name:'小曼',age:12})effect(()=>{document.querySelector('#app').innerText = `${user,name}-${user.age}`})
</script>


17  computed计算属性:
第一种 选项式写 法:

<div>{{}}</div><input v-model="firstName" />   <input v-module="lastName"><button @click="changeName">修改计算属性name的值</button>let firstName = ref('张')     let lastName = ref(‘三’)let name = computed({get(){return  firstName.value + '-' + lastNmae.value  // 当input 输入框的值发生改变的时候 这里的值也会随着改变 },set(newValue){console.log(newValue) // 王-五[firstName.value,lastName.value] = newValue.split('-') // 分隔成数组 然后给firstName和lastName重新赋值 }
})const changeName = ()=>{name.value = '王-五'}



第二种函数的写法: 不允许修改值得

let name =computed(()=>{return firstName.value + '-' + lastNmae.value }) 

computed计算属性的源码:

interface Options {scheduler?:Function }let activeEffect;export const effect = (fn,options) = >{const _effect = function (){activeEffect = _effect()let res = fn()return res }_effect.options = options_effect()return _effect
}const targetMap = new WeakMap() // 数据结构是 { {}:{} }export const track = (target,key)=>{let depsMap = targetMap.ger(target)if(!depsMap) {depsMap = new Map()targetMap.set(target,depsMap)     // 数据结构 { {name:'zs'}: {} }}let deps = depsMap.get(key)if(!deps){deps = new Set()depsMap.set(key,deps)  // 此刻的数据结构 { {name:'zs'}:{name:[]} }}deps.add(activeEffect) // 收集副作用函数 // { {name:'zs'}:{name:[activeEffect]} }} export const trigger = (targer,key)=>{const depsMap = targetMap.get(target)const deps = depsMap.get(key)deps.forEach(effect=>{if(effect?.options?.scheduler){effect?.options?.scheduler?.()}else{effect()}}) 
}export const computed = (getter:function)=>{let _value = effect(getter,{scheduler:()=>{_dirty=true}})let _dirty = true // 脏值检测let catchValue;class ComputedRefImpl{get value () {if(_dirty){catchValue = _value()}return catchValue}}return new ComputedRefImpl()}

18 watchEffect监听器的使用:

const message = ref(‘消息’)const stop = watchEffect((oninvalidate)=>{console.log(meaasge+'message数据发生改变了')oninvalidate(console.log('我会先执行')) // 这个函数会先执行 可以清除一些副作用
})
通过调用watchEffect的返回值,可以清除这个监听器<button @click="clearEffect">清除监听器</button>const clearEffect = ()=>{ stop() } // 清除了监听器

19 组件之间的传参方式:

第一种 父组件向子组件传递参数:

第一种 父组件向子组件传递参数:父组件:<div><son :title="title" :arr="arr"></son>
</div>子组件:<div>{{title}}</div>01 第一种不使用ts接收<script>const props = defineProps({title:{type:string, default:'默认值'}})console.log(props.title)</script>02 第二种使用ts的方式接收<scipt>defineProps<{ title:string,arr:number[]}>()</script>03 使用ts指定默认值需要使用withDefaults的这个方法需要接受两个参数 第一个参数正常接受porps传递的参数的类型 第二个参数定义默认值的对象<script>withDefault( defineProps<{ title:string,arr:number[]}>(), {arr:()=>[]})</script>

第二种 子组件给父组件传递参数:

子组件:第一种 没有使用ts的方式<button @click="send">给父组件传递参数</button><script>defineEmits(['sendClick'])const send = ()=>{emit('sendClick','传递的参数')}</script>第二种使用ts的方式传值<script>defineEmits<{(e:"send-click",str:string):void}>()const send = ()=>{emit('sendClick','传递的参数')}</script>父组件接受:<son @sendClick="getData"></son>const getData = (str:string)=>{console.log(str)}

第三种 子组件暴露数据给父组件进行调用,父组件通过ref调用

子组件的数据:defineExpose = ({name:'小曼',fn:()=>{console.log('fn')}})父组件调用:<son ref="children"></son>const children = ref()console.log(children.value.name)ts如何读取子组件的类型来定义ref的类型呢:关于子组件定义ref的时候有自带的类型const children = ref<InstanceType<Typeof waterFallVue>>()

 20  案例封装瀑布流的组件:

父组件给子组件传递的数据:<son :list="list"></son>const list = [{height:300, background:'red'},{height:400, background:'pink'},...}]子组件:<template><div class="wraps"><div class="items" v-for="item in waterList" :style="{height:item.height+'px',background:item.background,left: item.left+'px',top:item.top+'px'}"><div></div></template><script lang="ts" setup>const waterList = reactive<any[]>([]) // 接收第一行的数据const heightList:number[] = [] // 维护高度的数组const props = defineProps<{list:any[]}>() // ts类型接收传递过来的参数const init =()=>{const width = 130 // 定义一个宽度 不要让每个items按着太近const x = document.body.clientWidth  // 获取窗口可视区的宽度const column = Math.floor(x/width) // 计算一行可以存放几个元素for(let i = 0; i<props.list.length; i++) {if(i<column){  // 判断是否属于第一行的元素 如果属于第一行的元素给第一行数据添加left topprops.list[i].left = width * 1; // 定位的左侧距离props.list[i].top = 20 // 距离顶部定位的距离waterList.push(props.list[i]) // 将第一行的数据 添加到数组中 接着遍历div第一行数组的数据heightList.push(props.list[i].height) // 将第一行的数据的高度传递到数组中}else {  // 当前的数据已经超过了第一行的数据 准备第一行追加数据 这时候要追加到最短的一行let current = heightList[0] // 先把第一行第一个数据拿出来 假设是最小的let index = 0 通过遍历先去找出真正的最小的数字heightList.forEach((h,i)=>{if(current > h) {current = hindex = i}})console.log(current) // 找到了最小的高度props.list[i].top = current + 20 // 设置当前元素定位的高度props.list[i].left = index*width //定位的left为当前找到元素的索引*设置的width度heightList[index] = heightList[index] + props.list[i].height + 20 // 再把当前找到的这个元素的高度 改为新增元素后的高度,waterList.push(props.list[i]) // 再不断的向数组里面追加数据}}}onMounted(()=>{init()}) // DOM渲染完毕 调用上面的方法</script><style>.wraps {position:relative;.items:{position:absolute;width:120px;}}</style>

21 vue3:异步组件&分包&suspense

异步组件的使用:结合骨架屏的使用<tempalte><Suspense><template #default> <asyncComponent/> </template><template #fallback> <gujiaping/ > </template></Suspense></template><script>import gujiaping from './gujiaping.vue'const asyncComponent = defineAsyncComponet(()=>import('@/component/asyncComponent.vue'))</script>在项目打包的时候,所有的组件都会被加载在同一个js文件中, 首次加载因为体积比较大 所以加载时间慢采用异步组件的时候 打包会自动进行分包,增加组件的js文件,有利于性能优化。

22 传送组件Tekeport

主要解决的问题:父组件嵌套子组件/ 子组件嵌套一个弹框的组件, 弹框的盒子,需要在屏幕中居中。如果弹框盒子的父级也就是子组件不设定position:relative的属性,这个盒子是不会受子组件影响问题: 但是如果子组件设置了position:relative, 那么弹框的盒子就会根据子组件去定位了解决问题的方法使用:Teleport使用方法:在子组件中:<template><Teleport :disable="false" to="body"> // disable是否关闭传输门  to传送的位置<Tankuang/> // 也就是定位以body为准了</Teleport></template>

23 transition动画组件
从 隐藏 到进入的样式
从显示到离开的状态

24 transition动画结合Animate.css动画库来使用:

第一步 需要安装animate.cssnpm install animate.css -S第二步 使用:在.vue文件中script标签下引入:<script>import 'animate.css'</script>然后在transtion标签上面使用自定义动画的名字就可以了<tempalte><transition leave-active-class="animate_animated animate_fadeOut"><div v-if="isShow">显示与隐藏</div></transition></template>leave-active-class类名是transition标签自带的 有进入 离开过渡的属性 结合 animate.css的类名使用便可

25 vue3 的css可以绑定定义的数据 const color = 'pink',    .box{color:v-bind(color)}
 

25 使用一个兄弟组件之间通信的Bus,遵循的还是发布订阅的模式:

type BUsClass = {emit:(name:string)=>voidon:(name:string,callback:Function)=>void}type ParamsKey = string | number | symboltype List = {[key:ParamsKey]:Array<Function>}class Bus implements BusClass{list:Listconstructor(){this.list = list}emit(name:string,...args:Array<any>){let evebtName:Arrat<Function> = this.list[name]evebtName.forEach(fn=>{fn.apply(this,args)})}on(name:string,callback:Function){let fn:Array<Function> = this.list[name] || []fn.push(callback)this.list[name] = fn}}

26 vue3使用tsx的语法:

第一步 安装插件npm install @vitejs/plugin-vue-jsx -D第二步 vite.config.ts配置import vueJsx from '@vitejs/plugin-vue-jsx'export default defineConfig({plugins:[vue(),vueJsx()]})第三步 测试组件 test.tsx01 写法 返回一个函数export default function (){return (<div>小明</div>)}02 写法 optionsApiimport {defineComponent} from 'vue'export default defineComponent({data(){return {age:12}},render(){return (<div>{this.age}</div>)}})03 setup函数的写法// 这是另外一个组件 需要给传递插槽的数据const A = (_,{slots})=>{<div>{slots.default?slots.default():'默认值'}</div><div>{slots.foo?.()}</div>}// 这是一个tsx的组件 import {defineComponent,ref} from 'vue'interface Props {name:string}export default defineComponent({props:{name:string} // 接收父组件传递的值setup(props:Props,{emit}){const isShow = ref(false)const fn = (v)=>{emit('sendClick',v)}const slot = {default:()=>(<div>插槽的内容</div>), foo:()=>(<span>11122</span>)}return ()=>(<><div v-show={isShow.value}>小曼</div><div>{props.name}</div><button onClick={()=>fn(v)}>派发事件</button><A v-slot={slot}><A></>)// 注意这里支持v-show但是不支持v-if 需要使用和react的一样语法{true&&<要渲染内容>}// map 代替 v-for// {} 代替 v-bind // 支持 v-model}})第四步 组件使用<xiaoming name={name}  @sendClick="getData"></xiaoming>const name = ref('zs')const getData = (v)=>{console.log(v)}import xiaoming from './test.tsx'

27 自定义指令:声明周期函数:created beforMount mounted beforUpdate updated ... 等:

第一步 创建自定义的指令:import {Directive} from 'vue'const vMove:Directive = {create(){console.log('create')}beforeMount(){console.log('beforeMount')}mounted(...args){conole.log(args) // 得到一个数组  数组的第一个元素 div.A 是v-move绑定的组件的根元素的div // 得到的第一个元素 是一个对象 {arg:'aaa', dir: created:f,beforeMounted:f,...},modifiers: {xiaoman:true}, value:{background:'red'}}这里分开的写法 为mounted(el,dir){ // 第一个元素为绑定的属性  第二个元素为bind绑定的值el.style.background = dir.value.background }}... 同vue2的声明周期函数   }第二步 给组件身上绑定自定义的指令<A v-move:aaa.xiaoman="{background:'ref'}"></A>

28 自定义指令 函数简写的方式:只使用mounted 和 updated的函数, 按钮鉴权、

<template><div><button v-has-show="shop:create">创建</button><button v-has-show="shop:deit">编辑</button><button v-has-show="shop:delete">删除</button></div></tempalte>import type {Directive} from 'vue'const permission = ['shop:create','shop:deit','shop:delete'] // 后台返回权限的数据const vHasShow:Directive = (el,bingding)=>{console.log(el,bingding) // el->button   binding->shop:create || deit || deleteif(!permission.includes(bingding.value)){el.style.display = 'none' // 隐藏按钮}}

29 自定义拖拽指令

import {ref,Directive,DirectiveBinding} from 'vue'const vMove:Directive<any,void> = (el:HTMLElement,bingding:DirectiveBinding)=>{let moveElement :HTMLDivElement = el.firstElementChild as HTMLDivElement //获取的div拖拽元素const mouseDown = (e:MouseEvent)=>{ // 鼠标按下的事件let x = e.clientX - el.offsetLeft // 记录当前鼠标点击在盒子的左侧的位置let y = e.clientY - el.offsetTop// 定义鼠标移动的事件const move = (e:MouseEvent)=>{console.log(e)el.style.left = e.clientX -X +'px'el.style.top = e.clientY - Y + 'px'}document.addEventListener('mousmove',move) // 鼠标移动document.addEventListener('mouseup',()=>{document.removeEventListener('mousemove',move) // 清除移动事件})}moveElement.addEventListener('mousedown',mouseDown)}

30 自定义图片懒加载的指令:

 一次性加载所有图片的方法

 

<template><div><img v-for="item in arr"  v-lazy="item" width="300" height:'400'/></div></template><script>// 获取assets/images下所有的图片const arr = Object.values(import.meta.glob('./assets/images/*.*'),{eager:true}).map(v=>v.default)// 封装懒加载指令const lazy:Directive<HMLImageElement,string> = async (el,bingding) = >{const def = await import('./asstes/vue.svg') // 默认的图片el.src = def.default const observer = new IntersectionObserver(err=>{if(err[0].intersectionRatio>0){ // 说明出现在了页面中el.src = bingding.valueobserver.unobserve(el) //停止监听}})observer.observe(el)}</script>




 

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

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

相关文章

gdb相关指令

背景知识 通过上图&#xff0c;可以看到&#xff0c;gcc 和 g 默认形成的可执行程序是release的&#xff01;&#xff01;&#xff01;故无法直接被调试。因此带 -g 选项表示使用 Debug 模式进行编译&#xff0c;而且我们可以看到&#xff0c;Debug 模式下编译形成的可执…

OSCP靶场--ClamAV

OSCP靶场–ClamAV 考点 1.nmap扫描 ##┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.42 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 10:01 EDT Nmap scan report for 192.168.153.42 Host is up (0.24s latency). N…

Ubuntu去除烦人的顶部【活动】按钮

文章目录 一、需求说明二、打开 extensions 网站三、安装 GNOME Shell 插件四、安装本地连接器五、安装 Hide Activities Button 插件六、最终效果七、卸载本地连接器命令参考 本文所使用的 Ubuntu 系统版本是 Ubuntu 22.04 ! 一、需求说明 使用 Ubuntu 的过程中&#xff0c;屏…

VNC Viewer 连接远程主机及常见错误处理(The connection closed unexpectedly)

搭建可接收vnc连接的环境 1、下载镜像 https://github.com/fcwu/docker-ubuntu-vnc-desktop 该镜像是含有ubuntu 通过docker运行的桌面环境&#xff0c;并接受vnc 的连接 docker pull dorowu/ubuntu-desktop-lxde-vnc 2、运行容器 1&#xff09;只暴露容器的80端口&#…

二叉树练习day.9

669.修剪二叉搜索树 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变…

Singleton单例设计模式详解

目录 模式定义应用场景实现方式1.懒汉模式&#xff1a;2.饿汉模式&#xff1a;3.静态内部类反射如何防止反射攻击破坏&#xff1f; 枚举类型序列化 部分源码中的应用定位Spring & JDKTomcat反序列化指定数据源 模式定义 保证一个类只有一个实例&#xff0c;并且提供一个全…

pytorch车牌识别

目录 使用pytorch库中CNN模型进行图像识别收集数据集定义CNN模型卷积层池化层全连接层 CNN模型代码使用模型 使用pytorch库中CNN模型进行图像识别 收集数据集 可以去找开源的数据集或者自己手做一个 最终整合成 类别分类的图片文件 定义CNN模型 卷积层 功能&#xff1a;提…

Chatgpt掘金之旅—有爱AI商业实战篇|播客剧本写作|(十三)

演示站点&#xff1a; https://ai.uaai.cn 对话模块 官方论坛&#xff1a; www.jingyuai.com 京娱AI 一、AI技术创业播客剧本写作服务有哪些机会&#xff1f; 人工智能&#xff08;AI&#xff09;技术作为当今科技创新的前沿领域&#xff0c;为创业者提供了广阔的机会和挑战。…

b站江科大stm32笔记(持续更新)

b站江科大stm32笔记&#xff08;持续更新&#xff09; 片上资源/外设引脚定义表启动配置推挽开漏oc/od 门漏极/集电极 电阻的上拉下拉输入捕获输入捕获通道主从触发模式输入捕获基本结构PWMI基本结构PWMPSC ARR CRR输入捕获模式测频率TIM_PrescalerConfig()初始化输入捕获测频法…

mysql四种引擎区别

MySQL 提供了多种不同的数据库引擎&#xff0c;其中最常见的有 MyISAM、InnoDB、MEMORY 和 BLACKHOLE。这四个引擎分别有以下特点&#xff1a; 1. MyISAM MyISAM 是 MySQL 的默认引擎。它对于只有较少的修改、大量读取的应用场景具有良好的性能。它不支持事务处理&#xff0c;也…

Steam平台游戏发行流程

Steam平台游戏发行流程 大家好我是艾西&#xff0c;一个做服务器租用的网络架构师也是游戏热爱者&#xff0c;经常在steam平台玩各种游戏享受快乐生活。去年幻兽帕鲁以及雾锁王国在年底横空出世&#xff0c;幻兽帕鲁更是在短短一星期取得了非常好的成绩&#xff0c;那么作为游戏…

你的系统是如何跟MySQL打交道的

1、Java 工程师眼中的数据库是什么东西? 从今天开始&#xff0c;我们将要开始一个MySQL的专栏&#xff0c;一起来研究MySQL数据库的底层原理和各种实践案例&#xff0c;以及互联网公司的技术方案。 现在我们先来看看&#xff0c;在一个Java工程师眼中的数据库是什么东西? 平时…

【Godot4.2】CanvasItem绘图函数全解析 - 5.绘制字符和字符串

概述 到这一节为止&#xff0c;我们已经学习了如何在CanvasItem中绘制简单几何图形、图片以及样式盒。但是对于很重要的文字一直没有涉及。 本节就来讲一下字符和字符串绘制函数&#xff0c;以及替换它们的两个类。 系列目录 0.概述1.绘制简单图形2.设定绘图变换3.绘制纹理4…

解决vue3更新chunk包后,点击页面报错

出现错误 解决思路 试了好多方法&#xff0c;跳了很多坑&#xff0c;router版本对不上&#xff0c;解决方案不实用。最后我直接捕获异常&#xff0c;刷新页面&#xff0c;解决最快最有效。 // vue-rotuer版本 "vue-router": "^4.0.3"解决方案 在router/…

路由器配置实验--R1---R5

R1的路由表中默认存在:192.168.1.0192.168.3.0 需要添加:192.168.2.0 4.0 5.0 R2的路由表中默认存在:192.168.1.0192.168.2.0需要添加:192.168.3.0 4.0 5.0 R3的路由表中默认存在:192.168.3.0192.168.4.0需要添加: 1.0 2.0 5.0 R4的路由表中默认存在:192.168.2.0 192.168.4.0…

面试算法-164-K 个一组翻转链表

题目 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内…

深入微服务框架:构建高效、可扩展与弹性的现代应用架构

前言&#xff1a;当今快速迭代和多变的商业环境中&#xff0c;传统的单体应用程序面临着一系列挑战&#xff0c;包括难以管理复杂性、缺乏灵活性以及无法有效扩展等问题。随着业务需求的不断增长和技术栈的不断演进&#xff0c;企业亟需一种更加模块化、易于管理和扩展的应用程…

给你的AppImage创建桌面快捷方式

原文链接 https://www.cnblogs.com/HGNET/p/16396589.html 运行环境:Ubuntu 22.04 LTS 1.首先准备好AppImage文件并放在一个你知道的地方 2.打开终端&#xff0c;在/usr/share/applications下新建APP.desktop文件&#xff08;APP可以改成你的应用名称&#xff09; cd /usr/s…

在 Elasticsearch 中扩展 ML 推理管道:如何避免问题并解决瓶颈

作者&#xff1a;来自 Elastic Iulia Feroli 是时候考虑语义搜索运营了吗&#xff1f; 无论你是一位经验丰富的搜索工程师&#xff0c;希望探索新的人工智能功能&#xff0c;还是一位机器学习专家&#xff0c;希望更多地利用搜索基础设施来增强语义相似性模型 —— 充分利用这…

易舟云财务软件免费版和专业版有什么区别?

文章目录 1、价格&#xff08;1&#xff09;免费版&#xff08;2&#xff09;专业版 2、版本功能&#xff08;1&#xff09;免费版&#xff08;2&#xff09;专业版 1、价格 &#xff08;1&#xff09;免费版 永久免费&#xff01; &#xff08;2&#xff09;专业版 298元/…