VUE家族系列:

01、component组件

1.1、component基础知识

组件是可以复用的Vue模块,是一个独立的,有自己的视图、样式CSS、ViewMoel业务逻辑,结构的完整模块。当成自定义元素,可以在任意Vue中、模板、其他组件中使用。一个复杂的页面、系统可以拆分为多个组件,独立开发和维护,可复用、更清晰。

注册组件Vue.component( id, [definition] )注册全局组件,id为组件的名称,也作为元素名,参数和Vue参数选项对象基本一致。

  • data 必须是函数:通过函数返回对象,避免不同组件实例共享data数据。
  • template 模板,字符串模板,或者<template>选择器,不能用真实Dom元素。
  • 必须有根元素:组件的模板必须有一个有效的根元素。

props 参数:通过props定义组件参数(Array<string> | Object ),参数都会作为组件元素的attribute特性使用,通过vm.$props获取组件参数。

自定义事件:在子组件中,申明并触发自定义事件 $emit( event-name, […args] ),通过vm.$listeners 获取组件的所有监听事件。(emit /iˈmɪt/ 发射,发出 )

  • 响应事件(父组件):v-on:event-name,这里的处理函数建议只绑定函数名,便于接收参数。
  • 修饰符.native 绑定组件根元素的原生事件,v-on:change.native="func"
  • 绑定事件监听器,在组件内特定元素上绑定所有监听事件:v-on="$listeners"vm.$listeners可获取组件上的所有监听事件。

<slot>插槽</slot>,在组件中设定一个插槽,来接收组件元素的标签内的内容,通过vm.$slots 获取组件的插槽。

  1. <div id="app9">
  2. <uinfo v-for="(u,i) in users" v-bind:u="u" type="钻石会员" v-on:remove="users.splice(i,1)"></uinfo>
  3. </div>
  4. <script>
  5. // 注册一个全局组件
  6. Vue.component("uinfo", {
  7. data: function () {
  8. return { count: 0 }
  9. }, //组件的data必须是函数返回对象
  10. props: ['u', 'type'],
  11. template: `<div class="uinfo">
  12. <span>{{u.name}}</span> <input v-model.number="u.age" type="number"> <i>{{type}}</i>
  13. <span>“{{u.summary}}”</span>
  14. <button v-on:click="$emit('remove')">删除</button>
  15. </div>` //通过模板字符的方式实现多行文本,IE是不支持的。
  16. });
  17. let app9 = new Vue({
  18. el: "#app9",
  19. data: {
  20. users: [
  21. { name: "张三", age: 14, summary: "垂死病中惊坐起,赶快下楼做核酸" },
  22. { name: "李四", age: 30, summary: "仰天大笑出门去,下楼排队做核酸" }]
  23. }
  24. })
  25. </script>

注意组件命名小写+连字符(kebab-case),包括组件名称(作为自定元素标签)、组件参数prop(作为自定义元素的 attribute),以及自定义事件名。

  • 小写遵循W3C规范,连字符避免和HTML冲突(包括以后新的HTML标签名)。
  • HTML 中的 attribute 名是大小写不敏感的,浏览器会把所有大写字符解释为小写字符。

    ️ 如果使用字符模板,就不归浏览器管了,就没有命名的限制问题了!

1.2、注册组件

  • 全局注册Vue.component( id, {选项}),全局组件,任何地方都可以使用。
  • 局部注册components:{id:{选型}}选项注册组件,只能在当前注册的Vue环境内使用,不可继承。
  • 扩展Vue类Vue.extend({选项}),创建一个Vue的扩展类,通过new()创建组件实例,也是一种组件复用方式。
  1. <div id="app10">
  2. <div>
  3. <sexbox v-bind:data="uinfo" age="99" required>性别({{uinfo.sex}}):</sexbox>
  4. <user-box :data="uinfo"></user-box>
  5. </div>
  6. </div>
  7. <template id="userSexTemplate">
  8. <div>
  9. <slot></slot>
  10. <label v-for="(value,name) in dic">
  11. <!-- v-bind="$attrs" 用来绑定组件上设置的属性:age="99" required -->
  12. <input type="radio" v-model="data.sex" name="sex" :value="name" v-bind="$attrs">
  13. {{value}}
  14. </label>
  15. </div>
  16. </template>
  17. <template id="userBoxTemplate">
  18. <div>姓名:<input type="text" v-model="data.name">
  19. <sexbox :data="data">性别:</sexbox>
  20. </div>
  21. </template>
  22. <script>
  23. // 性别选择组件
  24. let comSex = {
  25. data: function () { return { dic: { male: '男', female: "女", other: '其他' } } },
  26. props: ['data'],
  27. template: '#userSexTemplate'
  28. }
  29. // 用户信息组件,引入了性别组件
  30. let UserVue = Vue.extend({
  31. props: ['data'],
  32. components: { 'sexbox': comSex },
  33. template: `#userBoxTemplate`,
  34. })
  35. //vue 应用
  36. let app10 = new Vue({
  37. el: "#app10",
  38. data: { uinfo: { name: '核算', sex: 'male' } },
  39. components: { 'user-box': UserVue, 'sexbox': comSex }
  40. })
  41. // app10 = new UserVue({el:'#app10'})
  42. </script>

