当前位置: 首页 > news >正文

Vue3 中组件的使用(上)

目录

  • 前言:
  • 一、什么是组件
  • 二、注册组件
    • 1. 全局注册
    • 2. 局部注册
  • 二、传递数据【父 -> 子】
    • 1. 字符串数组的形式
    • 2. 对象的形式
  • 三、组件事件【子 -> 父】
    • 1. 字符串数组式声明自定义事件
    • 2. 【子组件】触发组件事件
    • 3. 【父组件】监听子组件自定义事件
    • 4. 组件事件例子
  • 总结:

前言:

在编写vue里的SPA(Single Page Application单页面应用)时,我们始终绕不开组件的使用,Vue3 里有一些重要更新,在这里分享给大家。


一、什么是组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:
请添加图片描述

组件就相当于页面的零件,当做正常的标签使用,不过能够进行自定义的数据传输和事件监听。
组件内也能使用其他的组件,任意处都能够使用。


二、注册组件

一个 Vue 组件在使用前需要先被 “注册”,这样 Vue 才能在渲染模板时找到其对应的实现;组件注册有两种方式:全局注册、局部注册


1. 全局注册

可使用 app.component(name, Component)注册组件的方法,在此应用的任意组件的模板中使用

  • name:注册的名字
  • Component:需要注册的组件
// 在 main.js 中注册全局组件
import { createApp } from 'vue'
import App from './App.vue'
// 1:引入需要被注册的组件
import Login from './components/Login.vue' const app = createApp(App)// 2:全局注册组件
app.component('MLogin', Login)app.mount('#app')
// 我们使用注册的组件
<template><h3>登录系统</h3><!-- 使用全局注册的组件 --><MLogin />
</template>

2. 局部注册

局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用

在组合式 API 中的 <script setup> 内,直接导入的组件就可以在模板中直接可用,无需注册。

<script setup>
// 1:引入需要注册的组件,无需注册
import LoginVue from './components/Login.vue';
</script><template><h3>登录系统</h3><!-- 2:使用全局注册的组件 --><LoginVue />
</template>

二、传递数据【父 -> 子】

如果父组件向子组件进行传递数据,那么我们需要在子组件中声明 props 来接收传递数据的属性,可采用字符串数组式或对象式来声明 props
父组件向子组件传递数据,在使用组件
let 的标签上采用属性方式传递的 props 值,可使用 v-bind:: 来绑定属性
组件中 props 中的数据是只读的,不可直接更改,只能通过父组件进行更改

声明与使用

  1. 在选项式 API
    1. 我们可以提供 props 选项来声明接收传递的数据
    2. 在 JS 中可使用 this.$props 来访问声明的自定义的属性
    3. 在视图模板中,可直接访问 props 中声明的自定义属性
  2. 在组合式 API
    1. 我们可以采用 defineProps 宏来声明接收传递的数据
    2. 在 JS 中可使用 defineProps 返回的对象来访问声明的自定义的属性
    3. 在视图模板中,可直接访问 defineProps 中声明的自定义属性

1. 字符串数组的形式

// 字符串数组的形式
<script setup>// 使用 defineProps 宏来声明
defineProps(['flat', 'title']) </script>

例子:

// 父组件
<script setup>
import { ref } from 'vue';
import ButtonVue from './components/Button.vue';let isError = ref(false) // 主题
let isFlat = ref(false) // 阴影
let btnText = ref('普通按钮') // 按钮文本
</script><template>主题:<input type="checkbox" v-model="isError">阴影:<input type="checkbox" v-model="isFlat">按钮文本:<input type="text" v-model="btnText"><hr><!-- 父向子传值,可采用属性的方式赋值 --><ButtonVue :title="btnText" :error="isError" :flat="isFlat"/>
</template>
// 子组件
<script setup>
// 声明接收父组件传递的属性值:自定义属性
let propsData = defineProps(['title', 'error', 'flat'])function showPropsData() {// 在 JS 中,需要通过 defineProps 返回对象来访问 props 的内容console.log(propsData)console.log(propsData.title)console.log(propsData.error)console.log(propsData.flat)
}function changeErrorProps() {// 不能直接修改 props 的数据,因为是只读的propsData.error = !propsData.error
}
</script><template><!-- 在视图模板上,可直接使用 props 中的属性 --><button :class="{ error, flat }" @click="showPropsData" @mousedown.right="changeErrorProps">{{ title }}</button>
</template><style>
button {border: none;padding: 12px 25px;
}.error {background-color: rgb(197, 75, 75);color: white;
}.flat {box-shadow: 0 0 10px grey;
}
</style>

2. 对象的形式

对象形式声明的 props,可以对传来的值进行校验,如果传入的值不满足类型要求,会在浏览器控制台中抛出警告来提醒使用者
对象形式声明的 propskeyprop 的名称,值则为约束的条件

对象中的属性:

type:类型,如 StringNumberBooleanArrayObjectDateFunctionSymbol
default:默认值;对象或者数组应当用工厂函数返回
required:是否必填,布尔值
validator:自定义校验,函数类型

<script>
// 对象的形式defineProps({// 基础类型检查// (给出 `null` 和 `undefined` 值则会跳过任何类型检查)propA: Number,// 多种可能的类型propB: [String, Number],// 必传,且为 String 类型propC: {type: String,required: true},// Number 类型的默认值propD: {type: Number,default: 100},// 对象类型的默认值propE: {type: Object,// 对象或数组的默认值// 必须从一个工厂函数返回。// 该函数接收组件所接收到的原始 prop 作为参数。default(rawProps) {return { message: 'hello' }}},// 自定义类型校验函数propF: {validator(value) {// The value must match one of these stringsreturn ['success', 'warning', 'danger'].includes(value)}},// 函数类型的默认值propG: {type: Function,// 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数default() {return 'Default function'}}})
</script>

例子:

// 父组件
<script setup>
import { ref } from 'vue';
import ButtonVue from './components/Button.vue';let isError = ref(false) // 主题
let isFlat = ref(false) // 阴影
let btnText = ref('普通按钮') // 按钮文本
</script><template>主题:<input type="checkbox" v-model="isError">阴影:<input type="checkbox" v-model="isFlat">按钮文本:<input type="text" v-model="btnText"><hr><!-- 父向子传值,可采用属性的方式赋值 --><ButtonVue :title="btnText" :error="isError" :flat="isFlat"/>
</template>
// 子组件
<script setup>
// 声明接收父组件传递的属性值:自定义属性
let propsData = defineProps({title: {type: String,required: true},error: Boolean,flat: Boolean,tips: {type: String,default: '我是一个普通的按钮'}
})function showPropsData() {// 在 JS 中,需要通过 defineProps 返回对象来访问 props 的内容console.log(propsData)console.log(propsData.title)console.log(propsData.error)console.log(propsData.flat)
}function changeErrorProps() {// 不能直接修改 props 的数据,因为是只读的propsData.error = !propsData.error
}
</script><template><!-- 在视图模板上,可直接使用 props 中的属性 --><button :title="tips" :class="{ error, flat }" @click="showPropsData" @mousedown.right="changeErrorProps">{{ title }}</button>
</template><style>
button {border: none;padding: 12px 25px;
}.error {background-color: rgb(197, 75, 75);color: white;
}.flat {box-shadow: 0 0 10px grey;
}
</style>

注意:

  1. 所有 prop 默认都是可选的,除非声明了 required: true
  2. Boolean 外的未传递的可选prop将会有一个默认值 undefined
  3. Boolean 类型的未传递 prop 将被转换为 false
  4. prop 的校验失败后,Vue 会抛出一个控制台警告【在开发模式下】
  5. 注意 prop 的校验是在组件实例被创建之前
    1. 在选项式 API 中,实例的属性(比如 datacomputed 等) 将在 defaultvalidator 函数中不可用
    2. 在组合式 API 中,defineProps 宏中的参数不可以访问 <script setup> 中定义的其他变量,因为在编译时整个表达式都会被移到外部的函数中

