我配了台电脑,主板是华硕z790,cpu是i9 13900k,显卡是 nvidia 4090。 底层系统我打算装esxi8,过程中遇到很多坑,在这里记录一下。
首先是esxi8不支持intel 13代cpu的大小核心。需要在启动esxi安装程序的时候按shift+o,添加参数:cpuUniformityHardCheckPanic=FALSE
然后又遇到问题是esxi不认识板载网卡(Realtek RTL8125 2.5GbE)。解决办法是买一张intel i226的pcie网卡。(点这里可以查看esxi8的硬件支持情况)
然后就能顺利安装esxi8了。 然后在esxi里面安装ubuntu22, 遇到了4090显卡无法直通的问题。 试了很多办法都不行。 后来我又装了一个windows 11虚拟机, 尝试把网卡直通给win11。 最后通过调整bios的显卡设置(本来是auto, 改成pcie才可以),成功把4090显卡直通给了win11。
最后又通过一些尝试才成功把显卡直通给ubuntu22。以下是一些关键步骤:
- 首先在esxi后台的 主机->管理->硬件->PCI设备 里面,找到显卡设备选中,然后点击切换直通来打开直通开关。
-
ubuntu虚拟机设置里面,添加高级参数:
hypervisor.cpuid.v0=FALSE
pciPassthru.use64bitMMIO=TRUE
pciPassthru.64bitMMIOSizeGB=64 -
ubuntu虚拟机预留全部内存 -
/etc/modprobe.d/blacklist-nvidia-nouveau.conf 文件添加:
blacklist nouveau
options nouveau modeset=0
-
/etc/modprobe.d/nvidia.conf 文件添加:
options nvidia NVreg_OpenRmEnableUnsupportedGpus=1
-
sudo update-initramfs -u
-
下载对应的nvidia驱动
-
sudo chmod u+x NVIDIA-Linux-x86_64-525.89.02.run
-
sudo apt install build-essential
-
sudo apt install pkg-config libglvnd-dev
-
sudo ./NVIDIA-Linux-x86_64-525.89.02.run -m=kernel-open -
然后运行nvidia-smi就能看到显卡信息了
一些参考资料:
-
Nvidia-smi "No devices were found" - VMWare ESXI Ubuntu Server 20.04.03 with RTX3070 - Graphics / Linux / Linux - NVIDIA Developer Forums -
VMware ESXi DirectPath I/O 直通GPU卡给虚拟机使用 – 丁辉博客 (dinghui.org)
完。
在iOS系统里面,任意webview在可滚动状态下,都是可以拖超出边界然后反弹回来的。这个效果非常的好看和实用。但是如果我要做一个web app,我就不希望我的整个app界面也被用户拖动。
在很久以前,iOS的浏览器是不支持overflow scroll的,也就是说除了整个网页可以滚动以外,其他部分是不能局部滚动的。要实现局部滚动,一般都是用iScroll等插件,用javascript来模拟滚动。这技术说起来容易做起来难,我看了无数个类似的东西,没有任何人能做到原生一样的滚动反弹效果。最接近原生效果的是我从某牛逼网站上8下来的代码:https://github.com/longbill/ScrollPane
后来iOS退出了iOS5,其中的浏览器支持了overflow scroll。在配合 -webkit-overflow-scrolling: touch; 的情况下滚动起来是比较理想的。但是唯一有一个弊端就是当局部滚动区域处于滚动边缘的时候(比如处于最上面),此时继续网下滚动手指,滚动操作不会体现在局部滚动区域,而是会作用于整个网页。这个在做web app的时候,是完全无法忍受的。做出来的效果跟把web app界面的头部和底部用position fixed固定是一样的。
所以,即使overflow scroll从iOS5起就被支持,但是用javascript模拟滚动的需求还是十分旺盛。其中很重要的一点就是滚动会传递到外面的网页。另外也很重要的一点就是原生的滚动很难实现类似pull to refresh的操作。
后来我打算将我的精选文章做成web app的形式。尝试了无数的scroll插件,都让人失望。被逼无奈仔细研究了一下原生的overflow scroll。再后来被我找到了一个奇怪的方法,来阻止滚动操作传递到整个网页。
就是。
在手指放在屏幕上的时候,判断里面的滚动部分的 scrollTop 是不是 0 或者 最底下。如果是,那么将 scrollTop 轻轻位移1个像素。就可以了。
另外,我还实现了一个pull to refresh,虽然效果跟原生的不太一样,但是看起来也还不错。
代码我空了会整理写文档然后放到github上。大家可以先看这个 demo。 暂时只支持iOS系统。安卓请忽略。
http://jszen.com/public/demo/ptr/index.html
完。
当我们设计一个带有用户注册/登录功能的网站的时候,一个必须的功能就是重设密码。 重设密码功能有很多种设计方式,比如发送一个新密码到用户邮箱等。不过今天我要介绍一个我经常用实现方式。
用户流程:
- 用户忘记密码,来到密码重设界面
- 用户输入Email地址,点击重设密码按钮
- 用户收到一封密码重设邮件,里面有重设密码的链接,此链接有过期时间
- 用户点击链接,来到密码重设页面,输入新密码,完成
这个流程并没有什么创新,很多网站都是用这套流程
后端实现方式:
- 当用户输入Email地址后,验证这个Email,如果存在于数据库,那么取得用户的user_id
- 将user_id和当前时间戳编码成HASH,需要提前准备好一个KEY,并且这个KEY只存在服务器上。 HASH = md5 ( user_id + timestamp + KEY )
- 生成一个URL,并且附带刚刚生成的HASH和用户id以及timestamp,比如 http://domain.com/reset-password.php?hash=HASH&user_id=123×tamp=1392121211
- 当用户访问这个URL, 检查HASH是否合法: HASH == MD5 ( user_id + timestamp + KEY)
- 检查 timestamp 是不是过期了
- 如果所有检查通过,那么显示一个新密码表单给用户
这种方式的好处:
- 不需要额外的数据表
- 不用担心参数被用户恶意修改,因为要检查hash是不是等于那几个参数的md5
- 密码重设URL自带时间戳
- 只要KEY设置的足够长足够复杂,那么可以认为HASH是绝对安全的
更详细的样例代码可以参考这里:http://jszen.com/reset-password-system.6.html
完。
某些时候,我们需要用户输入一个日期范围,比较直观的想法是用两个date picker控件。但是两个date picker给用户带来的体验并不好。于是我搞了个jQuery插件,可以实现在一个界面里面选择日期范围,并且将选择的值输出到一个input框中。
- 依赖 jQuery 1.3+, Moment 2.0.0+
- 支持 IE6+, Firefox, Chrome, Safari 等浏览器
- 支持多语言
- 界面完全CSS可控

