vue3 知识点的补充 之 第一节

news2025/6/8 23:34:05

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 = newValue
                        trigger()
                 }
          }
       })

}



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 = _effect
                let 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 top

          props.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 = h

                index = 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.css

npm 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)=>void

  on:(name:string,callback:Function)=>void

}

type ParamsKey = string | number | symbol

type List = {

  [key:ParamsKey]:Array<Function>

}

class Bus implements BusClass{

    list:List

    constructor(){

        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.tsx

01 写法 返回一个函数

export default function (){

   return (<div>小明</div>)

}

02 写法 optionsApi

import {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 || delete

    if(!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.value

            observer.unobserve(el) //停止监听
        }
    
    })

     observer.observe(el)
  
  }

</script>




 

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

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

相关文章

plsql developer 一键格式化sql/美化sql

PL/SQL 格式化工具 以 Oracle SQL Developer 为例&#xff0c;使用一键格式化的步骤如下&#xff1a; 打开 Oracle SQL Developer。在“文件”菜单中&#xff0c;选择“打开文件”&#xff0c;然后选择你的 PL/SQL 文件。打开文件后&#xff0c;你可以通过右键菜单选择“格式…

机器学习——自动驾驶

本章我们主要学习以下内容: 阅读自动驾驶论文采集数据根据论文搭建自动驾驶神经网络训练模型在仿真环境中进行自动驾驶 论文介绍 本文参考自2016年英伟达发表的论文《End to End Learning for Self-Driving Cars》 📎end2end.pdf

全栈的自我修养 ———— 如何发布一个npm包?

创建本地仓库 npm init在此期间会让你添加一些版本信息和名称 登陆npm npm login ——> yinhaodada arx.040208发布 npm publish查询

微服务(基础篇-008-Elasticsearch分布式搜索【上】)

目录 初识elasticsearch&#xff08;1&#xff09; 了解ES&#xff08;1.1&#xff09; 倒排索引&#xff08;1.2&#xff09; es的一些概念&#xff08;1.3&#xff09; 安装es、kibana&#xff08;1.4&#xff09; ik分词器&#xff08;1.5&#xff09; ik分词器的拓展…

RT-Thread内核简介

1、RT-Thread 内核介绍 RT-Thread 内核架构图,内核处于硬件层之上,内 核部分包括内核库、实时内核实现 内核库是为了保证内核能够独立运行的一套小型的类似 C 库的函数实现子集。这部分根据编译器的不 同自带 C 库的情况也会有些不同,当使用 GNU GCC 编译器时,会携带…

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

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

jenkins下载安装(mac)

下载官网 具体 直接命令安装 Sample commands: Install the latest LTS version: brew install jenkins-ltsStart the Jenkins service: brew services start jenkins-ltsRestart the Jenkins service: brew services restart jenkins-ltsUpdate the Jenkins version: brew u…

Linux02(项目部署,手动和自动部署,JDK版本问题,安装软件,安装软件,安装JDK,Tomcat,MySQL,Irzsz)

目录 一、安装软件 1. 安装准备工作 1 Linux里的软件安装方式 2 上传软件到Linux 3 拍照虚拟机快照 2. 安装JDK 1 卸载自带jdk 2 解压JDK 3 配置环境变量 4 测试JDK 3. 安装Tomcat 1 解压Tomcat 2 修改防火墙设置 3 测试Tomcat 启动Tomcat 访问Tomcat 查看Tom…

【Jenkins PipeLine】Jenkins PipeLine 联动参数示例

目录 1. Pipeline script&#xff1a; 1.1.代码说明&#xff1a; 2. 实现效果&#xff1a; 3.联动说明&#xff1a; 4.Jenkins安装插件 1. Pipeline script&#xff1a; properties([parameters([[$class: "ChoiceParameter", choiceType: "PT_SINGLE_SELE…

redis的主从复制(docker方式快速入门和实战)

