Vue | (六)使用Vue脚手架(下)| 尚硅谷Vue2.0+Vue3.0全套教程

文章目录

  • 📚Vue 中的自定义事件
    • 🐇使用方法
    • 🐇案例练习
    • 🐇TodoList案例优化
  • 📚全局事件总线
    • 🐇使用方法
    • 🐇案例练习
    • 🐇TodoList案例优化
  • 📚消息订阅与发布
    • 🐇使用方法
    • 🐇TodoList案例优化
      • ⭐️把删除一个todo(`deleteTodo`)改成消息订阅与发布
      • ⭐️添加编辑todo效果
      • ⭐️内容不为空限制
      • ⭐️点击编辑按钮自动获取焦点
  • 📚Vue封装的过度与动画
    • 🐇使用方法
    • 🐇案例练习
    • 🐇TodoList案例优化

学习链接:尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通,本文对应p79-p95,博客参考尚硅谷公开笔记,补充记录实操。

📚Vue 中的自定义事件

🐇使用方法

  • 区别于JS里的内置事件。

  • 一种组件间通信的方式,适用于:子组件 ===> 父组件

  • 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

  • 绑定自定义事件:

    • 第一种方式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>
    • 第二种方式,在父组件中:
      <Demo ref="demo"/>
      ......
      mounted(){this.$refs.xxx.$on('atguigu',this.test)
      }
      
  • 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

  • 触发自定义事件:this.$emit('atguigu',数据)

  • 解绑自定义事件this.$off('atguigu'),多个一起解绑套在一个数组里。this.$off() ,解绑所有的自定义事件。

  • 组件上也可以绑定原生DOM事件,需要使用native修饰符。

  • 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中要么用箭头函数,否则this指向会出问题!


