首页
Search
1
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
46 阅读
2
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
38 阅读
3
如何在 IOS Shadowrocket 上配置服务
34 阅读
4
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
34 阅读
5
如何在 Clash for Windows 上配置服务
30 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
635
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
232
篇与
的结果
2024-09-10
Qt Quick 笔记 - Anchors
看到许多 Qt Quick 样例中都会用到 Anchors,在官网这里找到了资料。还有这里也有详细的说明。除了Grid, Row, and Column,Anchors 也可以用来布局。注意只能对兄弟或父母 item 使用 anchorsAnchors 是 Item 中的属性,所以大多数类型都可以使用 Anchors。一图胜千言:![edges_qml][edges_qml]简单的例子:// ... Rectangle { id: rect1 //... } Rectangle { id: rect2 anchors.left: rect1.right //... } //...布局就会是这样子:![edge1][edge1]换一下//... Rectangle { id: rect1 //... } Rectangle { id: rect2 anchors.left: rect1.right anchors.top: rect1.bottom //... } //...布局就会是这样子![edge3][edge3]anchors.baseline 是一条假想的线,代表文本的位置。对于无文本的 item 它跟 top 一致。还有一些比较方便的属性anchors.fill: something 就是去填满 something,即 left,right,top, bottom 值都相等。anchors.centerIn: something 就是中心与 something 相等,即 verticalCenter, horizontalCenter 值相等。anchors.margins: 实数 以像素为单位设置间距,再次一图胜千言:![margins_qml][margins_qml]例子//... Rectangle { id: rect1 //... } Rectangle { id: rect2 anchors.left: rect1.right anchors.leftMargin: 5 //... } //...![edge2][edge2]注意 margins 是按 anchors 来设置间距,假如没有设置 anchor,margins 就会失效。此时可以用偏移值来设置间距,共三种: anchors.horizontalCenterOffset : 实数 anchors.verticalCenterOffset : 实数 anchors.baselineOffset : 实数 使用 AnchorChanges 去处理状态State { name: "anchorRight" AnchorChanges { target: rect2 anchors.right: parent.right anchors.left: undefined //remove the left anchor } }使用 AnchorAnimation 激活 AnchorChanges: Transition { AnchorAnimation {} //animates any AnchorChanges in the corresponding state change }![anchor_ordering][anchor_ordering]可以直接用 JavaScript 代替,但是要小心使用,会有很多坑 //会出问题 Rectangle { width: 50 anchors.left: parent.left function reanchorToRight() { anchors.right = parent.right anchors.left = undefined } }会变成这样:![anchor_ordering_bad][anchor_ordering_bad]要先释放不需要的属性再去更新其它属性Rectangle { width: 50 anchors.left: parent.left function reanchorToRight() { anchors.left = undefined anchors.right = parent.right } }还有这种代码//bad code Rectangle { width: 50; height: 50 anchors.left: state == "right" ? undefined : parent.left; anchors.right: state == "right" ? parent.right : undefined; }不推荐这么写,因为在 AnchorChanges 内部就会自动处理了。最后说明,不要跟绝对坐标混用,要用绝对坐标时先把冲突的 anchor 设置为 undefined [edges_qml]: /img/post/qt-quick-anchors/edgesqml.jpg [edge1]: /img/post/qt-quick-anchors/edge1.jpg [edge3]: /img/post/qt-quick-anchors/edge3.jpg [marginsqml]: /img/post/qt-quick-anchors/marginsqml.jpg [edge2]: /img/post/qt-quick-anchors/edge2.jpg [anchorordering]: /img/post/qt-quick-anchors/anchorordering.jpg [anchororderingbad]: /img/post/qt-quick-anchors/anchorordering_bad.jpg
2024年09月10日
2 阅读
0 评论
0 点赞
2024-09-10
使用 Express 与 AbsurdJS 构建 Node.js 应用
原文:Node.js application made with Express and AbsurdJS(2014-7-7)当今有许多新技术吸引着越来越多的开发者,Node.js 便是其中之一。主要因为它是 JavaScript 驱动的,许多人都很感兴趣。在本教程中,我将会教你结合 Express 去使用 AbsurdJS。Express 是流行的 Node.js 框架,而 AbsurdJS 则比较新鲜,希望你看完后会发现它很有用。本文中出现的源码都可以从这里下载。简介正如我提到的,Express 很流行。因为它是最早的 Node.js 框架之一。它把所有琐碎的事情都包办了,比如路由选择、参数解析、模板、向浏览器发送响应。它的库基于 Connect 提供的中间件架构对原生的 Node.js 进行了较好的封装。AbsurdJS 一开始是一个 CSS 预处理器。目的是为 CSS 开发者带来更好的灵活性。它接受纯 JavaScript 代码并转换为 CSS。大家对它的反馈都比较积极,我也在努力继续完善它。现在它不仅能预处理 CSS,还可以处理 HTML。它接受 JSON 和 YAML 并成功导出作客户端使用。步骤为了使最后做出的项目能跑起来,我们需要安装 Node.js。只需打开 http://nodejs.org 并点击大大的绿色“INSTALL”按钮。下载并安装完成后你就可以调用 Node.js 脚本,用npm(Node 的包管理器)安装依赖包。为你的项目新建一个文件夹,里面再新建一个空的“package.json”文件。包管理器会以这个文件为起点去安装我们需要的包。我们只需两个包,所以 json 文件应该是这个样子:{ "name": "AbsurdJSAndExpress", "description": "AbsurdJS + Express app", "version": "0.0.1", "dependencies": { "express": "3.4.4", "absurd": "*" } }当然,这里还有许多其它的参数可以配置,但为了方便举例我们就先按上面的配置吧。打开终端,定位包含到 Package.json 的目录,执行:npm install会在当前目录生成 node_modules 文件夹,并自动下载 Express 和 AbsurdJS。运行服务器有了 Express 你只需要简单几行代码就可以运行一个 http 服务器。var express = require('express'), app = express(); app.listen(3303); console.log('Listening on port 3303');保存以上代码为 app.js 并运行:node app.js这时控制台应该显示 “Listening on port 3303”。浏览器打开 http://localhost:3303/ 会看到:Cannot GET /不用担心,这很正常,因为我们还没有添加路由。添加路由Express 提供了友好的 API 去定义 URL 路由。我们在这里简单地添加一个,把下面的代码贴到 app.js 中。app.get('/', function(req, res, next) { res.setHeader('Content-Type', 'text/html'); res.send("application"); });这里做了几件事。.get 方法的第一个参数定义了路径;第二个参数是个方法,用来处理请求,它接受三个参数 – request、response、next。这里的好处是我们可以传入多个函数,它们会一个接一个的被调用。我们需要做的只是执行 next(),否者 next 方法不会被调用。比如:app.get( '/', function(req, res, next) { console.log("do some other stuff here"); next(); }, function(req, res, next) { res.send("application"); } );路由定义中通用的做法是添加一些可重用的任务作为中间件。比如说,我们有两种 Content-Type, HTML 和 CSS。用下面的方法就显得更加灵活。var setContentType = function(type) { return function(req, res, next) { res.setHeader('Content-Type', 'text/' + type); next(); } } app.get('/', setContentType("html"), function(req, res, next) { res.send("application"); });如果我们需要提供 CSS,只要用 setContentType(“css”) 即可。提供 HTML很多 Express 的教程和文章都会介绍一些模板引擎。通常是 Jade、Hogan 或者 Mustache。然而,如果用 AbsurdJS 我们不需要模板引擎。我们可以用纯 JavaScript 编写 HTML。更具体的说,是用 JavaScript 对象。我们先从实现着陆页开始。新建文件夹 pages,在里面新建 landing.js 文件。我们在用 Node.js 所以文件里应该包含:module.exports = function(api) { // ... }注意返回的函数接受 AbsurdJS API 的引用。这正是我们所要的。现在再加点 HTML:module.exports = function(api) { api.add({ _:"", html: { head: { 'meta[http-equiv="Content-Type" content="text/html; "]': {}, 'link[rel="stylesheet" type="text/css" href="https://blog.crimx.com//2014/07/07/nodejs-application-made-with-express-and-absurdjs/styles.css"]': {} }, body: {} } }); }“_” 属性添加的字符串在编译成HTML时不会被转换;其它的属性各定义了一个标签。还可以用其它方法去定义标签属性,但我认为用上面的方式更好。这个想法是从 Sublime 的 Emmet 插件中获得的。编译完成后会生成: 本次教程只有一个页面,而在现实中你可能会在多个页面中使用相同的HTML。此时更合理的做法是将这部分代码移到外部的文件中,在需要的时候引用进来。当然,这里还可以使用可重复模板。创建文件 /pages/partials/layout.js :module.exports = function(title) { return { _:"", html: { head: { 'meta[http-equiv="Content-Type" content="text/html; charset=utf-8"]': {}, 'link[rel="stylesheet" type="text/css" href="https://blog.crimx.com//2014/07/07/nodejs-application-made-with-express-and-absurdjs/styles.css"]': {}, title: title }, body: {} } }; };这里其实就是一个返回对象的函数。所以,之前的 landing.js 可以修改为:module.exports = function(api) { var layout = require("./partials/layout.js")("Home page"); api.add(layout); }可以看到,layout 模板接受 title 变量。这样就可以动态地生成一部分内容。接下来是向 body 标签添加内容。非常简单,因为所有内容都是纯 JavaScript 对象。module.exports = function(api) { var layout = require("./partials/layout.js")("Home page"); layout.html.body = { h1: "Page content" } api.add(layout); }生成的结果: Home page Page content 本文的代码看起来都很短、不完整,是因为全写的话文章就太长了。接下来我只会介绍一下建立无序列表的思想,因为这里比较有意思。剩余的部分跟 layout 类似,就不再敖述。下面就是生成无序列表的片段。标签:module.exports = function(data) { var html = { ul: [] }; for(var i=0; item=data[i]; i++) { html.ul.push({ li: item }); } return html; }这里只用了一个 ul 属性定义一个对象。ul 其实就是一个数组,装满列表中的项。var list = require("./partials/list.js"); var link = require("./partials/link.js"); list([ link("http://krasimir.github.io/absurd", "Official library site"), link("https://github.com/krasimir/absurd", "Official repository") ]);link 也是片段,类似这样子:module.exports = function(href, label) { return { a: { _attrs: { href: href }, _: label } } }组合起来后就会生成: Official library site Official repository 现在,想象我们有一堆可以使用的片段。如果它们编写得足够灵活,只需创建一次就可以在项目之间传递了。AbsurdJS 是如此强大,只要我们拥有一堆足够好的预定义集合,就可以快速、更具描述性地编写 HTNL 标记。最后,当 HTML 已经完成后,我们只需编译并发送给用户。于是,对 app.js 做小小的变动使得我们的应用响应正确的标记:var absurd = require("absurd"); var homePage = function(req, res, next) { absurd().morph("html").import(__dirname + "/pages/landing.js").compile(function(err, html) { res.send(html); }); } app.get('/', setContentType("html"), homePage);提供 CSS与 HTML 类型,先在 app.js 为 style.css 添加路由。var styles = function(req, res, next) { absurd().import(__dirname + "/styles/styles.js").compile(function(err, css) { res.send(css); }); } app.get('/styles.css', setContentType("css"), styles);使用 JavaScript 定义 CSS。任何东西都可以放在分好的 Node.js 模块中。让我们创建 /styles/styles.js 并加入代码:module.exports = function(api) { api.add({ body: { width: "100%", height: "100%", margin: 0, padding: 0, fontSize: "16px", fontFamily: "Arial", lineHeight: "30px" } }) }一个简单的 样式控制。注意带有破折号的属性被改写成驼峰式大小写风格。否则不能创建有效对象,会得警告。现在假设要控制 和 标签的样式。它们都是标题,颜色和字体相同;但是大小不一样。通过下面的方法,AbsurdJS会智能地输出正确的样式。var title = function() { return { color: "#2C6125", fontWeight: "normal", fontSize: "40px", fontFamily: "Georgia", padding: "20px 10px" } } api.add({ h1: title(), h2: [ title(), { fontSize: "30px" } ] });输出结果:h1, h2 { color: #2C6125; font-weight: normal; font-family: Georgia; padding: 20px 10px; } h1 { font-size: 40px; } h2 { font-size: 30px; }预处理器会收集只定义了一次的相同样式,并为不同的样式创建新的定义。结论如果打算使用 Node.js,Express 会是最好的起点之一。它虽然不是超级强大,但依然很好用。它具备了开发 web 应用所需的基本要素。然后去扩展它,使用 AbsurdJS 会为开发带来不少趣味性,因为整个应用都是用纯 JavaScript 编写的。资源 Express 官网 – http://expressjs.com/ Express GitHub 仓库 - https://github.com/visionmedia/express AbsurdJS 官网与在线编译器 – http://absurdjs.com AbsurdJS GitHub 仓库 – https://github.com/krasimir/absurd
2024年09月10日
1 阅读
0 评论
0 点赞
2024-09-10
Google Chrome 霸权主义
原文:Google Chrome HegemonyGoogle Chrome 是当今互联网中最大的玩家之一。它快速、可靠、功能丰富;特别对 web 开发者来说非常好用。Chrome 也允许安装第三方扩展;Google 团队做得很不错,这些扩展只需 HTML、CSS 和 JavaScript 即可搭建。本文将介绍几个能帮助我们开发的 Chrome 利器。本文的源码在[这里]。开发响应式 Web 应用现在响应式无处不在。随着移动设备的崛起,我们需要让应用运行在各种不同分辨率的平台上。新版本的 Chrome 提供了很棒的工具来帮助我们减轻工作量。这里我们先做一个简单的页面然后让它变成响应式。先是HTML代码: Responsive Web Design About Concept Examples Frameworks Contacts Responsive web design (RWD) is a web design approach ... The fluid grid concept calls for page element sizing to be in relative units ... 还有一些简单的 CSS 样式,浮动导航链接并让两个章节(section)彼此相邻。效果如图:准备好 HTML 和 CSS 后,我们就可以开始做些试验了。先学习添加媒体查询(Media Queries)断点。重点是要根据内容选择媒体并观察内容在什么范围会变得难看。不要因为流行就仅仅设置 1024x768 之类的分辨率。设置视图(Viewport)我们希望了解在视图多大的时候内容会断层。此时需要调整浏览器的窗口大小。在 Chrome 里,可以使用开发者工具面板直接调整大小。注意当我们改变视图大小的时候,右上角会显示当前的大小。这个小小的提示框省去了手动检查的麻烦。在我们的例子中,导航栏下的两个章节在 500px 左右就会显得过扁了。所以这里我们放置第一个媒体查询:section { float: left; width: 50%; } @media all and (max-width: 550px) { section { float: none; width: 100%; } }如果在 550px 再低一点,我们会发现 540px 左右导航栏会让窗口产生水平滚动条。再添加一个媒体查询解决这个问题:.nav { list-style: none; margin: 10px auto; padding: 0; width: 510px; } .nav li { float: left; margin: 0 20px 0 0; } @media all and (max-width: 540px) { .nav { width: auto; } .nav li { float: none; margin: 0; padding: 0; text-align: center; } }这就是一个适应多种分辨率的网页。虽然我们的页面很简陋,只有两个断点,但即便对于庞大的网站,选择断点的方法也是一样的。设备模拟有时候我们会收到 bug 显示应用在一些特定的设备上出错。Chrome 可以模拟各种各样的设备帮助我们解决问题。它会自动设置正确的分辨率和 HTTP 头;让我们方便地接近真实用户的视角。检测设备的 JavaScript 代码也会正常工作因为 Chrome 改变了请求报头。比方说我们需要模拟一部 iPhone5 设备。在开发者工具面板的顶栏有一个小小的抽屉(drawer)按钮,然后选择模拟(Emulation)标签。我们只需选择设备,Chrome 会自动应用所有的设置包括屏幕、用户代理(User agent)以及传感器;甚至还模拟了触摸事件。在元素面板(Elements Panel)进行修改我们的页面已经是响应式了,但有时候我们需要再做些修改。可以使用 Chrome 查看 document 上应用的样式。比如,第一个章节的文字太大了,我们希望做些修改并改变字体的颜色。查看具体的 CSS 规则时元素面板也很有用,但在这里我们不知道这些规则是在哪里定义的。这时在右侧的窗口就可以查看当前元素上经过计算后的样式,我们可以在这里去做修改。开发者工具面板有时候我们需要搜索特定的 CSS 样式,但是这个样式有太多定义了找起来很麻烦。在开发者工具面板中有一个很好用的过滤区域。比方说我们想查看 标签中应用 concept 类的规则。只需这么做:JavaScript 调试Google Chrome 是一个通用的工具。它有上一节提到的工具来支援设计师,也同样有支持开发者的工具。集成 JS 调试Chrome 集成了优秀的 JavaScript 调试器、控制台和源码查看器。为了说明这些工具是怎么工作的,我们先为例子添加一小段逻辑代码。我们希望点击 Examples 链接后该标签会变成 Awesome examples。借助 jQuery 可以让我们更好地关注到例子上。$('.nav').on('click', function(e) { var clicked = e.currentTarget; if(clicked.innerHTML === 'Examples') { clicked.innerHTML = 'Awesome examples'; } else { console.log('do nothing ...'); } });你很可能已经看出问题了,但且让我们运行以上代码看看。无论我们点击什么都会控制台都会打印 do nothing...。看来我们的 if 语句总是 false。先设置一个断点看看发生了什么。调试器在断点暂停并显示当前的局部变量。可以看到,clicked 变量指向的是导航栏的元素而不是 元素。所以它的 innerHTML 属性一定不是 Exmaples。这就是每次都打印 do nothing... 的原因。要修复这个 bug,将 .nav 改成 .nav a 即可。以上是调试的传统方法,只有在我们知道哪里设断点的情况下才有用。但如果我们在大型的代码库上工作,特别是要调试一连串文件的时候,问题就来了。我们开始到处放置 console.log 然后观察控制台。这个办法是可行,但很快就会产生大量的数据,这时就很难从中过滤出需要的信息。Chrome 对这个问题也提供了解决方案。我们可以在传给 .log 的文本前添加 %c ,然后利用第二个参数调整控制台输出的样式。如图:我们还可以添加一些其它的东西。console 对象有两个不太常见的方法 —— group 和 groupEnd。可以用来为 log 分组。使用 Deb.jsDeb.js 库结合了样式控制和输出分组。只需要在添加 .deb() 到需要检查的函数末尾之前把 Deb.js 包含进来即可。使用 .debc() 可以在控制台显示折叠的输出组。有了这个库,我们可以知道传给该函数的参数,函数的堆栈跟踪返回值和执行时间。正如上文提到的,这些信息被很好地组织和嵌套在一起,可以更方便地跟踪应用流。浏览器终端Google 浏览器的一个杀手锏是它的扩展应用生态系统。它为我们提供了途径去编写可安装的程序在浏览器中运行并提供了丰富的 API 给我们使用。最重要的是,我们不必再去学习一门新语言。只需要普通的 HTML、CSS 和 JavaScript 即可。看看这里《Chrome 扩展开发入门》。Yez!在 Chrome 网上应用店(Web Store)中甚至有一个单独的区域叫 Web development,里面有许多专门为我们开发者制作的有用工具。其中有一个工具叫 Yez!。它为开发者工具面板提供了类似终端的功能。可以执行 shell 命令和实时获得输出。该应用本身不足以执行 shell 命令,因为它没有权限访问操作系统。所以这里需要 Node.js 作为代理。Yez! 通过 web sockets 连接正在运行的 Node.js 应用。通过 Node.js 包管理器安装 Yez!:npm install -g yezYez! 集成 GitYez! 很好的整合了 Git,它会显示当前目录的分支。我们可以执行终端命令并立即得到输出。这个扩展原本是作为一个任务运行器开发的。所以它提供了任务定义的接口。实际上,这不过是一系列按顺序执行的 shell 命令。我们可以通过 shell 脚本实现同样的效果。我们还可以实时查看终端的输出,所以这个扩展非常适合开发 Node.js 应用。通常我们需要重启 Node.js 程序,但在 Chrome 中一切都是可见的。执行 HTTP 请求作为 web 开发者,我们经常需要让我们的应用执行 HTTP 请求。也许我们开发了一个 REST API,或者有一个接受 POST 参数的 PHP 脚本。这里有一个命令行工具 cURL。它应该是最常用的 web 查询工具了。有了 cURL,我们不再需要转到终端去。这里可以用 DHC (REST HTTP API Client)。这个应用可以让我们完全控制 HTTP 请求。我们可以改变请求方式、报头、或者 GET 和 POST 参数。它还可以显示请求的结果,连同报头一起显示,非常实用。使用 Chrome Web 驱动进行测试我们都知道测试的重要性。清楚了解我们的程序运行正确对我们来说极为重要。有时候测试的编写会很困难,特别是当我们要测试用户界面。幸运的是,这里有一个 Node.js 模块可以控制我们的浏览器(Chrome)并触发动作比如访问页面、点击链接或者填写表格。它就是 DalekJS。安装很简单:npm install -g dalek-cli我们做个小试验看看它是怎么工作的。在一个新建的目录中,我们需要一个 package.json 文件包含如下内容:{ "name": "project", "description": "description", "version": "0.0.1", "devDependencies": { "dalekjs": "0.0.8", "dalek-browser-chrome": "0.0.10" } }接着在这个目录执行:npm install我们会在 node_modules 文件夹中看到有 dalekjs 和 dalek-browser-chrome。回到原来的目录,新建文件 test.js,我们会在这里中编写我们的测试。这是一个小脚本用来测试 GitHub 的搜索功能:var url = 'https://github.com/'; module.exports = { 'should perform search in GitHub': function (test) { test .open(url) .type('#js-command-bar-field', 'dalek') .submit('#top_search_form') .assert.text('.repolist h3 a', 'dalekjs/dalek', 'There is a link with label dalekjs') .click('[href="https://blog.crimx.com/dalekjs/dalek"]') .assert.text('.repository-description p', 'DalekJS Base framework', 'It is the right repository') .done() } };要运行测试,我们需要在控制台中发射:dalek ./test.js -b chromeDalekJS 会启动 Google Chrome 浏览器的一个实例,然后打开 GitHub 网站,你可以在搜索框中输入 dalek ,它会跳转到正确的仓库。最后,Node.js 会把打开的窗口关闭。控制台的输出看起来是这样的:DalekJS 支持 PhantomJS、Firefox、InternetExplorer 和 Safari。是个很有用的工具,在Windows、Linux 和 Mac 上都可以工作。在官网 dalekjs.com 上可以获得文档。总结我们在电脑前花最多时间的就是看浏览器了。很高兴知道 Google Chrome 不仅是浏览网页的程序,还是一个强大的 web 开发工具。如今,这里有着大量的实用扩展和持续增长的社区。如果你没有打算用 Google Chrome 开发你的下一个 web 应用,我强烈建议你去试一下。
2024年09月10日
2 阅读
0 评论
0 点赞
2024-09-10
阅读 jQuery 源码的18个惊喜
原文:18 Surprises From Reading jQuery's Source Code(2014-7-23)我热爱 jQuery,且尽管我认为自己算是一名高级 JavaScript 开发者,我从来没有试过由头到尾把 jQuery 的源码看一遍,直到现在。这里分享一些我一路下来学到的东西:注意:我使用 $.fn.method() 语法来表示调用一组匹配元素的方法。比如当我说 $.fn.addClass,则表示 $('div').addClass('blue') 或者 $('a.active').addClass('in-use') 此类的用法。$.fn 是 jQuery 包装元素的原型。 Sizzle 的权重:Sizzle 是 jQuery 用于在 DOM 找元素的的选择器引擎,基于 CSS 选择器。正是它将 $('div.active') 转换成可操作的元素数组。我知道 Sizzle 占了 jQuery 相当大的部分,但它的庞大还是吓到了我。按行数来说它很无疑是 jQuery 中唯一最庞大的特性。我估计它占了总代码库的 22%,而第二大的特性—— $.ajax 只占了 8%。 $.grep:这个方法与 Underscore 的 _.filter 类似。接受两个参数,一个元素数组和一个函数,对每个元素依次执行函数,返回执行结果为 true 的元素数组。 冒泡禁令:jQuery 明文禁止 load 事件冒泡。从内部看,jQuery 在所有的 load 事件中传入特殊的 noBubble: true 标记,所以 image.load 事件才不会冒泡到 window 上错误地触发 window.load 事件。 默认动画速度:jQuery 通过快速连续地改变样式属性来实现元素动画效果。每一次小改变被称作一个 tick。默认动画速度是每13毫秒运行一次 tick,要改变速度你可以重写 jQuery.fx.interval 成你想要的整数。 fn.addClass 可以接受函数:我们通常向 $.fn.addClass 提供一个包含类名的字符串来创建元素。但它也可以接受一个函数。这个函数必须返回一个字符串,多个类名间要以空格隔开。这里还有个彩蛋,这个函数接受已匹配元素的索引作为参数,你可以用这个特性来构造智能变化的类名。 fn.removeClass 也一样:与上文的一样,它也可以接受一个函数。这个函数也会自动接收元素的索引。 :empty 伪选择器:可以方便地用来匹配没有孩子的元素。 :lt 与 :gt 伪选择器:它们会根据元素在匹配集合中的索引来匹配元素。比如 $('div:gt(2)') 会返回所有的 div,除了前三个(从0开始)。如果你传入一个负数,它会倒过来从尾开始数。 $(document).ready() 的承诺: jQuery 貌似是用回了自己的东西。在内部,可信赖的 $(document).ready() 使用了一个 jQuery 延迟来确定 DOM 在什么时候完全加载。 $.type: 大家肯定能熟练使用 typeof 来确定数据类型,但你知不知道 jQuery 提供了一个 .type() 方法?jQuery 版比原生版更加智能。比如 typeof (new Number(3)) 返回 object,而 $.type(new Number(3)) 则返回 number。更新:正如 ShirtlessKirk 在评论中指出,$.type 返回其对象的 .valueOf() 属性。所以更准确的说法应该是 $.type 告诉你一个对象的返回值的类型。 $.fn.queue:你可以通过 $(‘div’).queue() 查看一个元素的效果队列,很方便地了解元素还剩余多少效果。更有用的是,你可以直接操作队列去添加效果。从 jQuery 文档摘录的: $( document.body ).click(function() { $( "div" ) .show( "slow" ) .animate({ left: "+=200" }, 2000 ) .queue(function() { $( this ).addClass( "newcolor" ).dequeue(); }) .animate({ left: "-=200" }, 500 ) .queue(function() { $( this ).removeClass( "newcolor" ).dequeue(); }) .slideUp(); }); 禁用元素不会触发 click 事件:jQuery 默认不会为禁用的元素执行 click 事件,有了这个优化,你无需自己用代码再检查一遍。 $.fn.on 可以接受对象:你知道 $.fn.on 可以接受一个对象来一次过连接多个事件吗?jQuery 文档的例子: $( "div.test" ).on({ click: function() { $( this ).toggleClass( "active" ); }, mouseenter: function() { $( this ).addClass( "inside" ); }, mouseleave: function() { $( this ).removeClass( "inside" ); } }); $.camelCase:这个有用的方法可以将连字符式的字符串转换成驼峰式的字符串。 $.active:调用 $.active 返回 XHR (XML Http Request) 查询的个数。利用它可以手动制定 AJAX 请求的并发上限。 $.fn.parentsUntil / $.fn.nextUntil / $.fn.prevUntil:我比较熟悉 .parents()、.next() 和 .prev(),却不知道原来还有其它的方法。它们会匹配所有的 双亲/下一个/前一个 元素直到(until)遇到符合终止条件的元素。 $.fn.clone 参数:当你用 .clone() 克隆一个元素,你可以用 true 作为第一个参数来克隆该元素的数据属性(data attributes)和事件。 更多的 $.fn.clone 参数:除了上面的方法外,你还可以再传多一个 true 参数来克隆该元素所有孩子的数据属性和事件。这叫做“深克隆”。第二个参数的默认值与第一个一样(第一个默认false)。所以当第一个参数是 true 而你想让第二个参数也是 true 时,完全可以忽略第二个参数。
2024年09月10日
2 阅读
0 评论
0 点赞
2024-09-10
JavaScript 创建对象总结
JavaScript 是一门灵活的语言,就创建对象而言就有各种各样的方法。本文是《JavaScript高级程序设计》(第3版)的笔记,主要是针对各种创建对象方法之间的关系、优缺点进行梳理。每种方法相关的其它细节不是本文重点,我会标记页码。创建单个对象1、object 构造函数:调用 Object 的构造函数。person 的 constructor 值是 Object。var person = new Object(); person.name = 'StrayBugs'; person.age = 22; person.job = 'student'; person.sayName = function() { alert(this.name); };2、字面量:不会调用 Object 的构造函数。而 person 的 constructor 值也是 Object。var person = { name: 'StrayBugs', age: 22, job: 'student', sayName: function() { alert(this.name); } }优点:简单、方便缺点:批量创建对象很麻烦。不能使用 instanceof 来确定对象类型(都是 Object)。工厂模式工厂模式是为了解决批量创建对象的问题。就是用一个函数将上述创建单个对象的方法包装起来,就可以减少代码量了。以第一种方法为例:function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var person1 = createPerson('StrayBugs', 22, 'student'); var person2 = createPerson('Angel', 20, 'Artist');优点:减少了代码量。缺点:未能解决对象识别的问题。构造函数模式构造函数模式解决了对象识别问题,是基于工厂模式的改进。是利用了 new 作用域转移的特性。function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); }; } var person1 = new Person('StrayBugs', 22, 'student'); var person2 = new Person('Angel', 20, 'Artist');必须用 new 操作符来创建 Person 实例。以这种方式调用构造函数实际上会经历以下4个步骤: 创建一个新对象; 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象); 执行构造函数中的代码(为这个新对象添加属性); 返回新对象。 此时 person1 与 person2 都可以用 constructor 和 instanceof 来验证其对象类型是 Person。当不使用 new 来创建对象时,由于在全局作用域中 this 指向 Global(浏览器中就是 window 对象),所以可以直接通过 window 对象调用 sayName,不建议这么做,会污染全局环境。也可以用 call() 与 apply() 来为 Person 指定作用域。优点:在工厂模式的基础上解决了对象识别问题。缺点:每个实例的方法都是独立的,多数情况下同个对象的实例方法都是一样的,于是这里造成了冗余。偏方:将函数定义单独出来,如下面例子:function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); }; var person1 = new Person('StrayBugs', 22, 'student'); var person2 = new Person('Angel', 20, 'Artist');这么写是不是很别扭,也没有封装性可言。原型模式原型模式很好解决了上面的封装性问题。原型也是 JavaScrip 最重要的特性之一。书本篇幅比较长,这里只为了突出原型要解决的问题,所以会省略很多。原型就是为了共用而生:默认情况下,每个对象与它的所有实例都共用一个原型。对象可以通过 .prototype 访问原型。实例存在内部属性 [[Prototype]],不能直接访问(不推荐使用 __proto__)。function Person() { } Person.prototype.name = 'StrayBugs'; Person.prototype.age = 22; Person.prototype.job = 'student'; Person.prototype.sayName = function() { alert(this.name); }; var person1 = new Person(); person1.sayName(); //"StrayBugs" var person2 = new Person(); person2.sayName(); //"StrayBugs" alert(person1.sayName == person2.sayName); //true原型也可以用字面量来创建,但是其 constructor 要手动修改,具体方法及副作用见书 P155。如下图,原型的 constructor 属性指向 Person,Person 的两个实例的 [[Prototype]] 直接指向原型,与 Person 没有直接关系。上图可以看到三者是共用同一个原型。于是 Person 在原型上的改变会影响到所有的实例。Person.prototype.sayName = function() { alert("hi!"); }; person1.sayName(); //"hi!" person2.sayName(); //"hi!"注意当实例上存在与原型重名的属性时,实例的属性会屏蔽掉原型的属性。因为先是查看实例中有无该属性,没找到才会去原型中查找。书本 P150。对象还可以重写原型,但此时已创建的实例依然指向旧原型(前面说了实例原型与对象无直接关系)。书本 P157优点:共用原型减少了冗余。缺点:在原型上的改变会影响到所有的实例,于是实例没有了独立性。组合使用构造函数模式和原型模式目的是解决原型模式的独立性问题。将需要共用的属性(一般是方法)定义在原型上,将独立的属性定义在构造函数中。function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype = { constructor : Person, sayName : function(){ alert(this.name); } }; var person1 = new Person('StrayBugs', 22, 'student'); var person2 = new Person('Angel', 20, 'Artist'); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Count,Van" alert(person2.friends); //"Shelby,Count" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true优点:结合了构造函数模式和原型模式的优点,并解决了其缺点。缺点:代码没有很好的封装起来。动态原型模式看到这里也应该猜到,动态原型模式就是为了解决上面的封装问题。function Person(name, age, job){ //属性 this.name = name; this.age = age; this.job = job; //方法 if (typeof this.sayName != "function"){ Person.prototype.sayName = function(){ alert(this.name); }; } } var friend = new Person('StrayBugs', 22, 'student'); friend.sayName(); //'StrayBugs'这里即使有多个方法也只需判断其中一个方法存不存在即可开始初始化。到了这里其实最后两种创建对象的方法已经非常完美了。接下来讲的是一些特殊情况下,上面都不适应时的方法。寄生构造函数模式顾名思义,有时候我们需要在一些已有的对象上添加一些方法,但是又不能(或不希望)改变该对象的构造函数,就可以用寄生构造函数模式。function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var person1 = new createPerson('StrayBugs', 22, 'student'); var person2 = new createPerson('Angel', 20, 'Artist');它的定义方法跟工厂模式一模一样,不同的是调用时使用 new 创建。这是因为虽然里面都是 o,工厂模式中的 o 是作为实例,所以返回的是实例。寄生构造函数模式中的 o 是作为构造函数,所以返回的是构造函数。下面的例子更贴切。function SpecialArray(){ //创建数组 var values = new Array(); //添加值 values.push.apply(values, arguments); //添加方法 values.toPipedString = function(){ return this.join("|"); }; //返回数组 return values; } var colors = new SpecialArray("red", "blue", "green"); alert(colors.toPipedString()); //"red|blue|green"这样就在 Array 的基础上建立了新的构造函数了。缺点:与工厂模式一样,不能依赖 instanceof 操作符来确定对象类型。稳妥构造函数模式主要是为了在安全执行环境中使用。P161稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的实例方法不引用 this;二是不使用 new 操作符调用构造函数。function Person(name, age, job){ //创建要返回的对象 var o = new Object(); //可以在这里定义私有变量和函数 //添加方法 o.sayName = function(){ alert(name); }; //返回对象 return o; } 这里除了使用 sayName() 方法之外,没有其他办法访问 name 的值。可以像下面使用稳妥的 Person 构造函数。var friend = Person('StrayBugs', 22, 'student'); friend.sayName(); //'StrayBugs'缺点:与寄生构造函数一样,不能依赖 instanceof 操作符来确定对象类型。总结以上五花八门的创建对象方式正体现了 JavaScript 的灵活性。这里没有好与差的方法,只有最适合的方法。我认为重点是把这几种方法串起来,因为如果不了解其 WHAT HOW WHY,不仅很容易就忘记了,而且不能清晰的了解在什么场合适合运用什么方法。所以希望有机会能看到这篇文章的同学以后不用再愁“对象问题”啦!
2024年09月10日
3 阅读
0 评论
0 点赞
1
...
21
22
23
...
47