using System.Runtime.InteropServices;
/// <summary>
/// Windows 资源管理器的文件名排序规则(允许在非 Windows 平台使用)
/// <para>调用 Windows API(StrCmpLogicalW 函数)实现,仅在 Windows 平台环境中使用</para>
/// <para>基本规则如下:</para>
/// <para>将文件名中的数字作为数值来处理。</para>
/// <para>不区分大小写。</para>
/// <para>字符类型的大致优先级顺序为:特殊符号 → 数字 → 字母。</para>
/// <para>对于中文文件名,排序方式取决于系统的区域设置:拼音(默认)、笔画。</para>
/// </summary>
public class FileLogicalComparer : IComparer<string>
{
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
private static extern int StrCmpLogicalW(string psz1, string psz2);
private static readonly bool IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public int Compare(string? x, string? y)
{
// 处理 null 值情况
if (x == null && y == null) return 0;
if (x == null) return -1;
if (y == null) return 1;
try
{
if (IsWindows)
{
// Windows 平台:使用原生 API
return StrCmpLogicalW(x, y);
}
else
{
// 非 Windows 平台:使用 C# 实现的回退方案
return NaturalCompareFallback(x, y);
}
}
catch (Exception) // 捕获 DllNotFound、EntryPointNotFoundException 等异常
{
// 异常时使用默认的字符串比较器
return string.Compare(x, y, StringComparison.Ordinal);
}
}
/// <summary>
/// C# 实现的自然排序回退方案(代码来自 AI,未测试!)
/// </summary>
private static int NaturalCompareFallback(string x, string y)
{
if (x == y) return 0;
int i = 0, j = 0;
while (i < x.Length && j < y.Length)
{
if (char.IsDigit(x[i]) && char.IsDigit(y[j]))
{
// 提取连续数字并进行数值比较
string num1 = ExtractNumber(x, ref i);
string num2 = ExtractNumber(y, ref j);
if (long.TryParse(num1, out long n1) && long.TryParse(num2, out long n2))
{
if (n1 != n2)
return n1.CompareTo(n2);
}
else
{
// 解析失败时按字符串比较
int strCompare = string.Compare(num1, num2, StringComparison.Ordinal);
if (strCompare != 0)
return strCompare;
}
}
else
{
// 非数字字符直接比较
if (x[i] != y[j])
return x[i].CompareTo(y[j]);
i++;
j++;
}
}
return x.Length.CompareTo(y.Length);
}
/// <summary>
/// 从字符串中提取连续的数字序列
/// </summary>
private static string ExtractNumber(string str, ref int index)
{
int start = index;
while (index < str.Length && char.IsDigit(str[index]))
{
index++;
}
return str.Substring(start, index - start);
}
}

打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Version>
1.0.$([System.Math]::Floor($([System.DateTime]::Now.Subtract($([System.DateTime]::Parse('2000-01-01T00:00:00Z'))).TotalDays))).$([MSBuild]::Divide($([System.Math]::Floor($([System.DateTime]::Now.TimeOfDay.TotalSeconds))), 2))
</Version>
最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version!; // 当前类库
var version = Assembly.GetEntryAssembly()?.GetName().Version!; // 入口项目
从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);

在解决方案资源管理器中找到 Properties/AssemblyInfo.cs 文件。该文件存放程序集版本信息。
修改版本号格式
将以下代码片段中的 AssemblyVersion 改为使用星号通配符(建议保留主版本和次版本号):
[assembly: AssemblyVersion("1.0.*")] // 自动生成构建号和修订号 // [assembly: AssemblyFileVersion("1.0.0.0")] // 注释或删除此行
关闭确定性构建
用文本编辑器打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Deterministic>false</Deterministic>
此设置允许 MSBuild 生成动态版本号。
最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version;
从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);
查看 .NET Core / .NET 5+ 实现自动版本号的方法

