VUE3版本新特性
VUE3版本新特性
- VUE3和VUE2的区别
- 路由的使用
- vite安装项目
- 新特性使用
1.VUE3和VUE2的区别
2020年9月18日,Vue.js发布版3.0版本,代号:One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。体积更小 Vue3.0 打包大小减少41%。 同时Vue3可以更好的支持TypeScript。 vue3中文文档:Vue.js : https://cn.vuejs.org/,vue2和vue3的主要区别在于以下几点:1、生命周期函数钩子不同
beforeCreate -> setup() 开始创建组件之前,创建的是data和method
created -> setup()
beforeMount -> onBeforeMount 组件挂载到节点上之前执行的函数。
mounted -> onMounted 组件挂载完成后执行的函数
beforeUpdate -> onBeforeUpdate 组件更新之前执行的函数。
updated -> onUpdated 组件更新完成之后执行的函数。
beforeDestroy -> onBeforeUnmount 组件挂载到节点上之前执行的函数。
destroyed -> onUnmounted 组件卸载之前执行的函数。
activated -> onActivated 组件卸载完成后执行的函数
deactivated -> onDeactivated 在组件切换中老组件消失的时候执行
2、数据双向绑定原理不同
| VUE2 | VUE3 |
|---|---|
| 利用ES5的一个APIObject.defineProperty()对数据进行劫持,结合发布者订阅者模式的方式来实现的。 | 使用了ES6的Proxy API对数据代理。 |
vue3提供的proxy API代理的优势在于:
- defineProperty只能监听某个属性,不能对全对象监听
- 可以省去for…in,闭包等内容来提升效率(直接绑定整个对象即可)
- 可以监听数组,不再单独的对数组做特异性处理。可以检测到数组内部数据的变化。
3、定义变量和方法不同
| vue2 | vue3 |
|---|---|
| 在data中定义变量,在methods中创建方法 | 使用一个新的setup方法 |
vue3提供的setup方法在组件初始化构造的时候触发,使用以下三个步骤建立反应性数据:
-
从vue引入reactive
-
使用reactive方法来声明数据为响应性数据
-
使用setup方法返回响应性数据,从而template可以获取这些响应式数据。
<script> export default { setup(){// 数据和方法都写这里,更简洁const user = "username";const met = ()=>{} } } </script>
4、API类型不同
| vue2 | vue3 |
|---|---|
| 选项型api(在代码中分割不同属性:data,computed,methods等) | 组合型api(使用方法进行分隔,显得更加简便整洁) |
5、是否支持碎片
| vue2 | vue3 |
|---|---|
| 否 | 是,即可以拥有多个根节点 |
<template><div><h1></h1><div><div><h1></h1><div>
</template>
6、父子之间传参不同
| vue2 | vue3 |
|---|---|
| 父传子:子组件通过prop接收子传父:子组件中通过$emit向父组件触发一个监听方法,传递一个参数 | 使用setup()中的第二个参数content对象中有emit,只需要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。 |
7、v-if 和 v-for的优先级
| VUE2 | VUE3 |
|---|---|
| v-for 优先于 v-if 生效 | v-if 优先于 v-for 生效 |
2.使用Vite创建项目
在VUE3中使用vite来创建项目而不再使用 vue-cli,初始化项目 ,vite 是新一代前端构建工具,官网地址:https://vitejs.cn,vite的优势如:
-
轻量快速的热重载(
HMR),能实现极速的服务启动。 -
对
TypeScript、JSX、CSS等支持开箱即用。 -
真正的按需编译,不再等待整个应用编译完成。注意:Vite 需要 Node.js 版本 >= 12.0.0。【使用nvm安装 node 18.14.2】

注意:还需要去设置仓库地址: npm config set registry https://registry.npmmirror.com在VUE2中使用npm进行包的管理,在VUE3中pnpm进行包的管理,首先我们需要安装 pnpm
- 安装pnpm :
在磁盘上创建一个文件夹,如: vue3-demo,然后进入目录,使用cmd窗口执行命令如下:
npm i pnpm -g
-
安装vite : 执行下面命令,按照提示完成项目创建
pnpm create vite@latest 或者 yarn create vite
1.输入项目名字,默认为vue3-demo2.选择创建的项目类型,选择vue即可3.选择创建的vue项目类型, TypeScript4.启动项目
命令 : pnpm create vite@latest 执行效果如下
- 也可以使用 : npm init vite@latest
3. 安装依赖: `进入到创建好的项目中`执行命令 pnpm i
```shell
pnpm icnpm install
- 启动项目
-
启动命令看 package.json -> scripts { … }
pnpm dev访问控制台地址,启动效果如下
然后使用开发工具,导入创建好的项目
3.项目结构认识
├── dist/ //代码编译目录
└── src/├── api/ // 接口请求目录├── assets/ // 静态资源目录├── common/ // 通用类库目录├── components/ // 公共组件目录├── router/ // 路由配置目录├── store/ // 状态管理目录├── style/ // 通用样式目录├── utils/ // 工具函数目录├── views/ // 页面组件目录├── App.vue├── main.ts //主ts
├── tests/ // 单元测试目录
├── index.html //默认首页,入口页面
├── jsconfig.json // JavaScript 配置文件
├── vite.config.js // Vite 配置文件
└── package.json //依赖管理
└── vite.config.ts
4.route的使用
4.1.安装route路由
官网:https://router.vuejs.org/zh/installation.html
pnpm install vue-router@4

4.2.创建页面
在src目录下创建views/order/order.vue 以及 views/user/user.vue 页面文件,内容如下
<script setup lang="ts"></script><template><div>11111111111111</div>
</template><style scoped>
</style>
----
4.3.创建router
在src目录下创建router/index.ts文件,内容如下
import { createRouter, createWebHashHistory } from 'vue-router'const router = createRouter({history: createWebHashHistory(),routes: [{path:"/",name:"home",component:()=>import("../views/User.vue")},{path:"/test",name:"test",component:()=>import("../views/Order.vue"),}],})export default router
-
createWebHashHistory: hash 模式下使用的是createWebHashHistoryapi 进行配置 VueRouter 的历史模式。使用 hash 模式下会在浏览器网页路由当中使用哈希字符(#)对 url 进行切割并且匹配哈希字符后的字符进行判断路由匹配与跳转处理。
4.4.在main.js中使用路由
...省略...
//导入路由import { createApp } from 'vue’import router from ‘./router/index’
//创建appconst app = createApp(App);
//使用路由app.use(router)
//挂载appapp.mount(‘#app’)
#### 4.5.在App.vue文件中指定路由出口
```vue
<template><div><!-- 路由出口 ,所有页面都会放到这个里面--><router-view></router-view></div>
</template>
4.6.重启测试
5.vue的核心语法
5.1 简单入门
Vue3向下兼容Vue2语法,且Vue3中的模板中可以没有根标签
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年龄+1</button><button @click="showTel">点我查看联系方式</button></div>
</template><script lang="ts">export default {name:'App',data() {return {name:'张三',age:18,tel:'13888888888'}},methods:{changeName(){this.name = 'zhang-san'},changeAge(){this.age += 1},showTel(){alert(this.tel)}},}
</script>
5.2 Setup函数
在学习以下知识之前我们先了解一下 options api 和 composition api的区别:vue2中使用的是optionsAPI,来定义一个组件内部的一些属性,如methods、data等等;其缺点往往会在大项目中体现出来,比如一个简单的计数器功能,可能需要在methods内部书写一部分逻辑,在computed内部也书写一部分逻辑,那么问题来了:如果该组件内部有n个这样的小功能,那么此时代码逻辑是十分分散的,并且后期迭代维护面临的问题也是可能修改一个需求需要在不同的属性内部反复查找相关的代码,而compositionAPI的出现就是为了解决这一问题的。
vue3新增的compositionAPI主要就是为了解决API太过于分散的问题,避免一个功能点下的api太过于分散不便于维护,将同一个功能下的api统一放到一个地方,这样一来项目的开发和维护就简便多了。compositionAPI也叫做组合式API,vue3中组合式API的入口就是setup函数; 
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bc0be8211fc54b6c941c036791ba4efe~tplv-k3u1fbpfcp-watermark.image
setup是Vue3中一个新的配置项,值是一个函数,它是 Composition API “表演的舞台”,组件中所用到的:数据、方法、计算属性、监视…等等,均配置在setup中。
特点如下:
setup函数返回的对象中的内容,可直接在模板中使用。setup中访问this是undefined。setup函数会在beforeCreate之前调用,它是“领先”所有钩子执行的。
5.1.普通写法[不推荐]
通过 export default { setup(){ } } 来定义setup函数 , 这种方式不推荐
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年龄+1</button><button @click="showTel">点我查看联系方式</button></div>
</template><script lang="ts">export default {name:'Person',setup(){// 数据,原来写在data中(注意:此时的name、age、tel数据都不是响应式数据)let name = '张三'let age = 18let tel = '13888888888'// 方法,原来写在methods中function changeName(){name = 'zhang-san' //注意:此时这么修改name页面是不变化的console.log(name)}function changeAge(){age += 1 //注意:此时这么修改age页面是不变化的console.log(age)}function showTel(){alert(tel)}// 返回一个对象,对象中的内容,模板中可以直接使用return {name,age,tel,changeName,changeAge,showTel}}}
</script>
5.2.语法糖[推荐]
注意:在setup语法中使用 this 会出现unidefined , 在 `setup` 中你应该避免使用 `this`,因为它不会找到组件实例。`setup` 的调用发生在 `data` property、`computed` property 或 `methods` 被解析之前,所以它们无法在 `setup` 中被获取,这也是为了避免setup()和其他选项式API混淆。### 6.数据响应函数
什么是响应式:响应式指的是,把数据绑定当视图,当数据的值发生改变,视图也会跟着重新渲染。
#### 6.1.ref:基础数据响应式函数
VUE3提供了ref函数可以在修改完 数据后自动渲染视图,类似余双向绑定- 在js中通过 import {ref} from "vue"; 来声明 ref函数
- 注意:ref属性在js中要使用.value 取值
```javascript
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年龄:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年龄+1</button><button @click="showTel">点我查看联系方式</button></div>
</template><script setup lang="ts" name="Person">import {ref} from 'vue'// name和age是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的。let name = ref('张三')let age = ref(18)// tel就是一个普通的字符串,不是响应式的let tel = '13888888888'function changeName(){// JS中操作ref对象时候需要.valuename.value = '李四'console.log(name.value)// 注意:name不是响应式的,name.value是响应式的,所以如下代码并不会引起页面的更新。// name = ref('zhang-san')}function changeAge(){// JS中操作ref对象时候需要.valueage.value += 1 console.log(age.value)}function showTel(){alert(tel)}
</script>
通过ref获取dom对象
<template><input ref="inputRef" :value="refValue"/>
</template><script setup>import {ref} from "vue";//变量名 inputRef 和 dom元素上的ref="inputRef" 一样,就能获取到dom元素let inputRef = ref(null);console.log(inputRef);</script>
6.2.reactive创建:对象类型的响应式数据
对于对象类型可以使用reactive进行响应式函数处理
<template><div class="person"><h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2><h2>游戏列表:</h2><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul><h2>测试:{{obj.a.b.c.d}}</h2><button @click="changeCarPrice">修改汽车价格</button><button @click="changeFirstGame">修改第一游戏</button><button @click="test">测试</button></div>
</template><script lang="ts" setup name="Person">
import { reactive } from 'vue'// 数据
let car = reactive({ brand: '奔驰', price: 100 })
let games = reactive([{ id: 'ahsgdyfa01', name: '英雄联盟' },{ id: 'ahsgdyfa02', name: '王者荣耀' },{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = reactive({a:{b:{c:{d:666}}}
})function changeCarPrice() {car.price += 10
}
function changeFirstGame() {games[0].name = '流星蝴蝶剑'
}
function test(){obj.a.b.c.d = 999
}
</script>
注意:其实ref接收的数据可以是:基本类型、对象类型。若ref接收的是对象类型,内部其实也是调用了reactive函数
例如:
<template><div class="person"><h2>汽车信息:一台{{ car.brand }}汽车,价值{{ car.price }}万</h2><h2>游戏列表:</h2><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul><h2>测试:{{obj.a.b.c.d}}</h2><button @click="changeCarPrice">修改汽车价格</button><button @click="changeFirstGame">修改第一游戏</button><button @click="test">测试</button></div>
</template><script lang="ts" setup name="Person">
import { ref } from 'vue'// 数据
let car = ref({ brand: '奔驰', price: 100 })
let games = ref([{ id: 'ahsgdyfa01', name: '英雄联盟' },{ id: 'ahsgdyfa02', name: '王者荣耀' },{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = ref({a:{b:{c:{d:666}}}
})console.log(car)function changeCarPrice() {car.value.price += 10
}
function changeFirstGame() {games.value[0].name = '流星蝴蝶剑'
}
function test(){obj.value.a.b.c.d = 999
}
</script>
对比:
ref用来定义:基本类型数据、对象类型数据;reactive用来定义:对象类型数据。ref创建的变量必须使用.valuereactive重新分配一个新对象,会失去响应式
7.toRef 和 toRefs【了解】
7.1.toRef解析响应式
将一个响应式对象中的每一个属性,转换为ref对象,toRefs与toRef功能一致,但toRefs可以批量转换。
<template><div class="person"><h2>姓名:{{person.name}}</h2><h2>年龄:{{person.age}}</h2><h2>性别:{{person.gender}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年龄</button><button @click="changeGender">修改性别</button></div>
</template><script lang="ts" setup name="Person">import {ref,reactive,toRefs,toRef} from 'vue'// 数据let person = reactive({name:'张三', age:18, gender:'男'})// 通过toRefs将person对象中的n个属性批量取出,且依然保持响应式的能力let {name,gender} = toRefs(person)// 通过toRef将person对象中的gender属性取出,且依然保持响应式的能力let age = toRef(person,'age')// 方法function changeName(){name.value += '~'}function changeAge(){age.value += 1}function changeGender(){gender.value = '女'}
</script>
8.computed计算函数
下面通过计算函数演示2个值相加,需要通过 import {computed} from “vue”; 引入函数
<template><div class="person">姓:<input type="text" v-model="firstName"> <br>名:<input type="text" v-model="lastName"> <br>全名:<span>{{fullName}}</span> <br><button @click="changeFullName">全名改为:li-si</button></div>
</template><script setup lang="ts" name="App">import {ref,computed} from 'vue'let firstName = ref('zhang')let lastName = ref('san')// 计算属性——只读取,不修改/* let fullName = computed(()=>{return firstName.value + '-' + lastName.value}) */// 计算属性——既读取又修改let fullName = computed({// 读取get(){return firstName.value + '-' + lastName.value},// 修改set(val){console.log('有人修改了fullName',val)firstName.value = val.split('-')[0]lastName.value = val.split('-')[1]}})function changeFullName(){fullName.value = 'li-si'}
</script>
9.watch监听器
watch的作用是用来监听某个值的变化从而出发watch回调。watch可以:
-
监听单体数据
-
监听对象
-
监听对象的某个属性
-
监听多个数据
<template><div class="watch"></div><button @click="value++">修改value</button><button @click="persion.age++">修改persion</button> </template> <script setup>
import {reactive, ref, watch} from “vue”;
const value = ref(1111);const persion = reactive({ username:“zs” , age:18})//监听单个值watch(value,()=>{ console.log(value);})//监听对象watch(persion,()=>{ console.log(persion);})
//监听多个,用[]包含多个watch([persion,value],()=>{ console.log(persion,value);});
//监听对象的属性 watch(persion.age,()=>{ console.log(persion);});
watch如果监听对象,可以深度监听(即:对象中又深度嵌套了对象,嵌套的对象值被修改也会被监听到)
### 10.watchEffect监听副作用[了解]
立即运行一个函数,同时响应式地追踪其依赖,并在依赖更改时重新执行该函数。watchEffect的作用是只要使用到的数据都会被监听到,无需指定具体监听谁,他包含4个功能- 页面加载,watchEffect的回调就会立即执行
- 只要watchEffect 只要里面使用了任何数据,就会触发回到函数
- onCleanup函数可以清除副作用
- 返回一个stopHandler可以停止监听
```vue
<template><div class="watch_effect"></div><button @click="num++">num++</button><button @click="stopHandler">StopWatch</button>
</template><script setup>import {ref, watchEffect} from "vue";const num = ref(1111);//1.页面加载,初始化立即回执行回调
//2.只要watchEffect 只要里面使用了数据,就会触发回到函数
//3.onCleanup函数可以清除副作用
//4.返回一个stopHandler可以停止监听
/**
watchEffect(()=>{console.log(num.value);
})**/const stopHandler = watchEffect(onCleanup=>{console.log(num.value);onCleanup(()=>{console.log("清除副作用");});
})</script>
11.生命周期方法
因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。下表包含如何在 setup () 内部调用生命周期钩子:
| 选项式 API(VUE2) | Hook inside setup |
|---|---|
beforeCreate | Not needed* 不需要 |
created | Not needed* 不需要 |
beforeMount | onBeforeMount |
| 挂载之前 | |
mounted | onMounted |
| 页面加载完成时执行 | |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
| 页面销毁时执行 | |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
下面是代码案例
<script setup>
import {onBeforeMount, onBeforeUnmount, onMounted, onUnmounted} from "vue";console.log("初始化")
onMounted(()=>{console.log("onMounted 挂载中...");
})onBeforeMount(()=>{console.log("onBeforeMount 挂载前....");
})
onUnmounted(()=>{console.log("onUnmounted 当销毁..")
})
onBeforeUnmount(()=>{console.log("onBeforeUnmount 当销毁前..")
})
</script>
12.父子组件[重点]
12.1.父传参数给子
第一步:创建一个父组件页面,引入子组件,并传入参数 parent.vue
<template><H1 class="parent_child">父传子</H1><h2>使用子组件传参</h2><child-vue text="传入静态文本" :num="num" :title="title" :persion="persion"></child-vue>
</template><script setup>//引入子组件取名用驼峰,页面用中划线 <child-vue></child-vue>
import ChildVue from "@/views/parent_child/child.vue";
import {reactive, ref} from "vue";//构建一个响应式对象
const persion = reactive({username:"zs",age:18
})
//定义响应式变量
const title = ref("我是标题");
const num = ref(111);
</script>
第二步:创建一个子组件页面 : child.vue , 通过 defineProps接受父传入的参数
<template><h2>text:{{text}}</h2><h2>num:{{num}}</h2><h2>title:{{title}}</h2><h2>persion:{{persion}}</h2>
</template><script setup>
//通过defineProps来接受父传入过来的参数
const prop = defineProps({text:String,num:Number,title:String,persion:Object
})
//在js中可以读取父传入过来的参数,但是不能修改
console.log("prop.title" , prop.title)</script>
注意:在子组件中没法修改父转件传入的参数
12.2.子传参给父
子组件给父组件传值,需要通过defineEmits在子组件声明事件方法,然后调用该事件方法传值,父组件需要监听该事件方法取值。第一步:在子组件中准备一个按钮,点击按钮就给父组件传值。然后给按钮绑定一个方法。
<h1>给父组件传参</h1>
<button @click="sendData2Parent">给父组件传参</button>------------------------------------------------------------------------------------------//声明事件
const $emits = defineEmits(["data2parent","事件名","事件名"]);const sendData2Parent = ()=>{//调用声明的事件$emits('data2parent',"传给父组件的数据");
}
- const $emits = defineEmits([“data2parent”,“事件2”,“事件3”]); 自定义了三个事件
- $emits(‘data2parent’,“传给父组件的数据”); 调用自定义的事件
第二步:在父组件中绑定该事件,并调用一个函数来接受值
<child-vue @data2parent="getDataFromChild" ...></child-vue>const getDataFromChild = (data)=>{console.log("打印数据",data);
}
-
@data2parent=“getDataFromChild” : data2parent对应了子组件中声明的事件,拿到数据后交给getDataFromChild去处理。
12.3.子暴露
VUE3提供了 defineExpose 来暴露子组件中的数据和方法在父组件中可以拿到子组件中暴露的数据或者方法。第一步在子组件中暴露数据
//子暴露 defineExpose({data:"我是子暴露的数据",sayHi:()=>{return "我是子暴露的方法被调用返回的结果";} })第二步:在父组件接受子暴露的数据
<child-vueref="childVueRef" ...></child-vue>
//用一个响应式变量,接受子暴露的数据const childVueRef = ref(null);onMounted(()=>{ console.log(“子暴露的数据:”,childVueRef.value.data); console.log(“子暴露的方法:”,childVueRef.value.sayHi());})
- ref="childVueRef" : 接受子暴露,把数据绑定给childVueRef注意:因为在父组件的 setup 函数中,声明周期很早,此时子组件还没加载,所以需要在onMounted去调用子暴露的数据和方法才可以拿到结果。### 13.自定义Hooks函数
**hooks就是用来给我们抽取公共代码的**,hooks函数就是通过 use开头的js参数 。 自定义`hook`的优势:复用代码, 让`setup`中的逻辑更清楚易懂。
代码如下: useSum.ts```js
import {ref,onMounted} from 'vue'export default function(){let sum = ref(0)const increment = ()=>{sum.value += 1}const decrement = ()=>{sum.value -= 1}onMounted(()=>{increment()})//向外部暴露数据return {sum,increment,decrement}
}
useDog.ts中内容如下
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'export default function(){let dogList = reactive<string[]>([])// 方法async function getDog(){try {// 发请求let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')// 维护数据dogList.push(data.message)} catch (error) {// 处理错误const err = <AxiosError>errorconsole.log(err.message)}}// 挂载钩子onMounted(()=>{getDog()})//向外部暴露数据return {dogList,getDog}
}
组件中使用:
<template><h2>当前求和为:{{sum}}</h2><button @click="increment">点我+1</button><button @click="decrement">点我-1</button><hr><img v-for="(u,index) in dogList" :key="index" :src="u"> <span v-show="dogList.isLoading">加载中......</span><br><button @click="getDog">再来一只狗</button>
</template><script lang="ts">import {defineComponent} from 'vue'export default defineComponent({name:'App',})
</script><script setup lang="ts">import useSum from './hooks/useSum'import useDog from './hooks/useDog'let {sum,increment,decrement} = useSum()let {dogList,getDog} = useDog()
</script>
相关文章:
VUE3版本新特性
VUE3版本新特性 VUE3和VUE2的区别路由的使用vite安装项目新特性使用 1.VUE3和VUE2的区别 2020年9月18日,Vue.js发布版3.0版本,代号:One Piece 于 2022 年 2 月 7 日星期一成为新的默认版本! Vue3性能更高,初次渲染快55%, 更新渲染快133% 。…...
【Oracle篇】Oracle数据库坏块处理:rman修复坏块实践与案例分析(第七篇,总共八篇)
💫《博主介绍》:✨又是一天没白过,我是奈斯,DBA一名✨ 💫《擅长领域》:✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux,也在扩展大数据方向的知识面✌️…...
学懂C#编程:从一个简单的例子理解事件处理
在C#中,事件是一种特殊的委托类型,用于在对象上发生某些事情时通知订阅者。事件的处理通常包括定义事件,创建触发事件的条件,以及订阅该事件的事件处理程序。 以下是一个简单的C#事件处理示例: using System;// 定义…...
深入理解指针(2)
4. const 修饰指针 4.1 const修饰变量 变量是可以修改的,如果把变量的地址交给⼀个指针变量,通过指针变量的也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制,不能被修改,怎么做呢?这就是const的作⽤。 …...
C#.Net筑基-集合知识全解
01、集合基础知识 .Net 中提供了一系列的管理对象集合的类型,数组、可变列表、字典等。从类型安全上集合分为两类,泛型集合 和 非泛型集合,传统的非泛型集合存储为Object,需要类型转。而泛型集合提供了更好的性能、编译时类型安全…...
AI PPT生成器,一键在线智能生成PPT工具
PPT作为商业沟通和教育培训中的重要工具,PPT制作对于我们来说并不陌生。但是传统的PPT制作不仅耗时,而且想要做出精美的PPT,需要具备一定的设计技能。下面小编就来和大家分享几款AI PPT工具,只要输入主题,内容就可以在…...
stm32学习笔记---零基础入门介绍2
目录 STM32介绍 STM32家族系列 ARM介绍 ARM内核型号种类 我们学习用的STM32 片上资源/外设(Peripheral) 命名规则 系统结构 引脚定义 STM32的启动配置 STM32最小系统电路和其他部分电路 最小系统板的实物图 附:安装软件准备 声明…...
搭建取图系统app源码开发,满足广泛应用需求
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 图片已成为信息传递的重要媒介,广泛应用于各个领域。为满足日益增长的图片需求,搭建一款高效的取图系统,可以为用户提供便捷、全面的…...
语音质量评价方法之MOS
引言 在语音增强、语音合成、语音转换、声音转换、语音克隆、语音修复等等领域,常常要对输出的语音进行评价。对语音的质量评价一般关注两个方面,即主观评价和客观评价。主观评价就是人凭借听觉感受对语音进行打分,客观评价比较广泛…...
gorm简介
【1】ORM: 即Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它们就可以了。 【2】GORM gorm是go语言的一个orm…...
MySQL:SELECT list is not in GROUP BY clause 报错 解决方案
一、前言 一大早上测试环境,发现测试环境的MySQL报错了。 SELECT list is not in GROUP BY clause and contains nonaggregated column二、解决方案 官方文档中提到: 大致意思: 用于GROUP BY的SQL / 92标准要求满足以下条件: SE…...
IPython的使用技巧
1、解释说明 IPython是一个强大的Python交互式shell,它提供了丰富的功能,如自动补全、历史记录、内置帮助等。IPython使得在命令行下编写和测试Python代码变得更加方便和高效。 2、使用示例 安装IPython: pip install ipython启动IPython…...
Spring Boot 多线程例子
在Spring Boot中,多线程可以通过Java的并发工具来实现。以下是一些常见的多线程实现方法: 1. 使用Async注解和CompletableFuture: 首先,需要在Spring Boot应用的主类上添加EnableAsync注解,以启用异步支持。 java Spr…...
java干货 线程池的分析和使用
文章目录 一、了解线程池1.1 什么是线程池1.2 为什么需要线程池 二、四种线程池的使用2.1 newFixedThreadPool2.2 newCachedThreadPool2.3 newSingleThreadExecutor2.4 newScheduledThreadPool 三、自定义线程池3.1 线程池七大核心参数3.2 线程池内部处理逻辑 一、了解线程池 …...
文本张量入门
张量,英文为Tensor,是机器学习的基本构建模块,是以数字方式表示数据的形式。 张量的基本类型: 创建一个标量(0维张量),也就是一个单独的数字 scalar torch.tensor(7) scalar.ndim # 返回张量的维度 0 # …...
js文字如何轮播?
<div class"td-style"> <span class"td-text">内容1内容1内容1内容1内容1内容1</span> </div> css: <style> .td-style { width: 160px; height: 72px; overflow: hidden; white-…...
Linux 五种IO模型
注:还有一种信号驱动IO,使用较少暂不讨论; 一,区分阻塞、非阻塞和同步、异步 看了很多文章对这两组概念解释和对比,说的太复杂了,其实没必要,两句话就能说清楚。 首先,对于读数据rec…...
深度解析响应式异步编程模型
上一篇文章中我们聊了一下线程池,基于线程池的多线程编程是我们在高并发场景下提升系统处理效率的有效手段,但却不是唯一的。今天我们来看一下另一种异步开发的常用手段-响应式编程模型 传统多线程模型的缺陷 多线程模型是目前应用最为广泛的并发编程手段,但凡遇到什么性能…...
一个软件是如何开发出来的呢?
一、前言 如今,AI大爆发的时代,作为一名IT从业者,你是否也想尝试开发一套自己的系统,实现那些看似有可能实现的天马行空的想法,变成一个优秀甚至伟大的产品,甚至带来某个行业的革新,那作为一名…...
宝塔板面有哪些优势
哈喽呀,大家好呀,淼淼又来和大家见面啦,在当今数字化时代,随着云计算和互联网技术的飞速发展,服务器管理成为了许多企业和个人开发者不可或缺的一部分。然而,传统服务器管理方式的复杂性和技术门槛往往令初…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