文档以及代码见我的英文博客:http://jszen.com/jquery-date-range-picker-plugin.4.html
下载:https://github.com/longbill/jquery-date-range-picker
完。
记得很久很久以前,主流还是IE6。开发前端页面的时候,修改一行CSS或者JS,就要回到浏览器刷新看下效果。调试Javascript更是只能用alert来判断是哪行代码出问题了。那个时候,Javascript还有个竞争对手叫VBScript,声明script标签的时候还建议声明language="javascript"。那个时候网页脚本还被认为是仅仅能给网页增加一些跑马灯等的特效而存在的。
那都是05年的事了。现在前端的各种环境各种工具都迈入了一个崭新的时代。感谢Google推动了浏览器的发展,感谢W3C制定各种有用没用的标准,鄙视微软万恶的IE6。现在我们开发前端页面已经逐渐变得优雅/文艺了起来。这让我这个经历过当年艰苦岁月的前端er不禁感叹终于熬出头了。。。
这里我像各位同学介绍下我长期使用的各种前端开发工具,主要是提升效率。欢迎补充留言。
Chrome developer tools
不知道什么时候,Chrome developer tools强大到超过了Firebug,成为了我主要的debug工具。查看浏览器发起的所有请求、查看页面引用的js/css代码、查看/修改页面DOM结构、在页面上修改css/js然后直接看到效果、Javascript Console等等各种基本功能都做到非常好用。强烈建议各位找找深入介绍Chrome developer tools的文章,相信有很多高级的功能很多同学都还没用过。
Sublime Text 2
这是一个文本编辑器。也是不知道什么时候就强大到超过Textmate,成为我主要的编辑器。更重要的是,它居然是跨平台的。用Windows的同学有福了。
Zen Coding
这是一个编辑器插件,支持各种编辑器。这里有篇介绍文章。这个插件的牛逼之处在于可以大大提高写HTML的效率。比如我要写一个html table。输入 table#list-table.table>tr.row*3>td.cell*3 然后按定义的Zen Cod ing快捷键,就会马上生成:
<table id="list-table" class="table"> <tr class="row"> <td class="cell"></td> <td class="cell"></td> <td class="cell"></td> </tr> <tr class="row"> <td class="cell"></td> <td class="cell"></td> <td class="cell"></td> </tr> <tr class="row"> <td class="cell"></td> <td class="cell"></td> <td class="cell"></td> </tr> </table>
Twitter Bootstrap
这是twitter发布的一套前端整体框架。也就是预先定义了很多css和一些Js代码。写页面的时候,按照规范写class,就可以实现用户体验很好的页面。这里是项目主页。现在很多很多网站都基于bootstrap来开发。的确可以为开发者节省很多宝贵的时间,更重要的是,这些页面元素都是twitter经过研究后,觉得是用户体验最好的设计。而且,基于bootstrap,页面还可以很轻松的做到mobile friendly。我的一个小项目就是基于bootstrap,实现了使用同一个页面,支持各种尺寸的浏览器。尤其在iOS浏览器上表现非常好。精选文章
Devtools Autosave
这才是最牛逼的神器。项目地址在这里。这个东西实现了可以在Chrome developer tools里面修改css属性或者js代码,然后直接同步保存到本地或者服务器。比如以前我们先大概写好css,然后用firebug进行微调,调整好后,复制css代码,进入编辑器粘贴代码然后保存,然后刷新浏览器看效果。而现在,在Chrome devtools里面,修改的css可以自动保存了。而且不仅仅是css属性,还可以直接修改css源文件、javascript源文件。现在的开发方式可以简化到,先写好HTML骨架,定义好各个class名字,然后打开chrome devtools,在css源文件里面直接添加新的class。边写边可以看到效果哦。牛逼指数10颗星啊。
Markman
马克鳗是一个Design to HTML神器。很多时候我们需要根据设计图片文件来开发成网页代码。这时需要精确测量各种距离、各种宽度、各种颜色。马克鳗可以优雅的完成这个任务。项目地址在这里。下面是我截的图:

