微信小程序性能优化、分包

性能优化是任何应用开发中的重要组成部分,尤其是在移动环境中。对于微信小程序而言,随着用户量的增加和应用功能的丰富,性能优化显得尤为关键。良好的性能不仅提升用户体验,还能增加用户留存率和应用的使用频率。我们将探讨如何在微信小程序中进行性能优化,涵盖从首屏加载、分包、网络请求到渲染性能等多个方面。

  • 网络请求:合并请求,减少HTTP请求次数;使用缓存策略减少重复请求。
  • 布局与样式:避免使用复杂的CSS选择器;合理使用Flex布局减少重排重绘。
  • 事件处理:移除不再需要的事件监听器,防止内存泄漏。
  • 组件懒加载、按需加载

一、优化首屏加载

1. 减少初始包的体积

每个小程序都有一个加载包,包含了代码及依赖。为了加快加载速度,我们应尽量减少包的体积。

  • 懒加载组件:在小程序中使用 Component 时,可以选择懒加载。只有在组件实际需要时再加载。

    Component({
      properties: {
        show: {
          type: Boolean,
          value: false
        }
      },
      observers: {
        'show': function (newVal) {
          if (newVal) {
            // 只在需要展示时加载相关资源
            require('./path/to/your/component.js');
          }
        }
      }
    });
    
  • 拆分代码:把代码拆分成多个小模块,按需加载。
    合理地分割代码模块,不仅可以使代码结构更加清晰,还能够提高加载效率。只加载用户当前需要的部分,避免一次性加载整个应用的所有代码。

    // 示例:按需加载
    const pages = {
      home: () => import('./pages/home'),
      about: () => import('./pages/about')
    };
    
    Page({
      onLoad: function() {
        // 根据需要动态加载页面
        pages.home().then(module => {
          module.default.loadContent();
        });
      }
    });
    
  • 资源懒加载:按需加载图片和其他资源,减少初始加载时间。

    <image src="" mode="widthFix" data-src="{{item.image}}" bindload="imageLoad"/>
    
    // JS部分
    imageLoad(e) {
      e.currentTarget.src = e.currentTarget.dataset.src;
    }
    
  • 资源复用:合理利用已有资源减少重复加载

    对于那些多次使用的资源,如图标、背景等,我们可以将其作为公共资源存储起来,避免在每次加载页面时重复下载。

    // 示例:将公共图标作为公共资源
    const icons = ['icon1.png', 'icon2.png'];
    
    function preloadIcons() {
      icons.forEach(icon => {
        const img = new Image();
        img.src = icon;
      });
    }
    
    preloadIcons();
    

2. 资源压缩与图片优化

  • 图片格式与大小:使用合适的格式,如 JPEG、PNG 或 WEBP。尽可能减小图片尺寸,以减少加载时间。借助工具压缩图片,减少图片大小,同时保持较高质量。
  • 使用云存储:将图片存储在云端,利用 CDN 加速加载。
  • 代码压缩和混淆
    利用构建工具(如webpack)进行代码压缩和混淆,减小包体积,提高加载速度。
    // webpack.config.js
    module.exports = {
      mode: 'production',
      optimization: {
        minimize: true,
      },
    };
    

3. 优化 CSS 和 JavaScript

  • 减少 CSS 选择器的复杂性:复杂的选择器会增加渲染时间,建议使用简短的类名和 ID。
  • 合并 CSS 文件:将多个 CSS 文件合并成一个,减少 HTTP 请求次数。
  • 使用 CSS3 动画:使用 CSS3 动画替代 JavaScript 动画,控制性能和流畅度。

二、网络请求优化

网络请求是小程序性能的另一个关键因素,优化网络请求可以显著提升用户体验。

1. 缓存机制

使用缓存机制可以减少数据重复请求,加速数据的获取。

  • 使用 wx.setStorageSync 和 wx.getStorageSync:在获取数据后将其存储到本地,以后请求前先检查本地是否已有缓存。
const fetchData = async () => {
  const cachedData = wx.getStorageSync('myData');
  if (cachedData) {
    return cachedData; // 使用缓存
  }

  const response = await wx.request({/*...*/});
  wx.setStorageSync('myData', response.data);
  return response.data;
};

2. 限制请求数量

