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

【uniapp】APP打包上架应用商-注意事项

初雪云-uniapp启动图自定义生成(支持一键生成storyboard)
HBuilderX需要的自定义storyboard文件格式为 " zip压缩包 "

一、“Android” — 设置targetSdkVersion

小米、OPPO、vivo、华为等主流应用商店,将于2023年12月采用 targetSdkVersion>=30的等级要求作为应用上架收录标准。建议广大开发者如期适配。

打开项目的manifest.json文件,在 “App常用其它设置” -> “Android设置” -> “targetSdkVersion” 项中进行设置:
在这里插入图片描述

二、修改App端上传图片/视频 uni.uploadFile

在这里插入图片描述

let that=this;
uni.chooseImage({count: 1,sourceType: ['camera','album'],sizeType: ['compressed', 'original'],success: rey => {uni.showLoading({ title: '上传中',mask: true });uni.uploadFile({url: that.uploadUrl, // 你的上传图片接口filePath: rey.tempFilePaths[0],name: 'file',success:(uploadFileRes) =>{let res = JSON.parse(uploadFileRes.data)uni.hideLoading();if(res.code==1){} else{that.toast(res.msg)}}})},fail: (error) => {}
});

三、配置隐私政策提示框(此方法只支持Android)

在 manifest.json 中配置,在app-plus中添加

uni-app【Android平台隐私与政策提示框】

"privacy" : {"prompt" : "template","template" : {"title" : "用户协议和隐私政策","message" : "  请你务必审慎阅读、充分理解“用户协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href='https://https://xieyi.com'>《用户协议》</a>和<a href='https://https://xieyi.com'>《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。","buttonAccept" : "同意并接受","buttonRefuse" : "暂不同意","second" : {"title" : "温馨提示","message" : "  进入应用前,你需先同意<a href='https://https://xieyi.com'>《用户协议》</a>和<a href='https://https://xieyi.com'>《隐私政策》</a>,否则将退出应用。","buttonAccept" : "同意并继续","buttonRefuse" : "退出应用"}}
},

效果图
在这里插入图片描述

四、华为应用市场审核

用户告知权限申请的目的

【插件市场】解决软件在运行时,未见向用户告知权限申请的目的,华为等上架被拒问题

在这里插入图片描述
4.1 在上传图片中使用

chooseImage选择图片的sourceType要自己定义,来判断选择的权限

<template><view class="page"><view class="authItem" @tap.stop="judgment">上传图片</view><!-- 用户告知权限申请的目的 --><yk-authpup ref="authpup" type="top" @changeAuth="changeAuth" :permissionID="permissionID"></yk-authpup></view>
</template><script>var sourceType = [ ['camera'],['album'],['camera','album'] ]import ykAuthpup from "@/components/yk-authpup/yk-authpup";export default {components: { ykAuthpup },data() {return {// 用户告知权限申请的目的soIndex: 0,permissionID:''}},methods: {judgment() { // 判断H5还是App// #ifdef APP-PLUSlet that=this;uni.showActionSheet({itemList: ['拍摄', '从相册选择'],success: function (res) {that.soIndex = res.tapIndex;if(res.tapIndex==0){ // 相机this.permissionID = 'CAMERA';} else if(res.tapIndex==1){ // 相册选择this.permissionID = 'WRITE_EXTERNAL_STORAGE';}setTimeout(()=>{ this.$refs['authpup'].open(); },200)},fail: function (res) { console.log(res.errMsg); }});// #endif// #ifdef H5this.choose_img();// #endif},choose_img(){var that=this;uni.chooseImage({count: 1,// #ifdef H5sourceType: ['camera','album'],// #endif// #ifdef APP-PLUSsourceType: sourceType[this.soIndex],// #endifsizeType: ['compressed', 'original'],success: rey => {uni.showLoading({ title: '上传中',mask: true });uni.uploadFile({url: that.uploadUrl,filePath: rey.tempFilePaths[0],name: 'file',success:(res) =>{var data=JSON.parse(res.data);if(data.code==1){} else{that.toast(data.msg)}}})},fail: (error) => {}});},}}
</script><style></style>

4.2 对yk-authpup插件进行修改- components/yk-authpup/yk-authpup

由于权限拒绝之后,再次点击 权限说明弹窗总是会一闪一闪,所以进行了修改。
[/** ====新增==== */] 是我修改的内容

<template><!-- 用户告知权限申请的目的 --><view v-if="showPopup" class="uni-popup" :style="{top:isNativeHead?'':StatusBar}"><view :class="[type, ani, animation ? 'ani' : '']" class="uni-custom uni-popup__wrapper" @click="close(true)"><view class="uni-popup__wrapper-box"><view class="title">{{authList[permissionID].title}}</view><view class="content">{{authList[permissionID].content}}</view></view></view></view>
</template><script>export default {name: 'YkAuthpup',props: {// 开启动画animation: {type: Boolean,default: true},type: {type: String,default: 'top'},show: {type: Boolean,default: true},//是否是原生头部isNativeHead:{type: Boolean,default: false},permissionID: {type: [String, Number],default: ''}},data() {return {ani: '',showPopup: false,StatusBar:'',refuseNum:'',//拒绝次数,authList: {'WRITE_EXTERNAL_STORAGE': {title: "存储空间/照片权限申请说明",content: "便于您使用该功能拍照上传您的照片/视频及用于更换头像、XXXX、XXXX等场景中使用,请您确认授权,否则无法使用该功能"},'CAMERA':{title: "相机/摄像头权限申请说明",content: "便于您使用该功能拍照上传您的照片/视频及用于更换头像、XXXX、XXXX等场景中使用,请您确认授权,否则无法使用该功能"},'ACCESS_FINE_LOCATION': {title: "地理位置权限申请说明",content: "便于应用程序可以提供基于位置的服务、计算距离、获取经纬度、定位导航、附近搜索等功能,请您确认授权,否则无法使用该功能"},'CALL_PHONE': {title: "拨打电话权限申请说明",content: "便于您使用该功能联系、XXXX、XXXX,请您确认授权,否则无法使用该功能"}},/** ====新增==== */quanx: {'WRITE_EXTERNAL_STORAGE': 0,'CAMERA': 0,'ACCESS_FINE_LOCATION': 0,'CALL_PHONE': 0,}/** ====新增==== */}},created() {// #ifdef APP-PLUSthis.getSystemInfo();// #endif},methods: {//获取状态栏高度getSystemInfo() {let _this = this;uni.getSystemInfo({success: function(e) {_this.StatusBar = e.statusBarHeight + 'px'; //用于自定义头部时,给手机状态栏留出位置,可通过isNativeHead这个参数控制}})},open() {this.requestPermissions(this.permissionID);},close(type) {this.ani = '';this.$nextTick(() => {setTimeout(() => {this.showPopup = false;}, 300)})},//权限检测requestPermissions(permissionID) {let _this = this;/** ====新增==== */let _quanx = uni.getStorageSync('quanx')||_this.quanx;/** ====新增==== */// #ifdef APP-PLUS//判断安卓与ios设备if (plus.os.name == 'Android') {let _permissionID = 'android.permission.' + permissionID;plus.android.checkPermission(_permissionID,granted => {if (granted.checkResult == -1) {console.log(uni.getStorageSync('quanx'))//还未授权当前查询的权限,打开权限申请目的自定义弹框/** ====新增判断==== */if(_quanx[permissionID]==0){_this.showPopup = true;_this.$nextTick(() => {setTimeout(() => {_this.ani = 'uni-' + _this.type},30)})}/** ====新增==== */}},error => {console.log(error.message);});plus.android.requestPermissions([_permissionID], (e) => {//关闭权限申请目的自定义弹框_this.$nextTick(() => {setTimeout(() => {_this.ani = '';_this.showPopup = false}, 0)})// console.log(e,'kkkkk')if (e.granted.length > 0) { // 已获取的权限/** ====新增==== */_quanx[permissionID]=1;/** ====新增==== *///当前查询权限已授权,此时可以通知页面执行接下来的操作_this.$emit('changeAuth');}if (e.deniedAlways.length > 0) { // 永久拒绝申请的权限/** ====新增==== */_quanx[permissionID]=-1;/** ====新增==== *///当前查询权限已被永久禁用,此时需要引导用户跳转手机系统设置去开启// uni.showModal({// 	title: '温馨提示', content: '还没有该权限,立即去设置开启?',// 	cancelText: "取消", confirmText: "去设置",// 	showCancel: true, confirmColor: '#000', cancelColor: '#666',// 	success: (res) => {// 		if (res.confirm) {// 			_this.goSetting();// 		}// 	}// })}/** ====新增==== */uni.setStorageSync('quanx', _quanx);/** ====新增==== */})} else {//IOS不需要添加自定义弹框来描述权限目的,因为在配置文件的隐私信息访问的许可描述里可添加//正常可以直接调用uni的API调起权限询问弹框使用各种权限,下面的判断使用场景主要是在IOS禁用某权限后,这个可以判断有无权限,进而引导用户跳转设置开启,仅列出了位置、相册、通讯录、相机、录音等权限,其他IOS权限可具体参考 https://ext.dcloud.net.cn/plugin?id=15787let result = 0;if (permissionID == 'ACCESS_FINE_LOCATION') {//IOS检测位置权限let cLLocationManager = plus.ios.importClass("CLLocationManager"),authStatus = cLLocationManager.authorizationStatus(),enable = cLLocationManager.locationServicesEnabled();if (enable && authStatus != 2) {result = 1;} else {result = 0;}plus.ios.deleteObject(cLLocationManager);} else if (permissionID == 'WRITE_EXTERNAL_STORAGE') {//IOS检测相册权限let PHPhotoLibrary = plus.ios.importClass("PHPhotoLibrary"),authStatus = PHPhotoLibrary.authorizationStatus();if (authStatus === 3) {result = 1;} else {result = 0;}plus.ios.deleteObject(PHPhotoLibrary);} else if (permissionID == 'CAMERA') {//IOS检测相机/摄像头权限let avCaptureDevice = plus.ios.importClass("AVCaptureDevice"),authStatus = avCaptureDevice.authorizationStatusForMediaType("vide");if (authStatus === 3) {result = 1;} else {result = 0;}plus.ios.deleteObject(avCaptureDevice);} else if (permissionID == 'CALL_PHONE') {//IOS检测通讯录权限let contactStore = plus.ios.importClass("CNContactStore"),authStatus = contactStore.authorizationStatusForEntityType(0);if (authStatus === 3) {result = 1;} else {result = 0;}plus.ios.deleteObject(contactStore);}else if(permissionID == 'RECORD_AUDIO'){//IOS检测麦克风权限let aVAudioSession = plus.ios.importClass("AVAudioSession"),aVAudio = aVAudioSession.sharedInstance(),authStatus = aVAudio.recordPermission();if ([1684369017, 1970168948].includes(authStatus)) {result = 0;} else {result = 1;}plus.ios.deleteObject(aVAudioSession);}if (result) {//当前查询权限已授权,此时可以通知页面执行接下来的操作that.$emit('changeAuth')} else {//当前查询的权限已禁用,引导用户跳转手机系统设置去开启// uni.showModal({// 	title: '温馨提示', content: '还没有该权限,立即去设置开启?',// 	cancelText: "取消", confirmText: "去设置",// 	showCancel: true, confirmColor: '#000', cancelColor: '#666',// 	success: (res) => {// 		if (res.confirm) {// 			_this.goSetting();// 		}// 	}// })}}// #endif},//跳转手机系统设置goSetting() {if (plus.os.name == "iOS") {var UIApplication = plus.ios.import("UIApplication");var application2 = UIApplication.sharedApplication();var NSURL2 = plus.ios.import("NSURL");var setting2 = NSURL2.URLWithString("app-settings:");application2.openURL(setting2);plus.ios.deleteObject(setting2);plus.ios.deleteObject(NSURL2);plus.ios.deleteObject(application2);} else {var Intent = plus.android.importClass("android.content.Intent");var Settings = plus.android.importClass("android.provider.Settings");var Uri = plus.android.importClass("android.net.Uri");var mainActivity = plus.android.runtimeMainActivity();var intent = new Intent();intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);intent.setData(uri);mainActivity.startActivity(intent);}}}}
</script><style lang="scss">.uni-popup {position: fixed;top: 0;bottom: 0;left: 0;right: 0;z-index: 99999;overflow: hidden;&__wrapper {position: absolute;z-index: 999;/* #ifndef APP-NVUE */box-sizing: border-box;/* #endif */&.ani {/* #ifndef APP-NVUE */transition: all 0.3s;/* #endif */}&.top {top: 0;width:705rpx;/* #ifdef APP-NVUE */left:22.5rpx;/* #endif *//* #ifndef APP-NVUE */left:0;transform: translateY(-705rpx);/* #endif */}&-box {position: relative;/* #ifndef APP-NVUE */box-sizing: border-box;/* #endif */}&.uni-custom {& .uni-popup__wrapper-box {width: 705rpx;/* #ifndef APP-NVUE */margin: 0 22.5rpx;/* #endif */padding: 30upx;background: #fff;border: solid 2rpx #ddd;/* #ifndef APP-NVUE */box-sizing: border-box;/* #endif */border-radius: 16rpx;.title{font-size: 32rpx;font-weight: bold;}.content{margin-top: 16rpx;line-height: 1.6;}}&.top{& .uni-popup__wrapper-box {width: 705rpx;}}}&.uni-top{transform: translateY(0);}}}
</style>

相关文章:

【uniapp】APP打包上架应用商-注意事项

初雪云-uniapp启动图自定义生成&#xff08;支持一键生成storyboard&#xff09; HBuilderX需要的自定义storyboard文件格式为 " zip压缩包 " 一、“Android” — 设置targetSdkVersion 小米、OPPO、vivo、华为等主流应用商店&#xff0c;将于2023年12月采用 targetS…...

【算法题】43. 字符串相乘

题目 给定两个以字符串形式表示的非负整数 num1 和 num2&#xff0c;返回 num1 和 num2 的乘积&#xff0c;它们的乘积也表示为字符串形式。 注意&#xff1a;不能使用任何内置的 BigInteger 库或直接将输入转换为整数。 示例 1: 输入: num1 "2", num2 "3…...

CH341 SPI方式烧录BK7231U

CH341是一个USB总线的转接芯片&#xff0c;通过USB总线提供异步串口、打印口、并口以及常用的2线和4线等同步串行接口。 BK7231U Wi-Fi SOC芯片&#xff0c;内嵌处理器。1. 符合802.11b/g/n 1x1协议 2. 17dBm 输出功率3. 支持20/40 MHz带宽和STBC 4. 支持Wi-Fi STA、AP、…...

sd-webui-EasyPhoto win 安装笔记

目录 安装教程: 插件介绍 ControlNet 1.1 Tile: launch.py问题 依赖库 webui安装问题...

gradient_checkpointing

点评:本质是减少内存消耗的一种方式,以时间或者计算换内存 gradient_checkpointing(梯度检查点)是一种用于减少深度学习模型中内存消耗的技术。在训练深度神经网络时,反向传播算法需要在前向传播和反向传播之间存储中间计算结果,以便计算梯度并更新模型参数。这些中间结…...

回溯算法part05 算法

回溯算法part05 算法 今日任务 491.递增子序列46.全排列47.全排列 II 1.LeetCode 491.递增子序列 https://leetcode.cn/problems/non-decreasing-subsequences/description/ class Solution {List<List<Integer>> resultnew ArrayList<>();List<Inte…...

阿里云系统盘测评ESSD、SSD和高效云盘IOPS、吞吐量性能参数表

阿里云服务器系统盘或数据盘支持多种云盘类型&#xff0c;如高效云盘、ESSD Entry云盘、SSD云盘、ESSD云盘、ESSD PL-X云盘及ESSD AutoPL云盘等&#xff0c;阿里云百科aliyunbaike.com详细介绍不同云盘说明及单盘容量、最大/最小IOPS、最大/最小吞吐量、单路随机写平均时延等性…...

RK3568平台开发系列讲解(Linux系统篇)Linux 内核打印

🚀返回总目录 文章目录 一、方法一:dmseg 命令二、方法二:查看 kmsg 文件三、方法三:调整内核打印等级一、方法一:dmseg 命令 在终端使用 dmseg 命令可以获取内核打印信息,该命令的具体使用方法如下所示: 首先在串口终端使用 “dmseg”命令,可以看见相应的内核打印信息…...

迁移学习的最新进展和挑战

随着深度学习和人工智能技术的飞速发展&#xff0c;迁移学习作为一种有效的机器学习方法&#xff0c;已经在各个领域取得了显著的成果。迁移学习是指将一个领域&#xff08;源领域&#xff09;的知识应用到另一个领域&#xff08;目标领域&#xff09;&#xff0c;以提高目标领…...

Python基础(二十二、自定义模块和包)

文章目录 一、自定义模块1.如何自定义模块并导入?2.__main__变量的功能3.注意事项 二、自定义包1.什么是Python的包?2.__init __.py文件的作用?3.__all__变量的作用?4.示例 三、自定义模块和自定义包的好处 一、自定义模块 1.如何自定义模块并导入? 在Python代码文件中正…...

C#-数组

数组 (array) 是一种包含若干变量的数据结构&#xff0c;这些变量都可以通过计算索引进行访问。数组中包含的变量&#xff08;又称数组的元素&#xff09;具有相同的类型&#xff0c;该类型称为数组的元素类型。 数组类型为引用类型&#xff0c;因此数组变量的声明只是为数组实…...

机器学习周刊第二期:300个机器学习应用案例集

大家好 前文&#xff1a;机器学习项目精选 第一期 继续分享我最近看过并觉得非常硬核的资源&#xff0c;包括Python、机器学习、深度学习、大模型等等。 1、Python编程挑战 地址&#xff1a;https://github.com/Asabeneh/30-Days-Of-Python 30天Python编程挑战是一个逐步学…...

【华为OD机试真题2023CD卷 JAVAJS】中文分词模拟器

华为OD2023(C&D卷)机试题库全覆盖,刷题指南点这里 中文分词模拟器 知识点图字符串 时间限制:5s 空间限制:256MB 限定语言:不限 题目描述: 给定一个连续不包含空格字符串,该字符串仅包含英文小写字母及英文文标点符号(逗号、分号、句号),同时给定词库,对该字符串进…...

基于YOLOv8-pose的画笔关键点(bic_markers)检测

💡💡💡本文解决什么问题:教会你如何用自己的数据集训练Yolov8-pose关键点检测 Yolov8-Pose关键点检测专栏介绍:https://blog.csdn.net/m0_63774211/category_12398833.html ✨✨✨手把手教你从数据标记到生成适合Yolov8-pose的yolo数据集;...

【实用技巧】Windows 电脑向iPhone或iPad传输视频方法1:无线传输

一、内容简介 本文介绍如何使用 Windows 电脑向 iPhone 或 iPad 传输视频&#xff0c;以 iPhone 为例&#xff0c;iPad的操作方法类似&#xff0c;本文不作赘述。 二、所需原材料 Windows 电脑&#xff08;桌面或其它文件夹中存有要导入的视频&#xff09;、iPhone 14。 待…...

爬虫实战 - 微博评论数据可视化

简介&#xff1a; 我们都知道在数据比较少的情况下&#xff0c;我们是可以很轻易的获取到数据中的信息。但是当数据比较庞大的时候呢&#xff0c;我们就很难看出来了。尤其是面对现如今数以万计的数据&#xff0c;就更了。 不过好在我们可以通过计算机来帮我们进行分析&#…...

python装饰器嵌套基础

1 python装饰器嵌套基础 python支持装饰器嵌套&#xff0c;即多个装饰器装饰同一个函数或方法。 1.1 嵌套执行顺序 用法 a_deco b_deco c_deco def test_nest_deco():pass描述 a_deco、b_deco、c_deco分别占一行&#xff0c;编写在同一个函数或方法的def语句上方。 从def…...

C语言之三子棋小游戏的应用

文章目录 前言一、前期准备模块化设计 二、框架搭建三、游戏实现打印棋盘代码优化玩家下棋电脑下棋判断输赢 四、结束 前言 三子棋是一种民间传统游戏&#xff0c;又叫九宫棋、圈圈叉叉棋、一条龙、井字棋等。游戏分为双方对战&#xff0c;双方依次在9宫格棋盘上摆放棋子&#…...

优雅处理并发:Java CompletableFuture最佳实践

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天&#xff0c;小黑要和大家聊聊CompletableFuture&#xff0c;这个Java 8引入的强大工具。 在Java传统的Future模式里&#xff0c;咱们都知道&#xff0c;一旦开始了一个异步操作&#xff0c;就只能等它结束…...

熟悉HDFS常用操作

1. 利用Hadoop提供的Shell命令完成下列任务 (1)向HDFS中上传任意文本文件,如果指定的文件在HDFS中已经存在,由用户指定是追加到原有文件末尾还是覆盖原有的文件。 #检查文件是否存在./bin/hdfs dfs -test -e text.txt echo $? #结果是1 代表已存在 #根据结果判断出文件已存…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...