特别提醒:

关于 Boolean 类型转换:
为了更贴近原生 boolean attributes 的行为,声明为 Boolean 类型的 props 有特别的类型转换规则
如声明时:defineProps({ error: Boolean })
传递数据时:
- <MyComponent error/>:相当于 <MyComponent :error="true" />
- <MyComponent />:相当于 <MyComponent :error="false" />


三、组件事件【子 -> 父】

有的时候,父组件在使用子组件时,子组件如何给父组件传值呢?

  1. 子组件声明自定义的事件
  2. 子组件中触发自定义事件(可传值)
  3. 父组件使用子组件时监听对应的自定义事件,并执行父组件中的函数(获取子组件传递的值)

1. 字符串数组式声明自定义事件

  1. 在选项式 API 中,子组件可通过 emits 选项来声明自定义的事件
  2. 在组合式 API 中,子组件可通过 defineEmits() 宏来声明自定义的事件

字符串数组式声明自定义事件

采用字符串数组可以声明简单的自定义事件:

<script setup>defineEmits(['inFocus', 'submit'])
</script>

对象式声明自定义事件

采用对象式声明自定义事件,还可以进行校验传递的参数是否符合预期要求
对象式声明自定义事件中,属性名为自定义事件名,属性值则是是否验证传递的参数:

  1. 属性值为 null 则不需要验证
  2. 属性值为函数时,参数为传递的数据,函数返回 true 则验证通过,返回 false 则验证失败,验证失败可以用警告语句提示开发者【注意:无论是 true 还是 false 都会继续执行下去的,父组件都会获取到传递的值】
<script setup> 
defineEmits({autoEvent1: null, // 无需校验// 需要校验,param 可以是多个参数,返回布尔值来表明事件是否合法autoEvent2: (param) => {// true 则通过// false 则不通过,可以在控制台输入警告语句}
})
</script>

2. 【子组件】触发组件事件

在选项式 API 中,可通过组件当前实例 this.$emit(event, ...args) 来触发当前组件自定义的事件
在组合式 API 中,可调用 defineEmits 宏返回的 emit(event, ...args) 函数来触发当前组件自定义的事件
其中上方两个参数分别为:

  • event:触发事件名,字符串类型
  • ...args:传递参数,可没有,可多个
<script setup>// 自定义事件,并返回 emit 函数
const emit = defineEmits(['changeAge'])function emitAgeEvent() {// 触发自定义事件 changeAge,并传递参数 1,20emit('changeAge', 1, 20)
}
</script><template><button @click="emitAgeEvent">触发自定义事件</button><hr><!-- 触发自定义事件 changeAge,并传递参数 30 --><button @click="emit('changeAge', 30)">触发自定义事件</button>
</template>

3. 【父组件】监听子组件自定义事件

使用 v-on:event="callback" 或者 @event="callback" 来监听子组件是否触发了该事件

  1. event:事件名字(camelCase 形式命名的事件,在父组件中可以使用 kebab-case 形式来监听)
  2. callback:回调函数,如果子组件触发该事件,那么在父组件中执行对应的回调函数,回调函数声明参数可自动接收到触发事件传来的值
<script setup>
import { ref } from 'vue';import ButtonVue from './components/Button.vue';let startAge = ref(0)
let endAge = ref(0)// 子组件触发事件的回调函数
function addAge(start_age, end_age) {console.log('----------------');console.log(start_age)console.log(end_age)startAge.value = start_ageendAge.value = end_age
}
</script><template><h3>开始年龄:{{ startAge }}</h3><h3>结束年龄:{{ endAge }}</h3><!-- 使用引入的组件,并通过属性传递数据 --><ButtonVue @change-age="addAge" />
</template>