避免在短时间内发送过多请求,可以合并请求或使用防抖和节流技术。

  • 防抖

    let debounceTimer;
    function debounce(func, delay) {
      return function (...args) {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => func.apply(this, args), delay);
      };
    }
    
    // 使用示例
    const fetchDataDebounced = debounce(fetchData, 300);
    
  • 节流

    function throttle(func, limit) {
      let lastFunc;
      let lastRan;
      return function () {
        const context = this;
        const args = arguments;
        if (!lastRan) {
          func.apply(context, args);
          lastRan = Date.now();
        } else {
          clearTimeout(lastFunc);
          lastFunc = setTimeout(() => {
            if (Date.now() - lastRan >= limit) {
              func.apply(context, args);
              lastRan = Date.now();
            }
          }, limit - (Date.now() - lastRan));
        }
      };
    }
    

3. 分批加载:避免一次性加载大量数据

当需要加载大量数据时,可以采用分批加载的方式,每次只加载一部分数据,待这部分数据处理完毕后再加载下一批。

// 示例:分批加载数据
function fetchBatchData(page) {
  wx.request({
    url: `https://api.wwww.com/data?page=${page}`,
    success: function(res) {
      const newData = res.data;
      // 处理数据
      this.setData({
        items: this.data.items.concat(newData)
      });
    }
  });
}

fetchBatchData(1);

4. 智能请求:根据网络状况调整请求策略

根据用户的网络环境动态调整请求策略,可以进一步提高数据加载的速度和成功率。

// 示例:根据网络状况调整请求策略
wx.getNetworkType({
  success: function(res) {
    const networkType = res.networkType;
    if (networkType === '2g') {
      // 在2G网络环境下减少请求次数
      fetchBatchData(1, 5); // 一次性请求5页数据
    } else {
      // 其他网络环境下正常请求
      fetchBatchData(1);
    }
  }
});

三、优化页面渲染性能

页面渲染效率直接影响用户体验,优化渲染性能是非常必要的。

1. 启动速度优化 

  • 减少全局数据初始化
  • 使用分包加载,将不常用页面分割到子包中

2. 使用 wx:if 和 wx:for

适当使用 wx:if 和 wx:for(使用wx:key优化列表渲染) 避免过多的视图层重绘。尽量使用 wx:show 替代 wx:if,因为 wx:if 会在条件变化时销毁和重新创建节点。

3. 合理使用数据绑定

在数据大规模更新时,避免一次性改变全部数据,使用 this.setData() 时要尽量精简,减少触发视图的重复渲染。

this.setData({
  'todos[0].completed': true // 只更新部分数据
});

4. 使用组件化

将页面拆分成多个小组件,每个组件负责各自的状态和渲染,这样可以有效地减少失去控制的渲染过程,增加性能。同时也提高了代码的可维护性。

5. 避免长任务

对长时间运行的任务进行拆分,避免在主线程中阻塞 UI 更新。可以使用 Promise 和 setTimeout 进行分步执行,确保 UI 不被冻结。

6. 内存管理

  • 监听页面生命周期,及时释放不再使用的资源
  • 使用WeakRef避免循环引用问题
onUnload() {
  // 清理定时器、监听器等
  this.timer && clearInterval(this.timer);
}

7. 削减冗余:识别与移除无用代码

删除冗余代码就像是给程序减肥,让它变得更加苗条。那些不再使用的函数、未引用的变量或者废弃的样式都应该被清理掉,这样才能保证小程序运行得更快。

// 示例:删除未使用的变量
let unusedVar = 'I will be removed'; // 不再使用此变量

function cleanUpCode() {
  // 删除未使用的变量
  delete unusedVar; // 实际开发中应使用工具或手动检查
}

cleanUpCode();

8. 异步处理:合理使用异步任务不阻塞主线程

合理使用异步任务可以避免阻塞主线程,从而提高程序的执行效率。

// 示例:使用Promise异步加载数据
function fetchDataAsync() {
  return new Promise((resolve, reject) => {
    wx.request({
      url: 'https://api.wwww.com/data',
      success: resolve,
      fail: reject
    });
  });
}

fetchDataAsync().then(res => {
  this.setData({
    items: res.data
  });
});

9. 动画优化:流畅过渡增强交互感

通过优化动画效果,可以使用户界面更加流畅,增强用户的交互体验。

