Vue3.0快速上手

    • @[TOC](Vue3.0快速上手)
  • Vue3简介
  • Vue3.0相对于Vue2多了些什么?
    • 1.性能的提升
    • 2.源码改变
    • 3.拥抱TS
    • 4.新特性(重点)
  • 常用的组合式API
    • Vue3工程创建
    • 结构分析
    • 组合式API-setup
    • 实现响应式-ref和reactive
    • Vue2和Vue3的响应式实现对比
    • setup的两个参数
    • 计算属性
    • watch监听
    • watchEffect
    • watch和watchEffect对比
    • 生命周期
    • 自定义hook函数
    • toRef和toRefs
  • 其他组合式API
    • shallowReactive
    • shallowRef
    • readonly
    • shallowReadonly
    • toRaw
    • markRaw
    • customRef
    • provide和inject
  • 新的组件
    • Fragment(片段)
    • Teleport(瞬移)
    • Suspense(不确定的)

Vue3简介


代号:One Piece(海贼王)

Vue3.0相对于Vue2多了些什么?

1.性能的提升

根据官方文档描述,Vue3.0性能的提升提升主要包括以下几个方面:

  • 打包大小减少了41%。
  • 初次渲染55%,更新渲染快了133%。
  • 内存减少54%。

2.源码改变

  • 响应式的实现。之前我们知道Vue2的响应式是通过Object.definePropetry()实现并且有些小瑕疵(对于对象属性的增加和删除),而Vue3.0则通过Es6Proxy函数实现响应式。
  • 重写了对虚拟DOM的实现和Tree-Shaking

3.拥抱TS

  • 更好的兼容TypeScript。

4.新特性(重点)

  • Composition API(组合式API)
    setup,ref,reactive,watch,watchEffect,provide,inject
  • 内置组件
    Fragment,Teleport,Suspense…
  • 其它改变
    生命周期函数等等…

常用的组合式API

Vue3工程创建

我们还可以和之前一样用Vue-Clil来创建Vue3.0的工程,但是我们Vue3.0还可以使用vite来创建。

  • vite
    之前我们的前端构建工具大多数用的都是webpack,但是我们尤大给我们提供了新的前端构建工具就是vite,主要的优势:开发环境无需打包可冷启动热重载

结构分析

我在这里还是使用我们Vue-Cli来创建Vue3的工程
其实大概结构还是和Vue2是差不多的,首先我们先看一下入口文件

// Vue3引入了一个名为createAPP的工厂函数,并对外壳组件App进行挂载
import { createApp } from 'vue'
import App from './App.vue'createApp(App).mount('#app')

之前我们在Vue2中,我们是通过new Vue()的实例和渲染函数,通过$mount对外壳组件进行挂载。
其他包括外壳组件App,和其他配置比如 vue.config.js等等都是几乎一样的,我们遇到的时候再说。

组合式API-setup

setup是Vue3的一个新的配置项,值为一个函数。包含我们需要用到的数据,方法,计算属性,生命周期等等。同时需要返回一个包含数据方法计算属性等等的对象或者一个渲染函数
-------返回对象:

<template><div>我是App组件</div><h3>我的名字是{{person.name}}</h3><h3>我的年龄是{{person.age}}</h3><button @click="sayHello">点我SayHello</button></template><script>
export default {name: "App",setup() {let person = {name: "花生",age: 23,};function sayHello() {alert(`大家好,我的名字是${person.name},今年${person.age}岁了。`);}return { person, sayHello };},
};
</script>


-------返回渲染函数:

<template><div>我是App组件</div><!-- <h3>我的名字是{{person.name}}</h3><h3>我的年龄是{{person.age}}</h3> --><!-- <button @click="sayHello">点我SayHello</button> --></template><script>
import { h } from "@vue/runtime-core";
export default {name: "App",setup() {// let person = {//     name: "花生",//     age: 23,// };// function sayHello() {//     alert(`大家好,我的名字是${person.name},今年${person.age}岁了。`);// }// return { person, sayHello };return () => h("h2", "返回渲染函数");},
};
</script>


当返回是渲染函数的时候,不管我们模板中写了什么,都会被渲染函数替换掉。
我们看到上面代码的时候很当然的就会想到,这些数据目前都没有响应式,那Vue3 的响应式是怎么实现的呢?

实现响应式-ref和reactive

------ref:
在Vue2中我们使用ref为一个元素打标识,但是在Vue3 中我们的ref是一个函数,这两个可不是一个东西。而是在Vue3 中多出来一个ref函数。

<template><div>我是App组件</div><h3>我的名字是{{name}}</h3><h3>我的年龄是{{age}}</h3><button @click="changeInfo">修改人的信息</button></template><script>
export default {name: "App",setup() {let name = "花生";let age = 23;function changeInfo() {name = '土豆',age = 32console.log(name,age);}return {name,age,changeInfo,};},
};
</script>


当我们点击按钮修改数据后,数据其实已经改了,但是vue并没有捕获到,就是说我们现在定义的数据根本就不是响应式。
1.ref定义基本类型数据

<template><div>我是App组件</div><h3>我的名字是{{name}}</h3><h3>我的年龄是{{age}}</h3><button @click="changeInfo">修改人的信息</button></template><script>
import { ref } from '@vue/reactivity';
export default {name: "App",setup() {let name = ref("花生");let age = ref(23);function changeInfo() {name.value = '土豆',age.value = 32console.log(name,age);}return {name,age,changeInfo,};},
};
</script>


通过ref函数返回的其实是一个RefImpl(reference Implement)引用对象的实例对象,
其实,ref函数在实现基本类型的响应式的时候也是和Vue2的实现方法一样,通过Object.defineProperty()get/set进行数据劫持来实现的。

2.ref定义对象类型数据

<template><div>我是App组件</div><h3>我的名字是{{name}}</h3><h3>我的年龄是{{age}}</h3><h3>我的工作是{{job.type}}</h3><h3>我的薪水是{{job.salary}}</h3><button @click="changeInfo">修改人的信息</button><button @click="changeSalary">修改人的薪水</button></template><script>
import { ref } from '@vue/reactivity';
export default {name: "App",setup() {let name = ref("花生");let age = ref(23);let job = ref({type:"前端工程师",salary:20})function changeInfo() {name.value = '土豆',age.value = 32}function changeSalary() {job.value.type = "Java工程师"job.value.salary ++console.log(job);}return {name,age,job,changeInfo,changeSalary};},
};
</script>


Vue3.0在处理对象类型的数据响应式时,使用的并不是Object.defineProperty()而是底层通过Es6的Proxy实现响应式。

  1. reactive定义对象类型数据
setup() {let person = reactive({name: "花生",age: 23,job: {type: "前端工程师",salary: 20,},});function changeInfo() {person.name = "土豆";person.age = 32;}function changeSalary() {person.job.type = "Java工程师";person.job.salary++;console.log(person);}return {person,changeInfo,changeSalary,};},

其实,我们使用ref来定义对象类型数据的时候,Vue3也是通过reactive来实现响应式的。

Vue2和Vue3的响应式实现对比

1.回顾一下Vue2 的响应式实现。

<html><body><input id="input" name="value" type="text"><br>输入的是:<h3 id="myInput"></h3><script>var data = {}document.getElementById('input').oninput = function (e) {data.name = e.target.value}Object.defineProperty(data, 'name', {get: function () {return data.nameconsole.log("data被读取了");},set: function (val) {document.getElementById('myInput').innerHTML = valconsole.log("data被修改了");}})</script>
</body></html>

通过Object.defineProperty()的get/set进行数据劫持实现响应式。

2.Vue3.0实现响应式
Vue3.0对于基本类型使用ref函数实现响应式,原理还是之前的Object.defineProperty()的get/set 数据劫持。
我们这里主要说Vue3对于其他类型的数据的响应式的处理,Vue3在这里并没有跟之前一样使用Object.defineProperty()而是使用Es6的一个在Window上的新方法:Proxy

Proxy(代理)介绍

//target:需要被代理的对象
//handler:也是一个对象,用来定义被代理的行为
let proxy = new Proxy(target,handler)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Vue3响应式</title>
</head><body><script>let person = {name: "花生",age: 23}let p = new Proxy(person, {})</script></body></html>

Reflect

ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上。

Proxy相对应。我们的Vue3的响应式就可以这样实现:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Vue3响应式</title>
</head><body><script>let person = {name: "花生",age: 23}let p = new Proxy(person, {get(target, propName) {console.log(`p身上的${propName}属性被读取了`);return Reflect.get(person, propName)},set(target, propName, value) {console.log(`p身上的${propName}属性被修改了,要去更新页面了!`);Reflect.set(person, propName, value)},deleteProperty(target, propName) {console.log(`p身上的${propName}属性被删除了`);return Reflect.deleteProperty(target, propName)},})</script></body></html>

setup的两个参数

export default {name: "Test",props: {job: {type: String,default: "",},salary: {type: Number,default: 0,},},emits: ["sayHello"],setup(props, context) {console.log(props, context);let person = reactive({name: "花生",age: 23,});function sayHello() {context.emit("sayHello", person.name);}return {person,sayHello,};},
};


第一个参数props:值为对象,都组件外部传进来且组件内部声明接收了的参数
第二个参数context:
1.attrs:值为对象,由组件外部传进来但是组价内部没有声明接收的属性。
2.emit:分发自定义事件函数。
3.slots:收到的插槽内容(虚拟DOM)。

计算属性

  • 简写形式(只读)
<template><div class="app"><h3>我是App组件</h3>姓:<input v-model="person.fristName"><br>名:<input v-model="person.lastName"><br>全名:{{person.fullName}}</div>
</template><script>
import { reactive } from "@vue/reactivity";
import { computed } from "@vue/runtime-core";
export default {name: "App",setup() {let person = reactive({fristName: "花",lastName: "生",});//简写形式(只读)person.fullName = computed(() => {return person.fristName + "-" + person.lastName;});return {person,};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 300px;
}
</style>

  • 完整形式(读写)
person.fullName = computed({get() {return person.fristName + "-" + person.lastName;},set(value) {let nameArr = value.split("-");person.fristName = nameArr[0];person.lastName = nameArr[1];},});

watch监听

  • 监听单个ref定义的基本类型数据
<template><div class="app"><h3>我是App组件</h3><h3>{{sum}}</h3><br><button @click="sum++">点我+1</button></div>
</template><script>
import { ref } from "@vue/reactivity";
import { watch } from "@vue/runtime-core";
export default {name: "App",setup() {let sum = ref(0);watch(sum, (newValue, oldValue) => {console.log(`sum改变`, newValue, oldValue);},{immediate:true});return {sum,};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 300px;
}
</style>

  • 监听多个ref定义的基本类型数据
     watch([sum, name], (newValue, oldValue) => {console.log(`sum或name改变`, newValue, oldValue);});


newValue和oldValue都变成了数组。

  • 监听单个reactive定义的数据
watch(person, (newValue, oldValue) => {console.log(`person改变`, newValue, oldValue);});


newValue和oldValue值相同,同时默认强制开启了深度监听

  • 监听reactive定义的响应式数据中的某个属性
     watch(()=>person.age, (newValue, oldValue) => {console.log(`person.age改变`, newValue, oldValue);});
  • 监听reactive定义的响应式数据中的多个属性
     watch(() => [person.age, person.name],(newValue, oldValue) => {console.log(`person.age改变`, newValue, oldValue);});

watchEffect

     watchEffect(() => {const x1 = person.name;const x2 = person.age;console.log(`watchEffect被调用了!`);});

watch和watchEffect对比

  • watch:既要指明被监听的属性,也要指明监听的回调。
  • watchEffect:不需要指明监听的属性,监听的回调中用到那个属性,就监听哪个属性。

生命周期

  • Vue2的生命周期钩子

  • Vue3.0的生命周期钩子


整体观察,我们发现,Vue3.0因为先判断了是否挂载成功而少了一个判断环节,也减少了两个生命周期钩子(brforeCreate,created)资源的浪费。同时,beforeUNmount和unmounted的名字的更改。
我们来实际体验一下各个生命周期函数被调用的顺序。

  • 通过配置项的方式使用生命周期钩子

Demo.vue


<template><div class="demo"><h3>我是App组件</h3><h3>{{sum}}</h3><button @click="sum++">点我+1</button></div>
</template><script>
import { reactive, ref } from "@vue/reactivity";
export default {name: "App",setup() {let sum = ref(0);return {sum,};},beforeCreate() {console.log("------beforeCreate------");},created() {console.log("------created------");},beforeMount() {console.log("------beforeMount------");},mounted() {console.log("------creamountedted------");},beforeUpdate() {console.log("------beforeUpdate------");},updated(){console.log("------updated------");},beforeUnmount(){console.log("------beforeUnmount------");},unmounted(){console.log("------unmounted------");}
};
</script>
<style scoped>
.demo {background: orange;padding: 10px;height: 200px;
}
</style>

App.vue

<template><div class="app"><Demo v-if="isShowDemo" /><button @click="isShowDemo = !isShowDemo">是否展示Demo</button></div>
</template><script>
import { reactive, ref } from "@vue/reactivity";
import Demo from "./components/Demo.vue";
export default {components: { Demo },name: "App",setup() {let isShowDemo = ref(true);return {isShowDemo,};},
};
</script>
<style scoped>
.app {background: gray;padding: 10px;height: 300px;
}
</style>

Demo初始化挂载时

数据修改时

卸载之后重新挂载时

  • 使用组合式API
    官网给出的在setup()内部调用的生命周期钩子(只截取了部分)。

<template><div class="demo"><h3>我是App组件</h3><h3>{{sum}}</h3><button @click="sum++">点我+1</button></div>
</template><script>
import { reactive, ref } from "@vue/reactivity";
import {onBeforeMount,onBeforeUnmount,onBeforeUpdate,onMounted,onUnmounted,onUpdated,
} from "@vue/runtime-core";
export default {name: "App",setup() {console.log("------setup------");let sum = ref(0);onBeforeMount(() => {console.log("------onBeforeMount------");});onMounted(() => {console.log("------onMounted------");});onBeforeUpdate(() => {console.log("------onBeforeUpdate------");});onUpdated(() => {console.log("------onUpdated------");});onBeforeUnmount(() => {console.log("------onBeforeUnmount------");});onUnmounted(() => {console.log("------onUnmounted------");});return {sum,};},
};
</script>
<style scoped>
.demo {background: orange;padding: 10px;height: 200px;
}
</style>

自定义hook函数

本身是一个函数,对setup()中的组合式API进行了封装,实现代码复用类似于Vue2.x的mixin。我们还是用最经典的例子——屏幕打点。

Demo.vue


<template><div class="demo"><h3>我是Demo组件</h3><h3>打点坐标是: x:{{point.x}},y:{{point.y}}</h3></div>
</template><script>
import { reactive, ref } from "@vue/reactivity";
import { onBeforeUnmount, onMounted } from "@vue/runtime-core";
import usePoint from "../hooks/usePoint";
export default {name: "App",setup() {let point = usePoint();return {point,};},
};
</script>
<style scoped>
.demo {background: orange;padding: 10px;height: 200px;
}
</style>

hooks—>usePoint.js

import { reactive, ref } from "@vue/reactivity";
import { onBeforeUnmount, onMounted } from "@vue/runtime-core";export default function () {let point = reactive({x: 0,y: 0,});function getPoint(event) {point.x = event.pageX;point.y = event.pageY;console.log(point.x, point.y);}onMounted(() => {window.addEventListener("click", getPoint);});onBeforeUnmount(() => {window.removeEventListener("click", getPoint);});return point
}

toRef和toRefs

  • toRef
<template><div class="app"><h3>我是App组件</h3><h4>{{person}}</h4><h3>姓名:{{name}}</h3><h3>年龄:{{age}}</h3><h3>工作:{{salary}}块大洋</h3><button @click="name+='~'">修改姓名</button><button @click="age++">年龄+1</button><button @click="salary++">涨薪</button></div>
</template><script>
import { reactive, ref, toRef } from "@vue/reactivity";
export default {name: "App",setup() {let person = reactive({name: "花生",age: 23,job: {salary: 20,},});return {person,name:toRef(person,'name'),age:toRef(person,'age'),salary:toRef(person.job,'salary')};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 300px;
}
</style>

  • toRefs
<template><div class="app"><h3>我是App组件</h3><h4>{{person}}</h4><h3>姓名:{{name}}</h3><h3>年龄:{{age}}</h3><h3>工作:{{job.salary}}块大洋</h3><button @click="name+='~'">修改姓名</button><button @click="age++">年龄+1</button><button @click="job.salary++">涨薪</button></div>
</template><script>
import { reactive, ref, toRef, toRefs } from "@vue/reactivity";
export default {name: "App",setup() {let person = reactive({name: "花生",age: 23,job: {salary: 20,},});return {person,...toRefs(person)};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 300px;
}
</style>

其他组合式API

shallowReactive

浅层次的实现响应式,接着上面的例子,使用shallowReactive

setup() {let person = shallowReactive({name: "花生",age: 23,job: {salary: 20,},});return {person,...toRefs(person)};},

name,age都是响应式数据,但是深层次的salary则没有响应式。

shallowRef

ref对于对象类型数据借助了reactive,shallowRef而不对对象类型的数据进行响应式处理。

setup() {let refX = ref({x:0})let shallowRefX = shallowRef({x:0})console.log('ref',refX);console.log('shallowRef',shallowRefX);let person = shallowReactive({name: "花生",age: 23,job: {salary: 20,},});return {person,...toRefs(person)};},

readonly

使用readonly之后,无论是浅层次的,还是深层次的的数据都不能被修改。

setup() {let sum = ref(0);let person = reactive({name: "花生",age: 23,job: {salary: 20,},});person = readonly(person)return {sum,...toRefs(person),};},

shallowReadonly

使用readonly之后,第一层次的数据不能被修改,但是深层次的的数据时可以被修改的。

toRaw

将reactive定义的响应式数据类型,抓换成普通的对象。

<template><div class="app"><h3>我是App组件</h3><h3>求和为:{{sum}}</h3><hr><h3>姓名:{{name}}</h3><h3>年龄:{{age}}</h3><h3>工作:{{job.salary}}块大洋</h3><button @click="name+='~'">修改姓名</button><button @click="handleAgeChange">年龄+1</button><button @click="job.salary++">涨薪</button></div>
</template><script>
import { reactive, ref, toRaw, toRefs } from "@vue/reactivity";
export default {name: "App",setup() {let sum = ref(0);let person = reactive({name: "花生",age: 23,job: {salary: 20,},});function handleAgeChange() {person.age++;console.log(toRaw(person));}return {sum,...toRefs(person),handleAgeChange};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 300px;
}
</style>

markRaw

被标记的对象,将不会变成响应式数据。

<template><div class="app"><h3>我是App组件</h3><h3>求和为:{{sum}}</h3><hr><h3>姓名:{{name}}</h3><h3>年龄:{{age}}</h3><h3>工作:{{job.salary}}块大洋</h3><h3>车辆信息:{{person.car}}</h3><button @click="name+='~'">修改姓名</button><button @click="age++">年龄+1</button><button @click="job.salary++">涨薪</button><button @click="person.car.name+='!'">车改名</button><button @click="person.car.price++">车涨价</button></div>
</template><script>
import { markRaw, reactive, ref, toRaw, toRefs } from "@vue/reactivity";
export default {name: "App",setup() {let sum = ref(0);let person = reactive({name: "花生",age: 23,job: {salary: 20,},});person.car = markRaw({name:'跑跑卡丁车',price:40})console.log(person);return {sum,person,...toRefs(person),};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 400px;
}
</style>

customRef

自定义ref,官方例子

<template><div class="app"><h3>我是App组件</h3><inputtype="text"v-model="keyWord"><h3>{{keyWord}}</h3></div>
</template><script>
import { customRef, ref } from "@vue/reactivity";
export default {name: "App",setup() {let keyWord = myRef("hello", 1000);function myRef(value, delay) {return customRef((track, trigger) => {return {get() {console.log("数据被读取了");track(); //通知vue数据需要被追踪return value;},set(newValue) {console.log("数据被修改了", newValue);value = newValue;setTimeout(() => {trigger(); //通知vue去更新模板}, delay);},};});}return {keyWord,};},
};
</script>
<style scoped>
.app {background: orange;padding: 10px;height: 200px;
}
</style>

provide和inject

用于实现组件间的通信,尤其是祖孙组件之间。祖先组件使用provide提供数据,后代组件通过inject注入来获取数据。

App.vue

name: "App",setup() {let person = reactive({name: "花生",age: 23,});provide("info", person);return {person,};},

Test.vue

name: "Test",setup() {let person = inject("info");let car = inject("car");return {person,car,};},


且数据是响应式的。

新的组件

Fragment(片段)

Vue3.0新增了Fragment组件。在Vue2.x中我们只能有一个根标签,而在Vue3,0中我们可以写多个根标签,然后Vue3将其包在Fragment这一虚拟元素中。

Teleport(瞬移)

Teleport 提供了一种干净的方法, 让组件的html在父组件界面外的特定标签(很可能是body)下插入显示

Suspense(不确定的)

它们允许我们的应用程序在等待异步组件时渲染一些后备内容,可以让我们创建一个平滑的用户体验

学习Vue3.0笔记相关推荐

  1. 乐鑫esp8266学习rtos3.0笔记第9篇:整理分享那些我在项目中常用的esp8266 rtos3.0版本的常见驱动,Button按键长短按、PWM平滑调光等。(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...

  2. 乐鑫esp8266学习rtos3.0笔记第4篇:带你捋一捋微信公众号 airkiss 配网 esp8266 并绑定设备的过程,移植并成功实现在 esp8266 rtos3.1 sdk。(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...

  3. 乐鑫esp8266学习rtos3.0笔记第6篇:esp8266-12模块基于rtos3.1版本ota功能远程空中升级固件,官网之上增加dns域名解析!(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个"hello ...

  4. 学习Vue3.0,先来了解一下Proxy

    产品经理身旁过,需求变更逃不过. 测试姐姐眯眼笑,今晚bug必然多. 据悉Vue3.0的正式版将要在本月(8月)发布,从发布到正式投入到正式项目中,还需要一定的过渡期,但我们不能一直等到Vue3正式投 ...

  5. 学习Vue3.0,先从搭建环境开始

    Bug源测试,上线来几个.愿君多修改,今夜眼难合. 这是小编关于Vue3.0系列文章的第二篇,本文将带您从零搭建一个基于Vue3.0与vite的Vue3.0开发环境,通过本文的学习,你将学习到以下内容 ...

  6. Vue3.0笔记(B站天禹老师)

    Vue3快速上手 1.Vue3简介 2020年9月18日,Vue.js发布3.0版本,代号:One Piece(海贼王) 耗时2年多.2600+次提交.30+个RFC.600+次PR.99位贡献者 g ...

  7. 乐鑫esp8266学习rtos3.0笔记第3篇: 一篇文章带你搞掂存储技术 NVS 的认识和使用,如何利用NVS保存整型、字符串、数组以及结构体。(附带demo)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个" ...

  8. 乐鑫esp8266学习rtos3.0笔记:仅1M flash 的安信可 ESP-01S 模块,如何二次开发?如何对其 OTA 远程升级固件!

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个" ...

  9. 乐鑫esp8266学习rtos3.0笔记第5篇:基于乐鑫idf框架,研究出超稳定、掉线重连、解决内存泄露问题的Mqtt框架,支持esp8266和esp32!(附带链接)

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 1. Esp8266之 搭建开发环境,开始一个" ...

最新文章

  1. C语言12变21,【C语言】21-结构体
  2. ruby安装插件报错
  3. 为预防软件质缺陷应该做点儿什么
  4. 日计不足涓滴成河-自定义响应结果格式化器
  5. FIFO(命名管道)
  6. logback-spring.xml
  7. 股东接连减持 寒武纪2021年净亏损8.47亿元
  8. android 录音原始文件_Android 11可能最终会取消Android对视频录制的4GB文件大小限制...
  9. firefox扩展开发(八) :控件激活
  10. X协议 mysql_MySQL X协议分析
  11. win10清理c盘_别再用什么管家!打开这个功能,Win10自动给你清垃圾
  12. VALSE学习(五):看图说话-Visual Question Answering as Reading Comprehension
  13. c语言程序设计爱心图片,c语言爱心图片表白程序源代码
  14. Oracle Exadata 技术详解 - 李亚
  15. dataworks 生成表血缘依赖
  16. 矿大计算机 学硕专硕,【20考研】超详细对比,学硕专硕如何选,不懂的学弟学妹快进来看...
  17. 百万级数据连表查询优化
  18. iamp是什么意思计算机网络,pop3和imap什么意思
  19. Geant4能谱展宽【Gaussian Broadning】-root作图
  20. 残差网络ResNet最全分析

热门文章

  1. 最近遇到的部分知识点总结
  2. elementUI form表单重置问题
  3. 联想小新潮7000安装deepin 系统
  4. 创意电子学-小知识:如何使用面包板
  5. i7台式电脑配置推荐_i7组装电脑配置清单【攒机之家】
  6. [20091031]箱根红叶
  7. 简单爬取王者荣耀英雄图标!!!无废话,一看就会!!!
  8. 3D CAD模型的体素化
  9. java pinyin4j 官网_Pinyin4j---JAVA拼音解决方案
  10. sai魔棒工具选择后使用油漆桶铺色但图形的边界线颜色没改变