4. 组件事件例子

字符串数组式声明自定义事件

// 父组件
<script setup>
import { reactive } from 'vue';
import StudentVue from './components/Student.vue';let student = reactive({name: 'Jack',age: 18,sex: '男'
})// 获取子组件传递值
function getNewAge(newAge) {console.log('年龄的新值:' + newAge)student.age = newAge
}
function getNewAgeAndName(newAge, newName) {console.log('年龄的新值:' + newAge)console.log('名字的新值:' + newName)student.age = newAgestudent.name = newName
}
function getNewStudent(stu){console.log('学生新值:');console.log(stu);student.age = stu.agestudent.name = stu.namestudent.sex = stu.sex
}
</script><template>{{ student }}<hr><StudentVue @change-student="getNewStudent"@change-age-and-name="getNewAgeAndName" @change-age="getNewAge" />
</template>
// 子组件
<script setup>
// 自定义事件
let emit = defineEmits(['changeAge', 'changeAgeAndName', 'changeStudent'])function emitEventAge() {// 选项式通过 this.$emit 触发自定义事件,并传值emit('changeAge', 30)
}</script><template><button @click="emitEventAge">更改年龄</button><br><br><button @click="emit('changeAgeAndName', 10, 'Annie')">更改年龄和名字</button><br><br><button @click="emit('changeStudent', { age: 40, name: 'Drew', sex: '男' })">更改学生(验证通过)</button><br><br><button @click="emit('changeStudent', { age: -10, name: 'Tom', sex: '男' })">更改学生(验证失败)</button>
</template>

对象式声明自定义事件

// 父组件
<script setup>
import { reactive } from 'vue';
import StudentVue from './components/Student.vue';let student = reactive({name: 'Jack',age: 18,sex: '男'
})// 获取子组件传递值
function getNewAge(newAge) {console.log('年龄的新值:' + newAge)student.age = newAge
}
function getNewAgeAndName(newAge, newName) {console.log('年龄的新值:' + newAge)console.log('名字的新值:' + newName)student.age = newAgestudent.name = newName
}
function getNewStudent(stu){console.log('学生新值:');console.log(stu);student.age = stu.agestudent.name = stu.namestudent.sex = stu.sex
}
</script><template>{{ student }}<hr><StudentVue @change-student="getNewStudent"@change-age-and-name="getNewAgeAndName" @change-age="getNewAge" />
</template>
// 子组件
<script setup>
// 自定义事件
let emit = defineEmits({changeAge: null, // 无需验证changeAgeAndName: null, // 无需验证changeStudent: stu => {if (stu.age <= 0) {console.warn('年龄不得小于等于0')// false:验证不通过,会有警告语句,父组件依旧可以获取该值return false}// true:验证通过return true}
})function emitEventAge() {// 选项式通过 this.$emit 触发自定义事件,并传值emit('changeAge', 30)
}</script><template><button @click="emitEventAge">更改年龄</button><br><br><button @click="emit('changeAgeAndName', 10, 'Annie')">更改年龄和名字</button><br><br><button @click="emit('changeStudent', { age: 40, name: 'Drew', sex: '男' })">更改学生(验证通过)</button><br><br><button @click="emit('changeStudent', { age: -10, name: 'Tom', sex: '男' })">更改学生(验证失败)</button>
</template>

总结:

欢迎大家加入我的社区,在社区中会不定时发布一些精选内容:https://bbs.csdn.net/forums/db95ba6b828b43ababd4ee5e41e8d251?category=10003


以上就是 Vue3 中组件的使用(上),不懂得也可以在评论区里问我或私聊我询问,以后会持续发布一些新的功能,敬请关注。
我的其他文章:https://blog.csdn.net/weixin_62897746?type=blog