// 示例:优化动画效果
Page({
  data: {
    animate: false
  },
  startAnimation: function() {
    this.setData({
      animate: true
    });
    setTimeout(() => {
      this.setData({
        animate: false
      });
    }, 1000);
  }
});

四、减少小程序的启动时间

1. 初始页面优化

在小程序启动时载入的页面要尽量简化,减少初始页面的内容,延迟加载不必要的内容。

2. 使用 wx.navigateTo 与 wx.redirectTo

合理使用页面跳转方式,避免使用 wx.redirectTo 后缀跳转过多的页面,而导致栈溢出,减慢响应速度。

五、工具与监控

1. 性能监控工具

使用微信开发者工具中的性能分析工具来监控小程序的性能,查看每个调用的时间,找出性能瓶颈。

2. 代码性能分析

使用一些 JavaScript 的代码静态分析工具(如 ESLint, Prettier)来确保代码的高效性,及时优化掉低效代码。

六、优化微信小程序超包问题

1. 分包

分包部分规则
1、子包最多100个
2、tabBar页面只能在主包中
3、子包内不能再分包
4、子包内的资源不能互相引用(可使用分包异步化解决),但可使用主包内的资源
5、整个小程序所有分包大小不超过 20M,单个分包/主包大小不能超过 2M
小程序开发者工具的代码依赖分析可以查看包体积情况

分包规则

// 在小程序启动时,默认会下载主包并启动主包内页面,当用户进入分包内某个页面时,会把对应分包自动下载下来,下载完成后再进行展示,此时终端界面会有等待提示。
{
	// pages 主包(默认启动页面及 TabBar 页面)
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			// 页面上访问路径 /pages/index/index
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "首页",
				// custom即取消默认的原生导航栏
				"navigationStyle": "custom",
				"navigationBarTextStyle": "white"
				// "enablePullDownRefresh":false, //是否允许底部下拉刷新,可在页面配合 onPullDownRefresh生命周期一起使用
			}
		},
		{
			"path": "pages/my/my",
			"style": {
				"navigationBarTitleText": "我的",
				"navigationStyle": "custom",
				"navigationBarTextStyle": "white"
			}
		},
		{
			"path": "pages/cart/cart",
			"style": {
				"navigationBarTitleText": "购物车"
			}
		},
		
		{
			"path": "pages/404/404",
			"style": {
				"navigationBarTitleText": "页面未找到",
				"enablePullDownRefresh": false
			}
		}
	],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	// 组件自动引入规则
	// easycom方式引入组件不是全局引入,而是局部引入。例如在H5端只有加载相应页面才会加载使用的组件
	"easycom": {
		// 是否开启自动扫描
		"autoscan": true,
		"custom": {
			// uni-ui 规则如下配置  uni扩展组件
			"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue",
			//以 Xtx 开头的组件,匹配components目录内的vue文件(需要重启服务器)
			"^Xtx(.*)": "@/components/Xtx$1.vue"
			// 匹配node_modules内的vue文件,如匹配 uview-ui 包的组件
			// "^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
		}
	},
	// 底部
	"tabBar": {
		"color": "#333",
		"selectedColor": "#27ba9b",
		"backgroundColor": "#fff",
		"borderStyle": "white",
		"list": [{
				"text": "首页",
				// pagePath要与上面的pages一致
				"pagePath": "pages/index/index",
				"iconPath": "static/tabs/home_default.png",
				"selectedIconPath": "static/tabs/home_selected.png"
			},
			{
				"text": "购物车",
				"pagePath": "pages/cart/cart",
				"iconPath": "static/tabs/cart_default.png",
				"selectedIconPath": "static/tabs/cart_selected.png"
			},
			{
				"text": "我的",
				"pagePath": "pages/my/my",
				"iconPath": "static/tabs/user_default.png",
				"selectedIconPath": "static/tabs/user_selected.png"
			}
			// {
			// 	"text": "SKU",
			// 	"pagePath": "pages/sku/sku"
			// }
		]
	},
	// 分包页面(需手动创建subPackages文件夹),按需加载
	"subPackages": [
		{
			// 子包的根目录
			"root": "pagesMember",
			// 页面路径和窗口表现,和上面 pages 一样
			// 访问的完整路径   如:/pagesMember/settings/settings
			"pages": [{
					"path": "settings/settings",
					"style": {
						"navigationBarTitleText": "设置"
					}
				},
				{
					"path": "profile/profile",
					"style": {
						"navigationBarTitleText": "个人信息",
						// 取消默认的导航栏
						"navigationStyle": "custom",
						"navigationBarTextStyle": "white"
					}
				},
				{
					"path": "address/address",
					"style": {
						"navigationBarTitleText": "地址管理"
					}
				},
				{
					"path": "address-form/address-form",
					"style": {
						"navigationBarTitleText": "新建地址"
					}
				}
			]
		},
		{
			"root": "pagesOrder",
			"pages": [{
					"path": "create/create",
					"style": {
						"navigationBarTitleText": "结算"
					}
				},
				{
					"path": "detail/detail",
					"style": {
						"navigationBarTitleText": "订单详情",
						"navigationStyle": "custom"
					}
				},
				{
					"path": "payment/payment",
					"style": {
						"navigationBarTitleText": "支付结果"
					}
				},
				{
					"path": "list/list",
					"style": {
						"navigationBarTitleText": "订单列表"
					}
				}
			]
		}
	],
	// 预下载分包,分包预下载规则
	"preloadRule": {
		// 进入 我的 页面,预下载分包
		"pages/my/my": {
			"network": "all",
			// 分包 root的值
			"packages": [
				"pagesMember"
			]
		},
		"pages/cart/cart": {
			"network": "all",
			"packages": [
				"pagesOrder"
			]
		}
	},
	"condition": { //模式配置,仅开发期间生效
		"current": 0, //当前激活的模式(list 的索引项)
		"list": [{
			"name": "", //模式名称
			"path": "", //启动页面,必选
			"query": "" //启动参数,在页面的onLoad函数里面得到
		}]
	}
}