1.3、is 动态组件

通过is特性设置(或v-bind:is绑定)组件名称,动态的申明一个组件。

组件使用申明方式:

  • <user-info></user-info>:常规自定义元素方式申明。
  • <component is="user-info"></component>:component组件元素申明,通过is设置组件名称,:is就可以动态绑定组件了。
  • <tr is="user-info"></tr>:其他HTML元素+is申明组件,该元素会被组件内容替换掉。这主要是为了解决有些HTML元素中只能包含特定的子元素,如<ul><table>
  1. <keep-alive>
  2. <component is="user-info" v-bind:u="users[0]"></component>
  3. </keep-alive>
  4. <table>
  5. <tr is="user-info" v-bind:u="users[0]"></tr>
  6. </table>

keep-alive 缓存组件:用<keep-alive>包裹动态组件,配合组件特性:is使用,用来缓存失活的动态组件,避免组件失活后状态丢失。

1.4、Props参数

通过props定义参数(Array<string> | Object ),参数都会作为组件元素的attribute特性使用,通过vm.$props获取组件参数。

Prop对象验证:除了使用数组设置多个参数,还可以用一个对象来申明多个参数及参数规则,用于参数合法性验证。️注意验证的执行是在组件实例创建之前进行的,此时datacomputed都还不可用

  • 每个参数可以指定多个验证类型。
  • 每个参数可以定义类型type、必填require、默认值default,以及验证器函数validator
  1. <div id="app11">
  2. <sex-box v-bind:data="uinfo" type="vip" age="99" required class="form-item">性别:</sex-box>
  3. </div>
  4. <script>
  5. function User(name = "", sex = "") {
  6. this.name = name; this.sex = sex;
  7. }
  8. // 一个性别选择组件
  9. let sexBox = {
  10. data: function () {
  11. return {
  12. dic: { male: '男', female: "女", other: '其他' },
  13. utype: this.type, //使用prop参数为初始值
  14. }
  15. },
  16. inheritAttrs: false, //组件根元素不继承Attribute(不含style、class)
  17. props: {
  18. data: [Object, User], //User为自定义构造器
  19. type: String,
  20. age: {
  21. type: [String, Number],
  22. required: true,
  23. default: 18,
  24. validator: function (value) { return value > 0 && value < 100 } /* 自定义验证器 */
  25. }
  26. },
  27. // props: ['data', 'type', 'age'],
  28. template: `<div><slot></slot>
  29. <label v-for="(value,name) in dic">
  30. <input type="radio" v-model="data.sex" name="sex" :value="name" v-bind="$attrs">
  31. {{value}}</label> //{{type}}</div>`,
  32. }
  33. let app11 = new Vue({
  34. el: "#app11",
  35. data: {uinfo: new User("张三", 'male')},
  36. components: {'sex-box': sexBox,}
  37. })
  38. </script>

参数绑定:参数作为自定义组件元素的attribute使用,推荐v-bind:prop绑定赋值,除是非字符串值,绑定是支持表达式的。

  • 如果要传入一个对象的所有 property,直接v-bind="obj"即可。

参数的单向传递:参数的值是单向的向下传递的,子组件不可更改。

  • 父组件的数据变更会触发子组件所有参数prop的刷新。
  • 如果传入的是一个引用类型(数组、对象),这个是共享的,会影响父组件状态。