相关文章:

Vue3 中组件的使用(上)

目录前言&#xff1a;一、什么是组件二、注册组件1. 全局注册2. 局部注册二、传递数据【父 -> 子】1. 字符串数组的形式2. 对象的形式三、组件事件【子 -> 父】1. 字符串数组式声明自定义事件2. 【子组件】触发组件事件3. 【父组件】监听子组件自定义事件4. 组件事件例子…...

spring-boot、spring-cloud、spring-cloud-alibaba版本对应

一、查询 spring-boot(spring-boot-starter-parent) 版本号 https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent 二、查询 spring-cloud(spring-cloud-dependencies) 版本号 https://mvnrepository.com/artifact/org.springframework…...

【沐风老师】3DMAX一键楼梯脚本插件StairGenerator使用教程

3DMAX一键楼梯插件StairGenerator&#xff0c;不需要花费太多的时间&#xff0c;轻松从2D平面图生成3D楼梯模型&#xff0c;生成的楼梯模型细节丰富真实。 【主要功能】 1.简单&#xff1a;轻松实现2D到3D建模。 2.具有最详细三维结构的台阶平面图。 3.楼梯各部件完全参数化…...

OpenShift 简介

OpenShift 是红帽 Red Hat 公司基于开源的云平台&#xff0c;是平台即服务&#xff08;PaaS&#xff09;&#xff0c;是一种容器应用平台。允许开发人员构建、测试和部署云应用。该系统是在 K8S 核心之上添加工具&#xff0c;从而实现更快的应用开发、部署及扩展。 在 OpenShi…...

netty自定义封包实现

文章目录说明分享内置编码器和解码器解码器编码器代码实现创建核心类消息实体类自定义编码类自定义解码类服务端ServerHandler入口类客户端ClientHandler入口类测试参考总结说明 netty是java重要的企业级NIO&#xff0c;使用它可以快速实现很多功能通信功能如&#xff1a;http、…...

ORA error集锦

1、oralce 数据客户端需要安装的问题 保存信息为&#xff1a; “无法连接到数据库&#xff0c;因为数据库客户端软件无法加载。确保已正确安装并配置数据库客户端软件” 从百度网盘下载&#xff0c;并安装win32 oracle client 安装包 2、ORA错误 “执行异常,ORA-00911: inval…...

格雷码的实现

格雷码&#xff1a;任意两个相邻的二进制数之间只有一位不同 想必通信专业的学生应该都接触过格雷码&#xff0c;它出现在数电、通信原理等课程里。 如下图所示一个四位格雷码是什么样子的&#xff1a; 格雷码的特点&#xff1a; 其最大的特点是任意上下相邻的两个码值间&am…...

快到金3银4了,准备跳槽的可以看看

前两天跟朋友感慨&#xff0c;今年的铜九铁十、裁员、疫情导致好多人都没拿到offer!现在已经12月了&#xff0c;具体明年的金三银四只剩下两个月。 对于想跳槽的职场人来说&#xff0c;绝对要从现在开始做准备了。这时候&#xff0c;很多高薪技术岗、管理岗的缺口和市场需求也…...

最新BlackArch发布,提供1400款渗透测试工具

近日&#xff0c;BlackArch Linux新版本发布&#xff0c;此版本为白帽子和安全研究人员提供了大约1400款渗透测试工具&#xff0c;如果你是一位白帽子或者安全研究人员&#xff0c;这个消息无疑会让你很感兴趣。BlackArch Linux是一款基于Arch Linux的发行版&#xff0c;主要面…...

重走前端路JS进阶篇:This 指向与箭头函数

JavaScript 高级 This 指向规则 案例 function foo() {console.log(this)}// 1 调用方式1foo();// 2 调用方式2 放入对象中调用var obj {name: "why",foo: foo}obj.foo()// 调用方式三 通过 call/apply 调用foo.call("abc")指向定义 this 是js 给函数的…...