2. 如果分包后主包还是超了可以把图片放在云服务上,把主包文件夹中一些大的js或者json等的文件移到子包中

3. 在hbuilderx中的运行 -> 运行到小程序模拟器 -> 运行时是否压缩代码,勾选

4. 微信小程序模拟器中的本地设置把压缩的都勾选

七、分包异步化

分包异步化原理

原有的分包隔离机制导致各分包之间无法引用自定义组件或逻辑代码,分包异步化能力打通了不同分包的引用关系,支持跨分包组件和跨分包方法。

背景与案例

我们一般使用小程序插件的时候,喜欢将其放在分包中,因为插件体积会打包进主包内,很容易造成主包体积超过 2M 从而无法发布,我们暂且叫这个有插件的分包叫分包P,这时候另外两个业务分包XY,想引入这个分包P里的插件(插件里包含了几个组件和一些接口函数)。

方案一:因为分包里本身就是可以引入插件的,所以想直接在分包XY里面分别引入插件,但是同一个插件是不能在一个项目里多次引用的,所以这个方案不行;
方案二:把插件放在主包里,这样虽然可以实现,但是插件大小会打包进主包,容易超过 2M 无法发布;
方案三:分包异步化,将插件/逻辑代码(抽成一个模块)单独放在一个分包P下,分包XY通过分包异步化来引入

"subpackages": [
	{
	  "root": "pagesPlugin1",
	  'pages': [
	    'page-index/index'
	  ],
	  "plugins": {
	    "assist-photo": {
	      "version": "3.2.1",
	      "provider": "wxcf13b931313209a4"
	    }
	  }
	},
	{
	  "root": "pagesPlugin2",
	  'pages': [
	    'page-index/index'
	  ]
	}
]

这是分包2的代码:

<style lang="less">
</style>

<template>
  <div>这是pagesPlugin2</div>
  <chose-part></chose-part>
</template>

<script>
import wepy from '@wepy/core'
wepy.page({
  data: {
  },
  onShow() {
  }
})
</script>
<config>
{
  "usingComponents": {
    "chose-part": "../../pagesPlugin1/components/chose-part/index",
  },
  "componentPlaceholder": {
    "chose-part": "view"
  }
}
</config>

这个时候,打开分包2的页面就可以看到这个组件了

跨分包 JS 代码引用

分包2想调用分包1的接口,这里在分包1先导出一些函数
pagesPlugin1/utils/index.js

export const sayHello = () => {
  console.log('hello')
}

pagesPlugin2/page-index/index  在分包2调用