🐇案例练习

  • 案例实现,实操见真知😄
  • Student-Test.vue
    <template><div class="student"><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2><h2>当前求和为:{{number}}</h2><button @click="add">点我number++</button><button @click="sendStudentlName">把学生名给App</button><button @click="unbind">解绑atguigu事件</button><button @click="death">销毁当前Student组件的实例(vc)</button></div>
    </template><script>export default {name:'Student-Test',data() {return {name:'右一',sex:'女',number:0}},methods: {add(){console.log('add回调被调用了')this.number++},sendStudentlName(){//触发Student组件实例身上的atguigu事件this.$emit('atguigu',this.name,666,888,900)// this.$emit('demo')// this.$emit('click')},unbind(){this.$off('atguigu') //解绑一个自定义事件console.log('解绑了')// this.$off(['atguigu','demo']) //解绑多个自定义事件(写在一个数组里)// this.$off() //解绑所有的自定义事件},death(){//销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。//和视频里展示的不一样,现在销毁后原生num++也不奏效了,不论是console还是响应式。this.$destroy() console.log('销毁了')}},}
    </script><style scoped>.student{background-color: pink;padding: 5px;margin-top: 30px;}
    </style>
    
  • School-Test.vue
    <template><div class="school"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2><button @click="sendSchoolName">把学校名给App</button></div>
    </template><script>export default {name:'School-Test',props:['getSchoolName'],data() {return {name:'哔哩哔哩大学',address:'bilibili',}},methods: {sendSchoolName(){this.getSchoolName(this.name)}},}
    </script><style scoped>.school{background-color: skyblue;padding: 5px;}
    </style>
    
  • App.vue
    <template><div class="app"><h1>{{msg}}学生姓名是:{{studentName}}</h1><!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 --><School :getSchoolName="getSchoolName"/><!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --><!-- <Student @atguigu="getStudentName" @demo="m1"/> --><!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --><Student ref="student" @click.native="show"/></div>
    </template><script>import Student from './components/Student-Test'import School from './components/School-Test'export default {name:'App',components:{School,Student},data() {return {msg:'你好啊!',studentName:''}},methods: {getSchoolName(name){console.log('App收到了学校名:',name)},getStudentName(name,...params){console.log('App收到了学生名:',name,params)this.studentName = name},m1(){console.log('demo事件被触发了!')},show(){alert(123)}},mounted() {this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件// this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)},}
    </script><style scoped>.app{background-color: gray;padding: 5px;}
    </style>
    
  • num++
    在这里插入图片描述
  • 发送学生名在这里插入图片描述
  • 解绑
    在这里插入图片描述
  • 解绑后学生名发不出去了
    在这里插入图片描述
  • 销毁
    在这里插入图片描述
  • num++可点击,但不奏效
    在这里插入图片描述

🐇TodoList案例优化

  • 所有涉及到子组件给父组件传输的:
    • 添加一个todo,addTodo
    • 底部全选,checkAllTodo
    • 清除已完成,clearAllTodo
    • addTodo为例,
      • 首先,在App.vue中把:addTodo="addTodo"改为@addTodo="addTodo"
      • 而后在UserHeader中把props去除(不用接收了)。
      • 功能实现处:
        // 通知APP组件去添加一个todo对象
        this.$emit('addTodo',todoObj)
        

📚全局事件总线

🐇使用方法

  1. 一种组件间通信的方式,适用于任意组件间通信

  2. 安装全局事件总线

    new Vue({......beforeCreate() {Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm},......
    }) 
    
  3. 使用事件总线

    • 接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身

      methods(){demo(data){......}
      }
      ......
      mounted() {this.$bus.$on('xxxx',this.demo)
      }
      
    • 提供数据:this.$bus.$emit('xxxx',数据)

  4. 最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件。


🐇案例练习

  • main.js:安装全局事件总线。
    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //关闭Vue的生产提示
    Vue.config.productionTip = false//创建vm
    new Vue({el:'#app',render: h => h(App),beforeCreate() {Vue.prototype.$bus = this //安装全局事件总线},
    })
    
  • Student-Test.vue:提供数据。
    <template><div class="student"><h2>学生姓名:{{name}}</h2><h2>学生性别:{{sex}}</h2><button @click="sendStudentName">把学生名给School组件</button></div>
    </template><script>export default {name:'Student-Test',data() {return {name:'youyi',sex:'女',}},methods: {sendStudentName(){this.$bus.$emit('hello',this.name)}},}
    </script><style scoped>.student{background-color: pink;padding: 5px;margin-top: 30px;}
    </style>
    
  • School-Test.vue:接收数据。
    <template><div class="school"><h2>学校名称:{{name}}</h2><h2>学校地址:{{address}}</h2></div>
    </template><script>export default {name:'School-Test',data() {return {name:'哔哩哔哩大学',address:'bilibili',}},mounted() {// console.log('School',this)this.$bus.$on('hello',(data)=>{console.log('我是School组件,收到了数据',data)})},beforeDestroy() {this.$bus.$off('hello')},}
    </script><style scoped>.school{background-color: skyblue;padding: 5px;}
    </style>
    
    在这里插入图片描述

🐇TodoList案例优化

  • 把“爷孙”之间的改成全局事件总线:
    • 勾选一个todo,checkTodo
    • 删除一个todo,deleteTodo
    • 修改点:
      • 在main.js安装全局事件总线
        new Vue({el:'#app',render: h => h(App),beforeCreate(){Vue.prototype.$bus = this}
        })
        
      • checkTododeleteTodo不用给List传了,List对应也不用接收了。同样的,List也不用给Item,后者也不收了。也就是之前的层级传递过程删掉。
      • 收数据的(App.vue)绑定事件总线。
        mounted(){this.$bus.$on('checkTodo',this.checkTodo)this.$bus.$on('deleteTodo',this.deleteTodo)
        },
        beforeDestroy(){this.$bus.$off('checkTodo')this.$bus.$off('deleteTodo')
        }
        
      • Item提供数据。
        methods:{// 勾选or取消勾选handleCheck(id){// 通知App组件将对应的todo对象的done值取反this.$bus.$emit('checkTodo',id)},// 删除handleDelete(id){if(confirm('确定删除吗?')){// 通知App组件删除this.$bus.$emit('deleteTodo',id)}}
        }
        

📚消息订阅与发布

🐇使用方法

  1. 一种组件间通信的方式,适用于任意组件间通信

  2. 使用步骤

    • 安装pubsub:npm i pubsub-js
    • 引入: import pubsub from 'pubsub-js'
    • 接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身
      methods(){demo(data){......}
      }
      ......
      mounted() {this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
      }
      
    1. 提供数据pubsub.publish('xxx',数据)

    2. 最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)取消订阅

🐇TodoList案例优化

⭐️把删除一个todo(deleteTodo)改成消息订阅与发布

  • 引入pubsub库(用到的vue都需要引入),import pubsub from 'pubsub-js'
  • App.vue需要数据,订阅消息。这里需要methods里deleteTodo(_,id)_占个位。
    mounted(){this.$bus.$on('checkTodo',this.checkTodo)this.pubId = pubsub.subscribe('deleteTodo',this.deleteTodo)
    },
    beforeDestroy(){this.$bus.$off('checkTodo')pubsub.unsubscribe(this.pubId)
    }
    
  • UserItem.vue提供数据。
    methods:{// 勾选or取消勾选handleCheck(id){// 通知App组件将对应的todo对象的done值取反this.$bus.$emit('checkTodo',id)},// 删除handleDelete(id){if(confirm('确定删除吗?')){// 通知App组件删除pubsub.publish('deleteTodo',id)}}
    }
    

⭐️添加编辑todo效果

  • UserItem.vue样式添加编辑按钮。
    在这里插入图片描述
  • UserItem.vue
    <template><li><label><input type="checkbox" :checked="fasong.done" @change="handleCheck(fasong.id)"/><span v-show="!fasong.isEdit">{{fasong.title}}</span><input type="text" v-show="fasong.isEdit" :value="fasong.title"@blur="handleBlur(fasong,$event)"></label><button class="btn btn-danger" @click="handleDelete(fasong.id)">删除</button><button v-show="!fasong.isEdit" class="btn btn-edit" @click="handleEdit(fasong)">编辑</button></li>
    </template><script>import pubsub from 'pubsub-js'export default {name:'UserItem',// 声明接收发送内容props:['fasong'],methods:{// 勾选or取消勾选handleCheck(id){// 通知App组件将对应的todo对象的done值取反this.$bus.$emit('checkTodo',id)},// 删除handleDelete(id){if(confirm('确定删除吗?')){// 通知App组件删除pubsub.publish('deleteTodo',id)}},//编辑handleEdit(fasong){// 已经有了isEditif(fasong.hasOwnProperty.call('isEdit')){fasong.isEdit = true}else{this.$set(fasong,'isEdit',true)}},// 失去焦点回调(真正执行修改)handleBlur(fasong,e){fasong.isEdit = falsethis.$bus.$emit('updateTodo',fasong.id,e.target.value)}}}
    </script>
    
  • App.vue
    <template><div id="root"><div class="todo-container"><div class="todo-wrap"><UserHeader @addTodo="addTodo"></UserHeader><UserList :todos="todos"></UserList><UserFooter :todos="todos" @checkAllTodo="checkAllTodo" @clearAllTodo="clearAllTodo"></UserFooter></div></div></div></template><!-- App.vue -->
    <script>import pubsub from 'pubsub-js'import UserHeader from './components/UserHeader.vue'import UserList from './components/UserList'import UserFooter from './components/UserFooter'export default {name:'App',components:{UserHeader,UserList,UserFooter},data(){return{todos:JSON.parse(localStorage.getItem('todos')) || []}},methods:{// 数据在哪,对数据的操作就在哪// 添加一个todoaddTodo(todoObj){this.todos.unshift(todoObj)},// 勾选or取消勾选一个todocheckTodo(id){this.todos.forEach((todo)=>{if(todo.id === id) todo.done = !todo.done})},// 修改一个todoupdateTodo(id,title){this.todos.forEach((todo)=>{if(todo.id === id) todo.title = title})},// 删除一个tododeleteTodo(_,id){// this.todos = this.todos.filter((todo)=>{// 	return todo.id !== id// })// 精简写法this.todos = this.todos.filter(todo => todo.id != id)},// 全选or取消全选checkAllTodo(done){this.todos.forEach((todo)=>{todo.done = done})},// 清除所有已经完成的todoclearAllTodo(){this.todos = this.todos.filter((todo)=>{return !todo.done})}},watch:{todos:{// 开启深度监视deep:true,handler(value){localStorage.setItem('todos',JSON.stringify(value))}}},mounted(){this.$bus.$on('checkTodo',this.checkTodo)this.$bus.$on('updateTodo',this.updateTodo)this.pubId = pubsub.subscribe('deleteTodo',this.deleteTodo)},beforeDestroy(){this.$bus.$off('checkTodo')this.$bus.$off('updateTodo')pubsub.unsubscribe(this.pubId)}}
    </script>
    
    • 准备编辑
      在这里插入图片描述
    • 正在编辑(按钮不显示)
      在这里插入图片描述
    • 焦点移除,修改
      在这里插入图片描述

⭐️内容不为空限制

// 失去焦点回调(真正执行修改)
handleBlur(fasong,e){fasong.isEdit = falseif(!e.target.value.trim()) return alert('输入不能为空')this.$bus.$emit('updateTodo',fasong.id,e.target.value)
}

在这里插入图片描述

⭐️点击编辑按钮自动获取焦点

this.$nextTick(function(){this.$refs.inputTitle.focus()
})
  • 🔥 nextTick
    • 语法:this.$nextTick(回调函数)
    • 作用:在下一次 DOM 更新结束后执行其指定的回调。
    • 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

📚Vue封装的过度与动画

🐇使用方法

  1. 作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名。
  2. 写法
    • 准备好样式

      • 元素进入的样式:
        • v-enter:进入的起点
        • v-enter-active:进入过程中
        • v-enter-to:进入的终点
      • 元素离开的样式:
        • v-leave:离开的起点
        • v-leave-active:离开过程中
        • v-leave-to:离开的终点
          在这里插入图片描述
    • 使用<transition>包裹要过度的元素,并配置name属性:

      <transition name="hello"><h1 v-show="isShow">你好啊!</h1>
      </transition>
      
    • 备注:若有多个元素需要过度,则需要使用:<transition-group>,且每个元素都要指定key值。

🐇案例练习

  • 过度效果

    <template><div><button @click="isShow = !isShow">显示/隐藏</button><transition name="hello" appear><h1 v-show="isShow">你好啊!</h1></transition></div>
    </template><script>export default {name:'Final-Test',data() {return {isShow:true}},}
    </script><style scoped>h1{background-color: pink;}.hello-enter-active{animation: atguigu 0.5s linear;}.hello-leave-active{animation: atguigu 0.5s linear reverse;}@keyframes atguigu {from{transform: translateX(-100%);}to{transform: translateX(0px);}}
    </style>
    
  • 多个元素过度

    <template><div><button @click="isShow = !isShow">显示/隐藏</button><transition-group name="hello" appear><h1 v-show="!isShow" key="1">你好啊!</h1><h1 v-show="isShow" key="2">尚硅谷!</h1></transition-group></div>
    </template><script>export default {name:'Final-Test2',data() {return {isShow:true}},}
    </script><style scoped>h1{background-color: skyblue;}/* 进入的起点、离开的终点 */.hello-enter,.hello-leave-to{transform: translateX(-100%);}.hello-enter-active,.hello-leave-active{transition: 0.5s linear;}/* 进入的终点、离开的起点 */.hello-enter-to,.hello-leave{transform: translateX(0);}
    </style>
    
  • 集成第三方动画,animate.css官网

    <template><div><button @click="isShow = !isShow">显示/隐藏</button><transition-group appearname="animate__animated animate__bounce" enter-active-class="animate__swing"leave-active-class="animate__backOutUp"><h1 v-show="!isShow" key="1">你好啊!</h1><h1 v-show="isShow" key="2">尚硅谷!</h1></transition-group></div>
    </template><script>// npm install animate.cssimport 'animate.css'export default {name:'Final-Test3',data() {return {isShow:true}},}
    </script><style scoped>h1{background-color: rgb(0, 255, 183);}
    </style>
    

在这里插入图片描述

🐇TodoList案例优化

  • 让每一个todo的添加和删除都很柔和
    • 法①:UserItem.vue的整个li加过度和动画
    • 法②:在UserList.vue添加(关注多组是transition-group)(以下代码实现方式)
  • 结构部分
    <template><ul class="todo-main"><transition-group name="todo" appear><UserItem v-for="todoObj in todos" :key="todoObj.id" :fasong="todoObj" ></UserItem></transition-group></ul>
    </template>
    
  • 样式部分
    .todo-enter-active{animation: atguigu 0.5s linear;}.todo-leave-active{animation: atguigu 0.5s linear reverse;}@keyframes atguigu {from{transform: translateX(100%);}to{transform: translateX(0px);}}
    

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

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

相关文章

React18源码: Fiber树的初次创建过程图文详解

fiber树构造&#xff08;初次创建&#xff09; fiber树构造的2种情况&#xff1a; 1.初次创建 在React应用首次启动时&#xff0c;界面还没有渲染此时并不会进入对比过程&#xff0c;相当于直接构造一棵全新的树 2.对比更新 React应用启动后&#xff0c;界面已经渲染如果再次发…

微信小程序 --- 分包加载

分包加载 1. 什么是分包加载 什么是分包加载 ❓ 小程序的代码通常是由许多页面、组件以及资源等组成&#xff0c;随着小程序功能的增加&#xff0c;代码量也会逐渐增加&#xff0c;体积过大就会导致用户打开速度变慢&#xff0c;影响用户的使用体验。 分包加载是一种小程序…

遗传算法(Genetic Algorithm,GA)求解不闭合多旅行商问题(提供MATLAB代码)

一、遗传算法&#xff08;GA&#xff09;介绍 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;是一种模拟自然界生物进化过程的优化算法。它通过模拟生物的遗传、变异和选择等机制&#xff0c;来搜索问题的最优解。 遗传算法的基本思想是通过对候选解进行编…

stable diffusion学习笔记 手部修复

图片手部修复原理 某张图片在生成后&#xff0c;仅有手部表现不符合预期&#xff08;多指&#xff0c;畸形等&#xff09;。这种情况下我们通常使用【局部重绘】的方式对该图片的手部进行【图生图】操作&#xff0c;重新绘制手部区域。 但是仅采用重绘的方式也很难保证生成的…

笔记本如何录屏?很简单,我来告诉你

“最近遇到了一些工作上的问题&#xff0c;需要录制一些会议和讨论的内容&#xff0c;以便于后续的整理和回顾。但是&#xff0c;我没有使用过笔记本进行录屏&#xff0c;不知道该如何操作。大家有没有简单易懂的笔记本录屏指南&#xff0c;教教我&#xff01;” 在当今数字化…

选择VR全景行业,需要了解哪些内容?

近年来&#xff0c;随着虚拟现实、增强现实等技术的持续发展&#xff0c;VR全景消费市场得以稳步扩张。其次&#xff0c;元宇宙行业的高速发展&#xff0c;也在进一步拉动VR全景技术的持续进步&#xff0c;带动VR产业的高质量发展。作为一种战略性的新兴产业&#xff0c;国家和…

多重网格(Multigrid Method)-4

代数多重网格法简介&#xff08;Algebraic Multigrid&#xff09; 可以理解为对细网格上的方程&#xff0c;先使用光滑方法&#xff08;Gm&#xff09;进行迭代得到一个初始解&#xff0c;然后将这个初始解的残差乘限制算子转化到粗网格上得到粗网格的右端向量&#xff0c;再在…

流浪动物救助平台:Java开发的实践与思考

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

03_第三章 JavaScript(数据类型和运算符,流程控制和函数,JS的对象和JSON,事件的绑定,BOM编程,DOM编程,正则表达式)

文章目录 第三章 JavaScript一 JS简介1.1 JS起源JavaScript是一种基于对象的脚本语言&#xff0c;它不仅可以创建对象&#xff0c;也能使用现有的对象。但是面向对象的三大特性&#xff1a;『封装』、『继承』、『多态』中&#xff0c;JavaScript能够实现封装&#xff0c;可以模…

第十篇【传奇开心果系列】Python的文本和语音相互转换库技术点案例示例:Microsoft Azure开发语音翻译应用程序经典案例

传奇开心果博文系列 系列博文目录Python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、雏形示例代码二、扩展思路介绍三、Azure多语种支持示例代码四、Azure实时对话模式示例代码五、Azure自定义翻译模型示例代码六、Azure语音合成示例代码七、Azure用户界面优化示…

多输入回归预测|WOA-CNN|鲸鱼算法优化的卷积神经网络回归预测(Matlab)

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分程序&#xff1a; 四、完整程序数据下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matalb平台编译…

【摸鱼日常】使用Docker部署2048小游戏

一、本次实践介绍 ​1. 本次实践简介 本次实践部署环境为个人测试环境&#xff0c;快速使用docker部署2048小游戏。 rootWellDone:/home/goodjob# uname -aLinux WellDone 6.5.0-14-generic #14~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon Nov 20 18:15:30 UTC 2 x86_64 x86_64…

python自动化管理和zabbix监控网络设备(有线网络配置部分)

目录 一、拓扑图 二、core-sw1 三、core-sw2 四、sum-sw1 五、sum-sw2 一、拓扑图 二、core-sw1 sys sysname core-sw1 vlan batch 10 20 30 40 50 60 100 vlan batch 200 210 220 230 240 250 stp region-configuration region-name huawei revision-level 1 instance…

【深度学习】CIFAR10图像分类

案例3&#xff1a;PyTorch实战: CIFAR10图像分类 1 任务目标 1.1 用多层感知机(MLP)和卷积网络(ConvNet)完成CIFAR10分类 使用PyTorch分别实现多层感知机(MLP)和卷积网络(ConvNet)&#xff0c;并完成CIFAR10数据集&#xff08;http://www.cs.toronto.edu/~kriz/cifar.html&a…

力扣--哈希表/滑动窗口/双指针3.无重复字符的最长子串

思路分析&#xff1a; 使用双指针 i 和 j 表示子串的起始位置和结束位置。遍历字符串 s&#xff0c;对于每个字符&#xff1a; 如果字符不在 hash 中&#xff0c;将其加入 hash&#xff0c;同时更新最长子串的长度 result。如果字符已经在 hash 中&#xff0c;说明有重复字符出…

MyBatis使⽤PageHelper(MySQL)

MyBatis使⽤PageHelper&#xff08;MySQL&#xff09; 一、 limit分⻚二、PageHelper插件第⼀步&#xff1a;引⼊依赖第⼆步&#xff1a;在mybatis-config.xml⽂件中配置插件第三步&#xff1a;编写Java代码第四步&#xff1a;格式化结果查看 三、SpringBoot3 集成 PageHelper …

【Vue3】学习watch监视:深入了解Vue3响应式系统的核心功能(上)

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

AcWing算法基础课笔记 ------ 第二章 数据结构

本篇记录一下AcWing上第二章的笔记&#xff0c;这一章收获也很多&#xff0c;学会了用数组去模拟链表&#xff0c;复习了一遍KMP&#xff0c;求表达式&#xff0c;以及新的一些数据结构&#xff0c;字典树&#xff0c;并查集&#xff0c;还有更为高效的哈希表。 文章目录 一. …

正则表达式详细使用教程

正则是用于匹配字符串中字符组合的模式&#xff0c;在js中&#xff0c;正则也是对象。 定义正则的两种方式&#xff1a; 1.const 变量名new RegExp(/表达式/) <script>const req new RegExp(/a/)console.log(req.test("asd"))//true</script> 2.con…

(Linux学习一):Mac安装vmWare11.5,centOS 7安装步骤教程

一。下载vmware 官网地址&#xff1a;下载地址 由于我的电脑系统是Mac 10.15.6版本系统&#xff0c;我下载的是VMware Fusion 11.5版本&#xff0c;13是最新版本不支持安装需要系统在11以上。 百度网盘下载地址: VMware Fusion 11 VMware Fusion 12 VMware Fusion 13 下载需要…