先写这么多吧。
完。
用Titanium做iOS的APP挺简单的。完全不需要Object-C的知识,看官方的API文档基本就可以了。我最近做了个应用准备发布。不过遇到了个问题,就是app name不能设置成中文。 想了下,貌似App Name也有语言问题,不同语言环境下应该显示不同的名字才对。 后来网上找了一大圈,终于搞定。 下面是步骤:
环境: Titanium Studio, build: 1.0.9, Titanium Mobile SDK 2.0.1 , Mac OS Snow Leopard
- 首先在你的项目根目录下新建一个文件夹,i18n,这个是国际化文件夹,下面应该放各种语言的语言文件
- i18n下面新建en文件夹用于英文,zh_CN文件夹用于中文,ja 日文 ...
- 在每个语言文件夹下面新建app.xml文件
-
app.xml文件里面写:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="appname">APP NAME</string>
</resources> - 不同语言文件夹下的app.xml写不同的APP NAME就可以了。
- 如果没效果可以试试先clean再run
搞定。
另外,推荐一个可以下载免费icon素材的网站,http://www.softicons.com/ 里面好多开源免费的icon!!
完。
JQuery支持事件绑定,触发等操作。不仅仅对DOM元素有效,对普通的函数或者对象一样可以。比如
var a = {};
$(a).bind('msg',function(){ alert(1); });
$(a).trigger('msg');
我刚做了个函数,可以为自己写的普通函数增加类似上面这种事件监听、绑定功能。并且支持跟JQuery一样的事件命名空间。例如:
function ClasssA() {} //某个函数
EventMachine.call(ClassA); //为此函数的prototype增加几个方法(bind,unbind,trigger,unbindAll),此函数源代码见后面的链接
var a = new ClassA(); //实例化ClassA
a.bind('msg',callback1); //click的时候执行callback1
a.bind('msg.a',callback2); //click的时候执行callback2
a.bind('msg.b',callback3); //click的时候执行callback3
a.bind('logout.a',callback4); //mouseover的时候执行callback4
a.unbind('msg'); //干掉 callback1,2,3
a.unbind('msg.a'); //干掉 callback2
a.unbind('.a'); //干掉callback2,4
a.unbind('msg',callback2); //干掉callback2
a.unbind('.b'); //干掉callback3
a.unbindAll(); //干掉所有
a.trigger('msg','abc'); //触发callback1,2,3 并传递'abc'参数
源代码及demo看这里。
因为目前采用的方案是往this的prototype上写方法,所以暂时只支持函数。 不过可以经过很简单的修改来支持普通的对象(貌似没什么必要。。。)
因为没有用到任何平台相关的东西,所以EventMachine函数可以运行在几乎所有支持Javascript的地方。比如NodeJS, Web, Titanium等
完。
因为我学习Javascript的过程比较零散,没有仔细系统的看过。有些细节方面就被遗漏了。下面是我最近才搞清楚的几个函数。如果你此前就知道,那么恭喜你,你的JS比我好。如果也不清楚,那么也恭喜你,你看了此文就清楚了。
1. Array 的 slice方法
slice(start,end) 此方法可从已有的数组中返回位于start和end之间的元素。并且不改变数组本身。start和end参数可以为负数,表示从后面开始数的第几个。
例如: [1,2,3,4].slice(2,3) 返回[3] , [1,2,3,4].slice(2,-1) 也返回[3] 。
另外,如果只写一个参数,那么第二个参数默认是数组的长度。也就是说 [1,2,3,4].slice(-2) 返回 [3,4]
2. Array 的 splice 方法
splice(start,length) 此方法返回现有数组的从start开始的length个元素。并且会改变数组本身。start参数可以为负数。
例如: var a = [1,2,3,4]; a.splice(2,2) 返回[3,4] ,并且a变成了[1,2]
另外,splice还支持第3,4,5...个参数,表示用后面的参数替换掉被删除的元素。
3. String 的 substr 方法
substr(start,length) 此方法返回字符串从start开始的length个字符。不改变字符串本身。start参数可以为负数。
例如: "abcd".substr(2,1) 返回 'c',"abcd".substr(-2) 返回 "cd"
4. String 的 substring 方法
substring(start,end) 此方法返回字符串的start到end之间的字符。不改变字符串本身。start和end参数不能为负数!但是start可以比end小。
例如:"abcd",substring(1,3) 和 "abcd".substring(3,1) 都返回 "bc"
表格对比
| 参数 | 参数是否支持负数 | 是否改变对象本身 | |
|---|---|---|---|
| Array.slice | (start,end) | Yes | No |
| Array.splice | (start,length) | Yes | Yes |
| String.substr | (start,length) | Yes | No |
| String.substring | (start,end) | No | No |
此外,删除对象的某个属性用delete 操作符。
例如: var o = {"a":1,"b":2}; delete o.a; 那么o就变成 {"b":2}
但是如果要删除数组的某个元素,就要用上面提到的splice方法了。
例如: var a = [1,2,3,4]; delete a[1]; 那么a就变成[1,undefined,3,4],并且a.length还是4。 必须要用a.splice(1,1)。
还有Array.pop, Array.shift, Array.push, Array.unshift等常用方法就不说了。
完。