原生判断
window.addEventListener('scroll', scroll)
function scroll() {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const clientHeight = document.documentElement.clientHeight || document.body.clientHeight;
const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;
if (scrollTop === 0) {
console.log('滚动到顶了');
}
if (scrollTop + clientHeight >= scrollHeight - 100) {
console.log('滚动到底了');
}
}
window.removeEventListener('scroll', scroll) // 移除滚动事件
scrollTop:文档在可视区上沿的位置距离文档顶部的距离
clientHeight:可视区的高度
scrollHeight:文档总高度
100:用于在滚动到底部之前提前加载内容(如瀑布流),提高用户体验,请自行修改数值(建议不小于 2 像素,以规避在部分浏览器上因获得值为小数时可能无法触发的问题)
jQuery 判断
window.addEventListener('scroll', scroll)
function scroll() {
const doc_height = $(document).height();
const scroll_top = $(document).scrollTop();
const window_height = $(window).height();
if (scroll_top === 0) {
console.log('滚动到顶了');
} else if (scroll_top + window_height >= doc_height - 100) {
console.log('滚动到底了');
}
}

功能 | 主动推送方式 | 主动拉取方式 |
接口规范 | 由数据终端提供接口,数据源端调用接口推送数据 | 由数据源端提供接口,数据终端调用接口拉取数据 |
定时器 | 由推送方(数据源端)实现 | 由拉取方(数据终端)实现 |
缓存 | 在不影响正常运行的情况下,数据源端可不做缓存,实时获取并推送数据,消耗资源过大时做缓存 | 数据源端需要做缓存,以避免终端频繁拉取。若因参数值过多而致缓存过大时,应按调用方标识限制接口调用频次 |
截断标志 | 数据源端记录最后一次推送的数据ID,并在下一次推送时判断此标识往后推送数据 | 数据终端记录最后一次拉取的数据ID,并在下次一拉取时传递给数据源端 |
日志与故障排查 | 双方都需要保留日志 | 双方都需要保留日志 |
在有一个数据源端和多个数据终端的系统中 | 优点:无 缺点:数据源端需要依据不同的数据终端提供的接口规范推送数据,若这些数据终端要求的推送间隔时间不致,则会使用定时器和缓存实现更为复杂 | 优点:所有终端使用统一的接口规范,数据拉取间隔时间由终端自由决定 缺点:无 |
在有多个数据源端和一个数据终端的系统中 | 优点:所有数据源端使用统一的接口规范,数据推送间隔时间由数据源端自由决定 缺点:无 | 优点:无 缺点:数据终端需要依据不同的数据源端提供的接口规范拉取数据 |

POST
axios.post('AjaxCases', {
following: true,
success: null,
page: 1,
}).then(function (response) {
console.log(response.data)
}).catch(function (error) {
console.log(error.response.data);
});
[HttpPost]
public IActionResult AjaxCases([FromBody] AjaxCasesRequestModel req)
{
bool? following = req.following;
bool? success = req.success;
int page = req.page;
}
GET
axios.get('AjaxCase', {
params: {
int: 123,
}
}).then(function (response) {
console.log(response.data)
}).catch(function (error) {
console.log(error.response.data);
});
[HttpGet]
public IActionResult AjaxCases([FromQuery] int id)
{
}
DELETE
格式与 GET 类似
* 若服务端获取参数值为 null,可能的情况如下:
请检查相关枚举类型是否已设置 [JsonConverter] 属性,参:C# 枚举(enum)用法笔记,且传入的值不能为空字符串,可以传入 null 值,并将服务端 enum 类型改为可空。可以以 string 方式接收参数后再进行转换。
模型中属性名称不能重复(大小写不同也不行)。
布尔型属性值必须传递布尔型值,即在 JS 中,字符串 "true" 应 JSON.parse("true") 为 true 后再回传给服务端,vue 绑定方式参此文。