非Props参数的Attribute:对于非Prop参数的Attribute,默认会都应用到组件根元素上,如上面示例中的age="99" required class="form-item"

  • 替换:除了classstyle会合并,其他如果冲突会替换掉组件内部的Attribute
  • inheritAttrs 不继承:可在组件选项里设置inheritAttrs:false取消根元素的Attribute继承。
  • 主动继承:组件内部其他元素可以用 v-bind="$attrs",来主动继承非Prop的Attribute特性(不含class、style)。

1.5、#slot插槽

插槽可以用来插入任何内容,包括文本、HTML、其他组件。结合具名插槽(name)、prop绑定,可以实现更为开放、灵活的组件。

  • 申明插槽:在组件内部通过<slot></slot>申明一个插槽,整个<slot></slot>会被替换为组件元素标签的内容(InnerHTML)。
  • 后备内容/默认值<slot>默认显示内容</slot>,在没有提供内容时使用后备内容。
  1. <div id="app13">
  2. <com-search-box>
  3. <p>{{search.title[0]}}</p>
  4. <template v-slot:default> <!--效果同上-->
  5. <p>{{search.title[0]}}</p>
  6. </template>
  7. </com-search-box>
  8. </div>
  9. <script>
  10. let comSearchBox = {
  11. template: `<div><slot>搜索</slot> <input><button><b></b><span>搜索</span></button></div>`,
  12. }
  13. let app13 = new Vue({
  14. el: "#app13",
  15. data: { search: { title: ['百度搜索', '学术搜索', '图片搜索'] } },
  16. components: { 'com-search-box': comSearchBox }
  17. })
  18. </script>

具名插槽,有名字的VIP插槽,name特性取名,用于需要多个插槽的场景。没命名的插槽<slot>默认名称为"default"--默认插槽。

  • 必须通过一个模板<template>来使用,用slot参数v-slot:name = #name 指定插槽的名字。无<template>、不指定名字的内容用于默认插槽。
  • 缩写# = v-slot:,只能用于带参数的v-slotv-slot:default
  • 插槽名可以用动态参数,[data-name]<template v-slot:['default']>

作用域插槽:插槽内容访问子组件内部数据

父级不能访问子组件内部的数据,为了可以让插槽内容可以访问到子组件内部的数据,于是有了作用域插槽,主要就是2个步骤。

❶ 组件内部把数据绑定在插槽<slot>的特性Attribute上 <slot v-bind:data="btnKey">,称为插槽的Prop,在父级作用域可以访问。

❷ 在组件<template>上引用插槽prop :<template v-slot="soldData">,可取一个新名字。当然这里也可以用当前作用域的绑定数据。

  1. <div id="app13">
  2. <com-search-box>
  3. <template #header v-slot:header> <p>{{search.title[1]}}</p> </template>
  4. <template v-slot="soldData">
  5. <b></b><span>{{soldData.data[1]}}</span>
  6. </template>
  7. </com-search-box>
  8. </div>
  9. <script>
  10. let comSearchBox = {
  11. data: function () { return { 'btnKey': ['搜索', 'search'] } },
  12. template: `<div>
  13. <slot name="header"></slot> <input>
  14. <button> <slot v-bind:data="btnKey">{{btnKey[0]}}</slot> </button>
  15. </div>`,
  16. }
  17. let app13 = new Vue({
  18. el: "#app13",
  19. data: { search: { title: ['百度搜索', '学术搜索', '图片搜索'] } },
  20. components: { 'com-search-box': comSearchBox }
  21. })
  22. </script>

todo-list(代办列表)的示例:马上掘金 | codepen


1.6、组件树关系

属性 描述
$refs 通过过 refattribute 注册的所有 DOM 元素和组件实例的一个引用对象。
当 ref 和 v-for 一起使用的时候,其引用为一个数组
$parent 父实例,根实例的 $parent 为null
$root 组建树的根实例,根实例的 $root 为自己
$children 子组件实例数组Array<Vue instance>

当我们构建一颗树形结构(如文件目录树)的组件时,会递归循环引用,造成组件的循环依赖。

  • 全局注册组件。
  • beforeCreate手动注入子组件。
  • 设置webpack异步import引入组件。