import wepy from '@wepy/core'
wepy.page({
  data: {
  },
  methods: {
    getPagesPlugin1 () {
      require.async('../../pagesPlugin1/utils/index.js').then(pkg => {
        console.log('utils', pkg)
        pkg.sayHello()
      }).catch(({mod, errMsg}) => {
        console.error(`path: ${mod}, ${errMsg}`)
      })
    }
  },
  onShow() {
    this.getPagesPlugin1()
  }
})

注意:如果是使用 wepy 这样的框架,则需要在分包的页面中引入一下这些接口函数,否则最终打包不会打包这个接口函数,因为识别不出这些依赖 

跨分包方法

在小程序开发过程中,可以通过require回调函数或requireAsync异步调用两种方法,引用其他分包的逻辑代码。具体操作如下:

// 使用回调函数风格的调用
require('../subPackageB/utils.js', utils => {
  console.log(utils.whoami) // Wechat MiniProgram
}, ({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
require.async('../commonPackage/index.js').then(pkg => {
  pkg.getPackageName() // 'common'
}).catch(({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})

在其它分包中的插件也可以通过类似的方法调用:

// 使用回调函数风格的调用
requirePlugin('live-player-plugin', livePlayer => {
  console.log(livePlayer.getPluginVersion())
}, ({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})
// 或者使用 Promise 风格的调用
requirePlugin.async('live-player-plugin').then(livePlayer => {
  console.log(livePlayer.getPluginVersion())
}).catch(({mod, errMsg}) => {
  console.error(`path: ${mod}, ${errMsg}`)
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/944223.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【星海随笔】删除ceph

cephadm shell ceph osd set noout ceph osd set norecover ceph osd set norebalance ceph osd set nobackfill ceph osd set nodown ceph osd set pause参考文献&#xff1a; https://blog.csdn.net/lyf0327/article/details/90294011 systemctl stop ceph-osd.targetyum re…

Unity游戏环境交互系统

概述 交互功能使用同一个按钮或按钮列表&#xff0c;在不同情况下显示不同的内容&#xff0c;按下执行不同的操作。 按选项个数分类 环境交互系统可分为两种&#xff0c;单选项交互&#xff0c;一般使用射线检测&#xff1b;多选项交互&#xff0c;一般使用范围检测。第一人…

DVWA安装

这里讲的很清楚&#xff0c;如果是win10的话可能会出现端口80占用的情况&#xff0c; 使用管理员身份运行 cmdnet stop http //停止系统http服务sc config http start disabled //禁用服务的自动启动&#xff0c;此处注意等号后面的空格不可少

Oracle考试多少分算通过?

OCP和OCM认证的考试及格分数并不是固定的&#xff0c;而是根据考试的难度和考生的整体表现来确定。对于OCP认证&#xff0c;考生需要全面掌握考试要求的知识和技能&#xff0c;并在考试中表现出色才有可能通过。而对于OCM认证&#xff0c;考生则需要在每个模块中都达到一定的水…

18_HTML5 Web IndexedDB 数据库 --[HTML5 API 学习之旅]

HTML5 Web IndexedDB API 是一种在用户浏览器中存储大量结构化数据的机制&#xff0c;它允许存储和检索键值对&#xff0c;其中键可以是任何有效的JavaScript对象。IndexedDB 主要用于需要复杂查询的数据密集型Web应用。 IndexedDB 的特点&#xff1a; HTML5 Web IndexedDB A…

【Seata】分布式事务问题和理论基础

目录 1.分布式事务问题 1.1本地事务 1.2分布式事务 2.理论基础 2.1CAP定理 2.1.1一致性 2.1.2可用性 2.1.3分区容错 2.1.4矛盾 2.2BASE理论 2.3解决分布式事务的思路 1.分布式事务问题 1.1本地事务 本地事务&#xff0c;也就是传统的单机事务。在传统数据库事务中…

【数据库初阶】Linux中库的基础操作

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; 数据库初阶 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 Linux…

数据结构与算法Python版 图

文章目录 一、图二、抽象数据类型图三、图的实现-邻接列表法 一、图 表示图的英文单词 painting&#xff1a;用画刷画的油画drawing&#xff1a;用硬笔画的素描/线条画picture&#xff1a;真实形象所反映的画&#xff0c;如照片等&#xff0c;如take pictureimage&#xff1a…

Word表格另起一页解决办法

Word表格另起一页解决办法 表格设置根据内容自动调整&#xff0c;取消指定高度第1步 第2步

Python数据可视化案例——折线图

目录 json介绍&#xff1a; Pyecharts介绍 安装pyecharts包? 构建一个基础的折线图 配置全局配置项 综合案例&#xff1a; 使用工具对数据进行查看?&#xff1a; 数据处理 json介绍&#xff1a; json是一种轻量级的数据交互格式&#xff0c;采用完全独立于编程语言的…

【Seata】seata的部署和集成

一、部署Seata的tc-server 1.下载 首先我们要下载seata-server包&#xff0c;地址在http://seata.io/zh-cn/blog/download.html 当然&#xff0c;课前资料也准备好了&#xff1a; 2.解压 在非中文目录解压缩这个zip包&#xff0c;其目录结构如下&#xff1a; 3.修改配置 修…

链表 之 无头结点【哨兵位】单向非循环链表【单链表】增删改查 等方法

系列文章目录 &#x1f388; &#x1f388; 我的CSDN主页:OTWOL的主页&#xff0c;欢迎&#xff01;&#xff01;&#xff01;&#x1f44b;&#x1f3fc;&#x1f44b;&#x1f3fc; &#x1f389;&#x1f389;我的C语言初阶合集&#xff1a;C语言初阶合集&#xff0c;希望能…

GCP Cloud Architect exam - PASS

备考指南 推荐视频课程 https://www.udemy.com/course/google-cloud-architect-certifications/?couponCodeKEEPLEARNING 推荐题库 https://www.udemy.com/course/gcp-professional-cloud-architect-exam-practice-tests-2024​/?couponCodeKEEPLEARNING 错题集 http…

CCF-GESP 等级考试 2023年12月认证C++二级真题解析

2023年12月真题 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 正确答案&#xff1a;C 考察知识点&#xff1a;变量的定义与使用 解析&#xff1a;变量命名规则&#xff1a;1、只能包括数字、字母和下划线&#xff1b;2、不能以数字开头&#xff1b;3、不能和…

5.学习webpack配置 babel基本配置

babel是一个javascript编译工具&#xff0c;其主要功能是将新版本的JavaScript代码&#xff08;如es6&#xff09;转换为旧版本的代码&#xff08;如es5&#xff09;&#xff0c;以便能够在旧版本的浏览器或环境中运行。一般配合webpack使用。 使用npm i -D babel/core babel/p…

配置搜索无人机

升级ubuntu内核 https://www.bilibili.com/video/BV11X4y1h7qN/?spm_id_from333.337.search-card.all.click 进入四个内核文件并安装 sudo dpkg -i *.deb安装ROS&#xff0c;PX4&#xff0c;XTDrone&#xff0c;QGC https://blog.csdn.net/qq_45493236/article/details/13…

Linux内核蓝牙子系统有什么(9)

接前一篇文章&#xff1a;Linux内核蓝牙子系统有什么&#xff08;8&#xff09; 本文内容参考&#xff1a; Linux之蓝牙相关代码浅析 | DDNotes 蓝牙驱动相关代码_蓝牙驱动代码-CSDN博客 linux蓝牙驱动代码阅读笔记_bt-sco.c-CSDN博客 Linux内核的蓝牙子系统架构-CSDN博客 …

22. 仿LISP运算

题目描述 LISP语言唯一的语法就是括号要配对 形如(OP P1 P2 ...)&#xff0c;括号内元素由单个空格分割。其中第一个元素OP为操作符&#xff0c;后续元素均为其参数&#xff0c;参数个数取决于操作符类型。注意:参数P1,P2也有可能是另外一个嵌套的(OP P1 P2...)&#xff0c;当前…

Axure10

如果还是不行就将字体图标安装在控制面板–字体下 打开原型了之后&#xff0c;icon没有 一定要将字体库放到–》控制面板\外观和个性化\字体 里面

王佩丰24节Excel学习笔记——第十九讲:Indirect函数

【以 Excel2010 系列学习&#xff0c;用 Office LTSC 专业增强版 2021 实践】 【本章技巧】 如果indirect引用出错&#xff0c;首先检查一下引用位置的双引号有没有出错&#xff0c;再检查引用值的位置是否出错&#xff0c;如果是双引号出错&#xff0c;可以使用英文状态下输入…