使用 JS 根据屏幕宽度来计算页面尺寸和字体大小并不是一个好办法。
rem 单位是跟随网页根元素的 font-size 改变而自动改变的,是一个相对的长度单位,非常适合在不同手机界面上自适应屏幕大小。
一般的手机浏览器的默认字体大小为 16px。即:
:root { font-size: 16px; } /* 在 HTML 网页中,:root 选择器相当于 html */
也就是说,如果我定义一个宽度为 1rem,那么它的实际宽度为 16px。反过来说,如果设计稿宽度为 1000px,那么相当于 1000÷16=62.5rem。因此,我们设置一个 62.5rem 的宽度,即可正常显示 1000px 的设计效果。
为了适应不同屏幕尺寸的手机,只需按比例换算更改 :root 的 font-size 即可。这个比例是由“窗口宽度 ÷ 设计稿宽度”得到的,姑且称它为“窗设比”。
以 iPhone X 逻辑宽度 375px 为例,设计稿宽度 1000px 时,窗设比为:0.375。:root 的 font-size 将会被重置为 16 * 0.375 = 6px。上面的 62.5rem 宽度将对应 iPhone X 宽度为 62.5 * 6 = 375px,正好是屏幕逻辑宽度。
根据这个思路,理论上,我们只需要使用 CSS 将 :root 的 font-size 设置为 1px,然后使用 JS 重置为与“窗设比”相乘的积(本例中将被重置为 0.375px)。这样,我们可以不通过换算,只需要更改单位,将设计稿中的 500px 直接写入到 CSS 为 500rem,即可实现在 iPhone X 上显示逻辑宽度为(500 * 0.375 =)187.5px,即设计稿中的 1/2 宽度对应到屏幕上 1/2 的宽度。
实际上,部分安卓手机(如华为某旗舰机)不支持 :root 的 font-size 小于 12px,其它一些浏览器也会出现小于 12px 的文字以 12px 显示。
为了避免在任何环节出现小于 12px 的 font-size 值,且不增加设计稿尺寸到 CSS 数值的换算难度,我们设计了以下思路:
约定“设样比(设计稿的 px 值与 CSS 的 rem 值的比)”为 100;
使用 JS 将 :root 的 font-size 重置为“设样比”与“窗设比(窗口宽度 ÷ 设计稿宽度)”的乘积;
计算 CSS 时的 rem 值只需从设计稿中获取 px 值再除以“设样比”100 即可。
这样做的另一个好处是,不用要求设计师必须按多少尺寸来设计,当然按主流尺寸来建议是可行的。
完整代码(jQuery 版):
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app { margin: 0 auto; background-color: #EEE; display: none; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
// [函数] 重置尺寸
function fn_resize() {
// 设计稿宽度(px)
var designsWidth = 1000;
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
var px2rem = 100;
// 限制 #app 的最大宽度为设计稿宽度
$('#app').css('max-width', designsWidth).css('min-height', $(window).height());
// 重置 :root 的 font-size
var appWidth = Math.min($(window).width(), designsWidth);
$(':root').css('font-size', px2rem * appWidth / designsWidth);
$('#app').show();
}
// 页面加载完成后重置尺寸
$(fn_resize);
// 改变窗口大小时重置尺寸
$(window).resize(fn_resize);
</script>
</body>
</html>
完整代码(Vue2 版):
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app { margin: 0 auto; background-color: #EEE; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app" v-bind:style="{ maxWidth: designsWidth + 'px', minHeight: appMinHeight + 'px' }" style="display: none;" v-show="appShow">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
<div>appWidth: {{ appWidth }}</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
var app = new Vue({
el: '#app',
data: {
// 设计稿宽度(px)
designsWidth: 1000,
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
px2rem: 100,
// #app 的 width
appWidth: 0, // 勿改
appMinHeight: 0, // 勿改
appShow: false, // 勿改
},
mounted: function () {
// 页面加载完成后重置尺寸
this.fn_resize();
const that = this;
// 改变窗口大小时重置尺寸
window.onresize = () => {
return (() => {
console.log('RUN window.onresize()');
that.fn_resize();
})();
};
},
watch: {
// 侦听 appWidth 更改 root 的 font-size
appWidth: function () {
console.log('RUN watch: appWidth');
var root = document.getElementsByTagName("html")[0];
root.style.fontSize = (this.px2rem * this.appWidth / this.designsWidth) + 'px';
this.appShow = true;
}
},
methods: {
fn_resize: function () {
console.log('RUN methods: fn_resize()');
this.appWidth = Math.min(document.body.clientWidth, this.designsWidth);
this.appMinHeight = document.documentElement.clientHeight;
}
}
});
</script>
</body>
</html>
完整代码(Vue3 版):
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0" />
<title>Index</title>
<style>
body { margin: 0; text-align: center; }
#app > div { display: none; margin: 0 auto; background-color: #EEE; }
/* 长度计算方法:从设计稿获得长度(例如 160px),除以 px2rem 值(本例为 100),得到 1.6rem */
.whole { background-color: #D84C40; width: 10rem; }
.half { background-color: #3296FA; width: 5rem; }
.half2 { background-color: #3296FA; width: 5rem; margin-left: 5rem; }
</style>
</head>
<body>
<div id="app">
<div style="display: none;" v-bind:style="{ maxWidth: designsWidth + 'px', minHeight: appMinHeight + 'px', display: appShow ? 'block' : 'none' }">
<div class="whole">100%</div>
<div class="half">50%</div>
<div class="half2">50%</div>
<div>appWidth: {{ appWidth }}</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@3"></script>
<script>
const app = Vue.createApp({
data: function () {
return {
// 设计稿宽度(px)
designsWidth: 1000,
// 约定的“设计稿 px 值与 CSS rem 值的比”,为方便计算,一般无需改动
px2rem: 100,
// #app 的 width
appWidth: 0, // 勿改
appMinHeight: 0, // 勿改
appShow: false, // 勿改
}
},
mounted: function () {
// 页面加载完成后重置尺寸
this.fn_resize();
const that = this;
// 改变窗口大小时重置尺寸
window.onresize = () => {
return (() => {
console.log('RUN window.onresize()');
that.fn_resize();
})();
};
},
watch: {
// 侦听 appWidth 更改 root 的 font-size
appWidth: function () {
console.log('RUN watch: appWidth');
var root = document.getElementsByTagName("html")[0];
root.style.fontSize = (this.px2rem * this.appWidth / this.designsWidth) + 'px';
this.appShow = true;
}
},
methods: {
fn_resize: function () {
console.log('RUN methods: fn_resize()');
this.appWidth = Math.min(document.body.clientWidth, this.designsWidth);
this.appMinHeight = document.documentElement.clientHeight;
}
}
});
const vm = app.mount('#app');
</script>
</body>
</html>
示例中 CSS 初始 :root 的 font-size 为 16px(一个较小值,防止页面加载时瞬间出现大号文字影响用户体验),经过 fn_resize 后,:root 的 font-size 被设置为(100 * 375 / 1000 =)37.5px(iPhone X 中),那么宽度为 1000px 的设计稿中的 500px 换算到 CSS 中为 5rem,也即 37.5 * 5 = 187.5px,就是 iPhone X 的屏幕宽度的一半。
示例中 id 为 app 的 div 是用来在 PC 浏览器中限制页面内容最大宽度的(类似微信公众号发布的文章),如果网页不需要在 PC 端显示,jQuery 版代码中的 $('#app').width() 可以用 $(window).width() 来代替。
这个 div#app 一般设计有背景色,用于在宽度超过设计稿的设备上显示时区别于 body 的背景。但是当网页内容不超过一屏时,div#app 高度小于窗口,示例中与 appMinHeight 相关的代码就是为了解决这个问题。
示例中 div#app 隐藏/显示相关代码用于解决在页面加载初期由于 font-size 值变化引起的一闪而过的排版错乱。
最后补充一点,如果改变窗口大小时涉及执行耗时的操作,为避免页面卡顿,可以参考这篇文章添加函数防抖:https://xoyozo.net/Blog/Details/js-function-anti-shake

本文介绍 ASP.NET 的 Swagger 部署,若您使用 ASP.NET Core 应用程序,请移步 ASP.NET Core Web API Swagger 官方文档:
https://github.com/domaindrivendev/Swashbuckle.AspNetCore
安装
NuGet 中搜索安装 Swashbuckle,作者 Richard Morris
访问
http://您的域名/swagger
配置
显示描述
以将描述文件(xml)存放到项目的 bin 目录为例:
打开项目属性,切换到“生成”选项卡
在“配置”下拉框选择“所有配置”
更改“输出路径”为:bin\
勾选“XML 文档文件”:bin\******.xml,(默认以程序集名称命名)
打开文件:App_Start/SwaggerConfig.cs
取消注释:c.IncludeXmlComments(GetXmlCommentsPath());
添加方法:
public static string GetXmlCommentsPath() { return System.IO.Path.Combine( System.AppDomain.CurrentDomain.BaseDirectory, "bin", string.Format("{0}.xml", typeof(SwaggerConfig).Assembly.GetName().Name)); }
其中 Combine 方法的第 2 个参数是项目中存放 xml 描述文件的位置,第 3 个参数即以程序集名称作为文件名,与项目属性中配置一致。
如遇到以下错误,请检查第 2、3、4 步骤中的配置(Debug / Release)
500 : {"Message":"An error has occurred."} /swagger/docs/v1
使枚举类型按实际文本作为参数值(而非转成索引数字)
打开文件:App_Start/SwaggerConfig.cs
取消注释:c.DescribeAllEnumsAsStrings();

这是一个数据可视化项目,基于D3.js。能够将历史数据排名转化为动态柱状图图表。
先来看看效果:
https://xoyozo.net/Demo/BarGraph
作者 Jannchie 见齐还提供了官方视频教程:
https://www.bilibili.com/video/av28087807
不过由于开源项目的不断更新,该教程的部分内容已失效,本文针对 2018-12-25 版本总结了一些常用的配置说明,仅供参考。
从 GitHub 下载源代码,在 src 目录中可以看到 4 个文件:
bargraph.html --> 运行示例页面
config.js --> 配置文件
stylesheet.css --> 样式表
visual.js --> 核心文件
作者并没有将代码封装为插件的方式,所以我们是通过修改 config.js 配置文件的方式应用到自己的项目中的。
visual.js 虽然是核心文件,但作者将部分示例中的代码也包含其中,但并不影响我们直接在自己的项目中引用。
以下是 config.js 中的主要属性:
属性 | 说明 | 参考值 |
encoding | 数据源(csv、json)等的文件编码 | GBK / UTF-8 等 |
max_number | 每个时间节点最多显示的条目数 | 10 |
showMessage | 控制是否显示顶部附加信息文字 | true / false |
auto_sort | 时间自动排序(详细含义、作用及限制见代码中注释) | true / false |
timeFormat | 时间格式,显示于图表右下角的时间 | %Y、%Y-%M-%D 等 |
reverse | 是否倒序 | true / false |
divide_by | 类型根据什么字段区分?如果是 name,则关闭类型显示 | |
divide_color_by | 颜色根据什么字段区分? 须要注意的是,如果配置成 name,则各条颜色不同(因为 name 值各异),如果配置成 type 等,那么相同 type 值的条颜色相同。 | 字段名 |
color | 指定部分或所有条的颜色,该项与 divide_color_by 设置有关。 | 以 divide_color_by = 'name' 为例,"中国"是其中的一项 name 值,那么该项将显示 #D62728 色: color: { '中国': '#D62728' } |
changeable_color | 若 true 则颜色的深浅将根据数据的增长率实时改变 | |
itemLabel | 左边文字 | |
typeLabel | 右边文字 | |
item_x | ||
interval_time | 时间点间隔时间 | 2 |
text_y | ||
text_x | ||
offset | ||
display_barInfo | 如果希望不显示,则可以设置较大的值,单位像素 | |
use_counter | ||
step | ||
format | 格式化数值 | |
left_margin | ||
right_margin | ||
top_margin | ||
bottom_margin | ||
dateLabel_x | ||
dateLabel_y | ||
allow_up | ||
enter_from_0 | ||
big_value | ||
use_semilogarithmic_coordinate | ||
long | ||
wait | 数据加载完成后开始播放前的等待时间 | 0 |
update_rate |

本文不定时更新中……
收集了一些在开发过程中遇到的一些问题的解决方法,适合新手。
异常:
出现脚本错误或者未正确调用 Page()
原因:不小心删了第一行内容:<template>
异常:
模块编译失败:TypeError: Cannot read property 'for' of undefined
at fixDefaultIterator (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4277:24)
at mark (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4306:5)
at markComponent (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4371:5)
at baseCompile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4384:15)
at compile (D:\HBuilderX\plugins\uniapp\lib\mpvue-template-compiler\build.js:4089:28)
at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\mpvue-loader\lib\template-compiler\index.js:43:18)
原因:新建的页面(简单模板)只有以下 3 个标签,须在 <template /> 中添加一些代码,如 <view />
<template>
</template>
<script>
</script>
<style>
</style>
异常:
模块编译失败:TypeError: Cannot read property 'toString' of undefined
at Object.preprocess (D:\HBuilderX\plugins\uniapp\lib\preprocess\lib\preprocess.js:56:15)
at Object.module.exports (D:\HBuilderX\plugins\uniapp\lib\preprocessor-loader.js:9:25)
原因:没有原因,纯抽风,HX 关掉再开就好了。
异常:
Cannot set property 'xxx' of undefined;at pages/... onLoad function;at api request success callback function
原因:属性未定义,例如
data() {
return {
item: { }
}
}
而直接赋值 this.item.abc.xxx = '123';
解决:
data() {
return {
item: {
abc: ''
}
}
}
问:page 页面怎样修改 tabBar?
答:官方文档未给出答案,百度了一圈也无果(2018-10-23),但有人说小程序的 setTabBarBadge() 方法设置角标是可以用的。
坑:
VM1694:1 获取 wx.getUserInfo 接口后续将不再出现授权弹窗,请注意升级
参考文档: https://developers.weixin.qq.com/community/develop/doc/0000a26e1aca6012e896a517556c01
填坑:放弃使用 uni.getUserInfo 接口来获取用户信息,uni.login 可返回用于换取 openid / unionid 的 code,参:uni.login、 code2Session
坑:字符搜索(当前目录)(Ctrl+Alt+F)搜不出所有结果
填坑:顾名思义他只搜索当前目录,即当前打开文件所在目录,而非我误认为的整个项目根目录。在“项目管理器”中选中要搜索字符的目录即可。
坑:uni.navigateTo() 或 uni.redirectTo() 没反应
填坑:这两个方法不允许跳转到 tabbar 页面,用 uni.switchTab() 代替。
坑:使用“Ctrl+/”快捷键弹出“QQ五笔小字典”窗口
解决:打开QQ五笔“属性设置”,切换到“快捷键设置”选项卡,把“五笔小字典”前的勾取消(即使该组合键是设置为Ctrl+?)。
坑:<rich-text /> 中的 <img /> 太大,超出屏幕宽度
填坑:用正则表达式给 <img /> 加上最大宽度
data.data.Content = data.data.Content.replace(/\<img/gi, '<img style="max-width:100%;height:auto" ');
坑:无法重命名或删除目录或文件
填坑一:“以管理员身份运行”HBuilder X 后再试。
填坑二:关闭微信开发者工具、各种手机和模拟器后再试。
填坑三:打开“任务管理器”,结束所有“node.exe”进程后再试。
坑:
thirdScriptError
sdk uncaught third Error
(intermediate value).$mount is not a function
TypeError: (intermediate value).$mount is not a function
Page[pages/xxxx/xxxx] not found. May be caused by: 1. Forgot to add page route in app.json. 2. Invoking Page() in async task.
Page is not constructed because it is not found.
填坑:关闭微信开发者工具、各种手机和模拟器后,删除“unpackage”目录。
坑:
Unexpected end of JSON input;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected end of JSON input
填坑:给 uni.navigateTo() 的 url 传参时,如果简单地将对象序列化 JSON.stringify(item),那么如果内容中包含“=”等 url 特殊字符,就会发生在接收页面 onLoad() 中无法获取到完整的 json 对象,发生异常。
uni.navigateTo({
url: "../news/view?item=" + JSON.stringify(item)
})
所以应该把参数值编码:
uni.navigateTo({
url: "../news/view?item=" + escape(JSON.stringify(item))
})
如果是一般的 web 服务器来接收,那么会自动对参数进行解码,但 uni-app 不会,如果直接使用:
onLoad(e) {
this.item = JSON.parse(e.item);
}
会发生异常:
Unexpected token % in JSON at position 0;at "pages/news/view" page lifeCycleMethod onLoad function
SyntaxError: Unexpected token % in JSON at position 0
需要解码一次:
onLoad(e) {
this.item = JSON.parse(unescape(e.item));
}
需要注意的是,unescape(undefined) 会变成 'undefined',如果要判断是否 undefined,应是 unescape 之前。
坑:图片变形
填坑:mode="widthFix"
坑:页面如何向 tabBar 传参
填坑:全局或缓存
坑:编译为 H5 后,出现:Access-Control-Allow-Origin
填坑:参阅
坑:编译为 H5 后,GET 请求的 URL 中出现“?&”
填坑 :客户端只求 DCloud 官方能够尽快修复这个 bug,IIS 端可以暂时用 URL 重写来防止报 400 错误,参此文。
坑:[system] errorHandler TypeError: Cannot read property 'forEach' of undefined
填坑:待填