1.7、总结:组件通信

通过组件关系树也是可以的,不过不推荐,耦合性太高。


02、可复用性 & 组合

2.1、[mixins]混入(CtrlV)组件代码

混入(mixins)可以灵活复用组件中的代码,可惜只能用于组建内,也仅支持Vue的选项。步骤:

  1. 定义混入对象:let cmixin={}
  2. 组件中使用:mixins:[cmixin],混入对象中的内容。

代码混入(合并)规则:

  • 选项合并:如果混入时存在代码冲突,则会先递归合并,然后本地优先的策略。
  • 混入的钩子,合并为一个数组,依次调用。
  • 全局混入Vue.mixin( mixin ),应用于后面所有的Vue对象。
  • 混入优先级:本地代码优先 > 局部混入 全局混入。
  • 自定义混入合并策略:Vue.config.optionMergeStrategies
  1. let cmixin = {
  2. data: { message: "hello world!" },
  3. methods: { say: function () { console.log(this.message) } }
  4. }
  5. let app1 = new Vue({
  6. el: "#app1",
  7. data:{name:'sam'},
  8. mixins: [cmixin],
  9. //...cmixin, //不支持合并,会覆盖已有属性值
  10. created: function () { this.say() }
  11. })

用ES6的展开运算符...,也能达到类似的复用目的,不过不支持合并策略。

2.2、v-自定义指令

指令是对Dom元素的扩展,具有一定的行为特征(钩子函数)。注册的自定义指令,需要用指令的钩子函数来触发指令行为,一个指令支持多个钩子函数,不同钩子函数(触发点)可设置不同的行为。如果不指定钩子函数,就是全都要,都会触发调用。

注册方式:全局、局部

  • 全局注册Vue.directive( id, [definition] ),注意顺序,先定义后使用。
  • 局部注册-选项directives:{ id: { } }

指令命名:参考HTML命名规范,小写+连字符,正式指令名称会加上v-

指令函数参数(el, binding, vnode, oldVnode)

  • el:绑定的Dom元素。
  • binding:指令对象,包含指令名称name、参数arg、修饰符modifiers、属性值value、上一次的属性值oldValue、指令表达式 expression。这里的值可用来做变化判断,以优化指令性能。
  • vnode:虚拟Dom元素
  • oldVnode:上一个虚拟Dom元素

使用<input v-id:arg.ky='value'>

构子函数 描述
bind 只调用一次,指令第一次绑定到元素时调用。
inserted 被绑定元素插入父节点时调用
update 所在组件的 VNode 更新时调用
componentUpdated 所在组件的 VNode 更新后调用
unbind 只调用一次,指令与元素解绑时调用

自定义指令-验证器表单输入:值为需要验证的数据,其他验证参数check-reg、check-error用自定属性申明,指令用在表单元素后面的一个用于提示错误的元素上。

  1. <div id="app1">
  2. <p>
  3. <label>用户名:<input type="text" v-model="userName" maxlength="40" size="40" placeholder="请输入用户名"></label>
  4. <span v-check.required="userName" check-reg="^\w{4,6}$" check-error="用户名必须是4-6位的字母数字"></span>
  5. </p>
  6. <p>
  7. <label>用户名:<input type="text" v-model="email" maxlength="40" size="40" placeholder="请输入邮箱"></label>
  8. <span v-check="email" check-reg="^\w+@\w+\.\w+$" check-error="邮箱格式不合法"></span>
  9. </p>
  10. </div>
  11. <script>
  12. // 验证器(必填修饰符),正则,错误信息,check,check-reg,check-error
  13. let mixinDirectivesValidator = {
  14. directives: {
  15. check: { //check指令:v-check
  16. //绑定指令时触发
  17. bind(el, bind) {
  18. //先读取check的配置属性信息,暂存备用
  19. el.text = el.getAttribute('check-error');
  20. el.reg = new RegExp(el.getAttribute('check-reg'));
  21. el.style.color = 'red';
  22. el.style.fontSize = '0.8em';
  23. if (bind.modifiers.required) el.innerText = ' * 必填';
  24. },
  25. //更新视图时触发
  26. update: function (el, bind) {
  27. if (bind.value === bind.oldValue) return;
  28. el.innerText = '';
  29. if (bind.modifiers.required) el.innerText = ' * 必填';
  30. if (bind.value && !el.reg.test(bind.value)) el.innerText = el.text;
  31. }
  32. }
  33. }
  34. }
  35. let app1 = new Vue({
  36. el: "#app1",
  37. data: { userName: '', email: '' },
  38. mixins: [mixinDirectivesValidator]
  39. })
  40. </script>