Python基础:函数式编程

一、概述 Python是一门多范式的编程语言&#xff0c;它同时支持过程式、面向对象和函数式的编程范式。因此&#xff0c;在Python中提供了很多符合 函数式编程 风格的特性和工具。 二、lambda表达式&#xff08;匿名函数&#xff09; 除了 函数 中介绍的 def语句&#xff0c;P…...

【YBT2023寒假Day14 C】字符串题(SAM)(树链剖分)(线段树)

字符串题 题目链接&#xff1a;YBT2023寒假Day14 C 题目大意 对于一个字符串 S 定义 F(S) 是 fail 树上除了 0 点其它点的深度和。 G(S) 是 S 每个子串 S’ 的 F(S’) 之和。 然后一个空串&#xff0c;每次在后面加一个字符&#xff0c;要你维护这个串的 G 值。 思路 考虑…...

Tailwind CSS 在Vue中的使用

什么是Tailwind CSS&#xff1f; Tailwind CSS 是一个功能类优先的 CSS 框架&#xff0c;它集成了诸如 flex, pt-4, text-center 和 rotate-90 这样的的类&#xff0c;支持 hover 和 focus 样式&#xff0c;它们能直接在脚本标记语言中组合起来&#xff0c;构建出任何设计。 …...

三层楼100人办公网络如何规划设计实施(实战案例)

如何设计组网 1.采用防火墙+三层交换机+二层POE交换机+AP的方案 2.三层交换机作为网络的核心,提供网络的配置、划分和各个VLAN间的数据交换,而每个VLAN由二层交换机组建 3.网络主干设备的选型,建议网络主干设备或核心层设备选择具备第3层交换功能的高性能主干交换机。 4…...

Redis:实现全局唯一ID

Redis&#xff1a;实现全局唯一ID一. 概述二. 实现&#xff08;1&#xff09;获取初始时间戳&#xff08;2&#xff09;生成全局ID三. 测试为什么可以实现全局唯一&#xff1f;其他唯一ID策略补充&#xff1a;countDownLatch一. 概述 全局ID生成器&#xff1a;是一种在【分布式…...

webpack打包基本原理——实现webpack打包核心功能

webpack打包的基本原理 核心功能就是把我们写的模块化代码转换成浏览器能够识别运行的代码&#xff0c;话不多说我们一起来了解它 首先我们建一个空项目用 npm init -y 创建一个初始化的&#xff0c;在跟目录下创建src文件夹&#xff0c;src下创建index.js&#xff0c;add.js…...

git的使用(终端输入指令) 上

git目录前言1.创建仓库2.创建文件和修改数据状态分区![分区](https://img-blog.csdnimg.cn/d124dec6b2b14769ad20b75490f29cae.png)3 .删除、撤销重置 、和比较前言 今天带大家手把手敲一遍 git 流程&#xff1a; 安装一下git&#xff08;详细观看我之前发的git文档&#xff0…...

react定义css样式,使用less,css模块化

引入外部 css文件 import ./index.css此时引入的样式是全局样式 使用less 安装 npm i style-loader css-loader sass-loader node-sass -D生成config文件夹 npm run eject配置 以上代码运行完&#xff0c;会在根目录生成config文件夹 进入 config > webpack.config.js 查找…...

基于JavaWeb的学生管理系统

文章目录 项目介绍主要功能截图:登录用户信息管理院系信息管理班级信息管理新增学生课程管理成绩管理部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系�…...

win11右键新建菜单添加选项

需要操作 2 处注册表&#xff0c; 以下以在右键新建菜单中添加 .html 为例 在主键 HKEY_CLASSES_ROOT 中&#xff0c;搜索 .html 找到后 &#xff0c;右键点击它&#xff0c;选 新建 ->项&#xff0c; 在这里插入图片描述 项目名字是&#xff1a;ShellNew 新建后&#x…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...