目录 一、主从复制简介 二、配置主从服务器 2.1使用配置文件的形式来主从复制 2.2使用纯代码的方式来进行主从复制&#xff1b; 2.3脱离主服务器 三、一些注意事项 一、主从复制简介 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器…

【opencv】示例-pca.cpp PCA图像重建演示

// 加载必要的头文件 #include <iostream> // 用于标准输入输出流 #include <fstream> // 用于文件的输入输出 #include <sstream> // 用于字符串的输入输出流操作#include <opencv2/core.hpp> // OpenCV核心功能的头文件 #include "o…

Upload-labs(Pass-17--Pass-21)

Pass-17 二次渲染图片马/条件竞争 二次渲染就是在我们上传的图片后&#xff0c;网站会对图片进行二次处理&#xff0c;比如对图片的尺寸、格式、以及网站对图片进行定义的一些要求等进行处理&#xff0c;并且服务器会对里面的内容进行二次替换更新&#xff0c;在处理完后&…

【深度学习】图像超分辨

案例 7&#xff1a;图像超分辨 相关知识点&#xff1a;生成对抗网络、图像处理&#xff08;PIL&#xff09;和可视化&#xff08;matplotlib&#xff09; 1 任务目标 1.1 任务和数据简介 ​ 本次案例将使用生成对抗网络来实现 4 倍图像超分辨任务&#xff0c;输入一张低分辨…

搭建基于Hexo的个人博客,以及git相关命令

全文写完之后的总结 测试命令 hexo clean hexo g hexo s 上传到服务器命令 hexo clean hexo g hexo d 上传到服务器&#xff08;如果上一个命令用不了&#xff09;&#xff0c;也要先hexo clean,hexo g git init git add . git commit -m "first commit" git p…

.NET i18n 多语言支持与国际化

环境 WIN10 VS2022 .NET8 1.&#x1f44b;创建项目 2.&#x1f440;创建Resources Controllers HomeController.en.resx HomeController.fr.resx HomeController.zh.resx 3.&#x1f331;Program.cs添加国际化支持 // 添加国际化支持 builder.Services.AddLocalization(…

【OTA】STM32新能源汽车OTA技术ymodem协议PC串口升级过程

【OTA】STM32新能源汽车OTA技术ymodem协议PC串口升级过程 文章目录 前言一、实验工具1.串口USB线——烧录APP2生成的BIN文件2.STLINK——烧录BOOT代码和APP1代码3.烧录工具——将BIN文件烧录到单片机中4.FLYMCU——清除芯片FLASH 二、硬件绘制1.原理图2.PCB 三、软件配置1.BOOT…

【GD32】MQ-3酒精检测传感器

2.31 MQ-3酒精检测传感器 MQ-3气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(Sn0)。当传感器所处环境中存在酒精蒸气时&#xff0c;传感器的电导率随空气中酒精蒸气浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。…

设计模式代码实战-装饰者模式

1、问题描述 小明喜欢品尝不同口味的咖啡&#xff0c;他发现每种咖啡都可以加入不同的调料&#xff0c;比如牛奶、糖和巧克力。他决定使用装饰者模式制作自己喜欢的咖啡。 请设计一个简单的咖啡制作系统&#xff0c;使用装饰者模式为咖啡添加不同的调料。系统支持两种咖啡类型…

【Vue + keep-alive】路由缓存

一. 需求 列表页&#xff0c;n 条数据项可打开 n 个标签页&#xff0c;同时1条数据项的查看和编辑共用一个标签页。如下所示&#xff1a; 参考 // 主页面 // 解决因 路由缓存&#xff0c;导致 编辑后跳转到该页面 不能实时更新数据 onActivated(() > {getList() })二. 实现…

ISP图像处理pipeline简介1

ISP 是什么&#xff1f; ISP (Image Signal Processor)&#xff0c;图像信号处理器&#xff0c;是用于摄影和视频处理的一种专用芯片。它是用来干什么的呢&#xff1f;简单说就是用来将图像传感器&#xff08;CCD, CMOS&#xff09;信号转化成可视的信号的功能&#xff0c;这里…