2.3、| 插值过滤器

过滤器就是一个函数,在{{文本插值}}v-bind="表达式"绑定表达式后面使用,对绑定的值进行过滤(再加工)处理。支持链式的过滤使用,支持参数,常用于格式化显示。在V2、V3中,过滤器被逐渐弱化,更推荐用表达式或计算属性。

  • 全局过滤器Vue.filter( id, func(value,...arg ),第一个参数为管道符号前面的绑定值。
  • 局部过滤器-filters{id:func(value,...arg)}选项,(多了个s
  • 使用:用管道符号连接,{{文本插值 | filter1 | filter2(arg)}}
  1. <style>
  2. #app2 *{
  3. font-family:'Courier New', Courier, monospace;
  4. }
  5. </style>
  6. <div id="app2">
  7. <ul>
  8. <li v-for="a in arr">{{a | fixedLength(3,'&nbsp;')}}: {{a|fixedLength(4)| money|money|money}}</li>
  9. </ul>
  10. </div>
  11. <script>
  12. //全局过滤器,数字固定长度
  13. Vue.filter("fixedLength", function (value, length,char='0') {
  14. return (Array(length).join(char) + value).slice(-length);
  15. })
  16. let app2 = new Vue({
  17. el: "#app2",
  18. data: { arr: [1, 2, 3, 44, 55, '5K'] },
  19. //具备过滤器定义
  20. filters: {
  21. money: function (v) { return '¥' + v; }
  22. }
  23. })
  24. </script>

2.4、Vue插件开发

插件就是一个函数或者包含install()方法的对象,目的是实现封装复用。通过Vue.use() 来安装,给Vue提供全局的扩展能力,如添加全局的指令、方法、组件,混入选项等,很多Vue的UI组件都是这么处理的。

  • install(Vue,...args):插件应该提供的安装函数,第一个参数就是Vue构造器,就可以调用Vue的静态方法做一些处理。后面的参数就是插件自己用的参数了。
  • Vue.use(插件, ...args)注册插件,第一个参数为插件,后面就是插件需要的参数选项了。
  1. // 封装插件
  2. export let SuperPlugin = {
  3. install(Vue, ...args) {
  4. console.log('安装插件SuperPlugin', args);
  5. //安装一个UI组件
  6. Vue.component('super-btn', { template: '<button>Super<slot></slot></button>' });
  7. //添加全局静态方法
  8. Vue.$get = function (url) { /*ajax get*/ };
  9. Vue.$post = function (url, data) { /*ajax post*/ };
  10. //添加实例方法
  11. Vue.prototype.$myMethod = function () { };
  12. //混入全局的选项
  13. Vue.mixin({ created: function () {console.log('创建组件') } });
  14. }
  15. }
  16. // 注册插件
  17. import { SuperPlugin } from './super-plugin.js'
  18. Vue.use(SuperPlugin, 1, 2, 3);

️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

Vue快速上门(3)-组件与复用的更多相关文章

  1. Vue.js——60分钟组件快速入门(上篇)

    组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HTML ...

  2. 转: Vue.js——60分钟组件快速入门(上篇)

    转自: http://www.cnblogs.com/keepfool/p/5625583.html Vue.js——60分钟组件快速入门(上篇)   组件简介 组件系统是Vue.js其中一个重要的概 ...

  3. Vue.js——60分钟组件快速入门

    一.组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HT ...

  4. 【转】Vue.js——60分钟组件快速入门(上篇)

    文章作者:keepfool 文章出处:http://www.cnblogs.com/keepfool/ 组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的 ...

  5. Vue.js——60分钟组件快速入门(上篇)二

    来源:https://www.cnblogs.com/keepfool/p/5625583.html 组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小 ...

  6. Vue.JS快速上手(组件生命周期)

    一.什么是组件 组成网页独立功能基本单元(片段), 复用.维护.性能, Vue.js中的组件就是一个Vue的实例,Vue中的组件包含data/methods/computed. 一个Vue.js的应用 ...

  7. Vue.js——60分钟组件快速入门(下篇)

    概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子组件中定义props,可以让父组件的数据传递下来,这就好比子组件告诉父组件:"嘿,老哥,我开 ...

  8. Vue.js——60分钟组件快速入门(下篇)

    转自:https://www.cnblogs.com/keepfool/p/5637834.html 概述 上一篇我们重点介绍了组件的创建.注册和使用,熟练这几个步骤将有助于深入组件的开发.另外,在子 ...

  9. Vue.JS快速上手(组件间的通信)

    前言 Vue采用的是组件化思想,那么这些组件间是如何通信的呢?下面详细介绍一下. 所谓组件间通信,不单单是我们字面上理解的相互传递数据,这里还包括一个组件访问另一个组件的实例方法等,如父组件通过ref ...

  10. 使用Vue快速开发单页应用

    本文所涉及代码全在vue-cnode 单页应用,即在一个页面集成系统中所有功能,整个应用只有一个页面.因为路由的控制在前端,单页面应用在页面切换时比传统页面更快,从而在前端体验更好. 将逻辑从后端转移 ...

随机推荐

  1. VScode开发STM32/GD32单片机-环境搭建

    1.软件下载 1.1.安装VSCode 1.2.下载安装VisualGDB 1.3.下载安装mingwin64 1.4.下载安装OpenOCD 1.5.下载GNU Arm Embedded Toolc ...

  2. 文盘Rust -- struct 中的生命周期

    最近在用rust 写一个redis的数据校验工具.redis-rs中具备 redis::ConnectionLike trait,借助它可以较好的来抽象校验过程.在开发中,不免要定义struct 中的 ...

  3. 代码随想录第八天 |344.反转字符串 、541. 反转字符串II、剑指Offer 05.替换空格 、151.翻转字符串里的单词 、剑指Offer58-II.左旋转字符串

    第一题344.反转字符串 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 s 的形式给出. 不要给另外的数组分配额外的空间,你必须原地修改输入数组.使用 O(1) 的额外空间解决这 ...

  4. Java一次返回中国所有省市区三级树形级联+前端vue展示【200ms内】

    一.前言 中国省市区还是不少的,省有34个,市有391个,区有1101个,这是以小编的库里的,可能不是最新的,但是个数也差不了多少. 当一次返回所有的数据,并且还要组装成一个三级树,一般的for,会循 ...

  5. Java学习之路:HelloWorld

    2022-10-08 16:13:57 HelloWorld   1. 随便新建一个文件夹,存放代码   2. 新建一个Java文件 文件后缀名为.java hello.java 注意:系统没有显示后 ...

  6. 安装 LAMP 环境(yum 版本) shell脚本

    #!/bin/bash # 安装 LAMP 环境(yum 版本) # 本脚本适用于 RHEL7(RHEL6 中数据库为 mysql) yum makecache &>/dev/null ...

  7. Redis Cluster 原理说的头头是道,这些配置不懂就是纸上谈兵

    Redis Cluster 原理说的头头是道,这些配置不懂就是纸上谈兵 Redis Cluster 集群相关配置,使用集群方式的你必须重视和知晓.别嘴上原理说的头头是道,而集群有哪些配置?如何配置让集 ...

  8. nrf52——DFU升级OTA升级方式详解(基于SDK开发例程)

    在我们开始前,默认你已经安装好了一些基础工具,如nrfutil,如果你没有安装过请根据官方中文博客去安装好这些基础工具,连接如下:Nordic nRF5 SDK开发环境搭建(nRF51/nRF52芯片 ...

  9. 在 .NET 7上使用 WASM 和 WASI

    WebAssembly(WASM)和WebAssembly System Interface(WASI)为开发人员开辟了新的世界..NET 开发人员在 Blazor WebAssembly 发布时熟悉 ...

  10. 抓包分析 TCP 握手和挥手

    前言 首先需要明确的是 TCP 是一个可靠传输协议,它的所有特点最终都是为了这个可靠传输服务.在网上看到过很多文章讲 TCP 连接的三次握手和断开连接的四次挥手,但是都太过于理论,看完感觉总是似懂非懂 ...