javascript钩子,web 钩子-成都快上网建站

javascript钩子,web 钩子

如何在WordPress上正确加载Javascript和CSS

有两种常用的 add_action 钩子可以加载 脚本和CSS到WordPress:

在南县等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站制作、网站设计 网站设计制作定制设计,公司网站建设,企业网站建设,品牌网站建设,全网整合营销推广,成都外贸网站建设公司,南县网站建设费用合理。

init: 确保始终为您的网站头部加载脚本和CSS(如果使用home.php,index.php或一个模板文件),以及其他“前端”文章、页面和模板样式。

wp_enqueue_scripts:“适当”的钩子方法,并不总是有效的,根据你的WordPress设置。

下面的所有例子都在WordPress多站点模式、WordPress 3.4.2 通过测试(如果不支持后续版本,请留言告知)

加载外部 jQuery 库和主题自定义的脚本、样式

下面这个例子在 add_action 钩子中使用 init。使用 init 有两个原因,一是因为我们正在注销WordPress默认的jQuery库,然后加载谷歌的jQuery库;二是确保在WordPress的头部就加载脚本和CSS。

使用if ( !is_admin() )是为了确保这些脚本和css只在前端加载,不会再后台管理界面加载。

/** Google jQuery Library, Custom jQuery and CSS Files */

function myScripts() {

wp_register_script( 'google', '' );

wp_register_script( 'default', get_template_directory_uri() . '/jquery.js' );

wp_register_style( 'default', get_template_directory_uri() . '/style.css' );

if ( !is_admin() ) { /** Load Scripts and Style on Website Only */

wp_deregister_script( 'jquery' );

wp_enqueue_script( 'google' );

wp_enqueue_script( 'default' );

wp_enqueue_style( 'default' );

}

}

add_action( 'init', 'myScripts' );

加载WP默认 jQuery 库和主题自定义的脚本、样式

第3行:使用 array(‘jquery’) 是为了告诉 WordPress 这个 jquery.js 是依赖WordPress 的jQuery库文件,从而使 jquery.js 在WordPress jQuery库文件后加载。

/** Add Custom jQuery and CSS files to a Theme */

function myScripts() {

wp_register_script( 'default', get_template_directory_uri() . '/jquery.js', array('jquery'), '' );

wp_register_style( 'default', get_template_directory_uri() . '/style.css' );

if ( !is_admin() ) { /** Load Scripts and Style on Website Only */

wp_enqueue_script( 'default' );

wp_enqueue_style( 'default' );

}

}

add_action( 'init', 'myScripts' );

加载 print.css 到你的WordPress主题

第 3 行:最后的 ‘print’是媒体屏幕调用,确保 print.css 在网站的打印机中的文件加载时才加载。

/** Adding a Print Stylesheet to a Theme */

function myPrintCss() {

wp_register_style( 'print', get_template_directory_uri() . '/print.css', '', '', 'print' );

if ( !is_admin() ) { /** Load Scripts and Style on Website Only */

wp_enqueue_style( 'print' );

}

}

add_action( 'init', 'myPrintCss' );

使用 wp_enqueue_scripts 替换 init

如果你要在文章或页面加载唯一的脚本,那就应该使用 wp_enqueue_scripts 替换 init。使用 wp_enqueue_scripts 仅仅只会在前台加载脚本和CSS,不会在后台管理界面加载,所以没必要使用 !is_admin() 判断。

使用 is_single() 只在文章加载脚本或CSS

第 3 行的 # 替换为文章的ID就可以让脚本和css只加载到那篇文章。当然,如果直接使用 is_single() (不填ID),就会在所有文章加载脚本和CSS。

/** Adding Scripts To A Unique Post */

function myScripts() {

if ( is_single(#) ) { /** Load Scripts and Style on Posts Only */

/** Add jQuery and/or CSS Enqueue */

}

}

add_action( 'wp_enqueue_scripts', 'myScripts' );

使用 is_page() 只在页面加载脚本或CSS

第 3 行的 # 替换为页面的ID就可以让脚本和css只加载到那个页面。当然,如果直接使用 is_single() (不填ID),就会在所有页面加载脚本和CSS。

/** Adding Scripts To A Unique Page */

function myScripts() {

if ( is_page(#) ) { /** Load Scripts and Style on Pages Only */

/** Add jQuery and/or CSS Enqueue */

}

}

add_action( 'wp_enqueue_scripts', 'myScripts' );

使用 admin_enqueue_scripts 加载脚本到后台

这个例子将在整个后台管理界面加载脚本和CSS。这个方法不推荐用在插件上,除非插件重建了整个后台管理区。

第 10 行使用 admin_enqueue_scripts 替换了 init 或 wp_enqueue_scripts

第 5、6 行,如果你要自定义后台管理区,你可以需要禁用默认的WordPress CSS调用。

/** Adding Scripts To The WordPress Admin Area Only */

function myAdminScripts() {

wp_register_script( 'default', get_template_directory_uri() . '/jquery.js', array('jquery'), '' );

wp_enqueue_script( 'default' );

//wp_deregister_style( 'ie' ); /** removes ie stylesheet */

//wp_deregister_style( 'colors' ); /** disables default css */

wp_register_style( 'default', get_template_directory_uri() . '/style.css', array(), '', 'all' );

wp_enqueue_style( 'default' );

}

add_action( 'admin_enqueue_scripts', 'myAdminScripts' );

加载脚本和CSS到WordPress登录界面

第 6 行:我无法弄清楚如何在在登录页面注册/排序 CSS文件,所以这行手动添加样式表。

第 10-14行:用来移除WordPress默认的样式表。

/** Adding Scripts To The WordPress Login Page */

function myLoginScripts() {

wp_register_script( 'default', get_template_directory_uri() . '/jquery.js', array('jquery'), '' );

wp_enqueue_script( 'default' );

?

link rel='stylesheet' id='default-css' href='?php echo get_template_directory_uri() . '/style.css';?' type='text/css' media='all' /

?php }

add_action( 'login_enqueue_scripts', 'myLoginScripts' );

/** Deregister the login css files */

function removeScripts() {

wp_deregister_style( 'wp-admin' );

wp_deregister_style( 'colors-fresh' );

}

add_action( 'login_init', 'removeScripts' );

加载脚本和CSS到WordPress插件

WordPress插件加载脚本和CSS也是常见的。主要的不同之处在于文件的 URL。主题使用的是 get_template_directory_uri ,而插件应该用 plugins_url ,因为文件是从插件目录进行加载的。

从插件加载脚本和CSS

这个例子将在整个网站前端加载脚本和CSS。

/** Global Plugin Scripts for Outside of Website */

function pluginScripts() {

wp_register_script( 'plugin', plugins_url( 'jquery.js' , __FILE__ ), array('jquery'), '' );

wp_register_style( 'plugin', plugins_url( 'style.css' , __FILE__ ) );

if ( !is_admin() ) { /** Load Scripts and Style on Website Only */

wp_enqueue_script( 'plugin' );

wp_enqueue_style( 'plugin' );

}

}

add_action( 'init', 'pluginScripts' );

从插件加载脚本和CSS到后台管理区

如果你需要在整个后台管理区加载脚本和CSS,就使用 admin_enqueue_scripts 替换 init。

/** Global Plugin Scripts for The WordPress Admin Area */

function pluginScripts() {

wp_register_script( 'plugin', plugins_url( 'jquery1.js' , __FILE__ ), array('jquery'), '' );

wp_enqueue_script( 'plugin' );

wp_register_style( 'plugin', plugins_url( 'style1.css' , __FILE__ ) );

wp_enqueue_style( 'plugin' );

}

add_action( 'admin_enqueue_scripts', 'pluginScripts' );

从插件加载脚本和CSS到插件设置页面

例子只会加载所需的脚本和CSS到插件设置页面,不会在管理区的其他页面加载。

第 3 行:自定义 page= 后面的值为你的插件设置页面

/** Adding Scripts On A Plugins Settings Page */

function pluginScripts() {

if ( $_GET['page'] == "plugin_page_name.php" ) {

wp_register_script( 'plugin', plugins_url( 'jquery.js' , __FILE__ ), array('jquery'), '' );

wp_enqueue_script( 'plugin' );

wp_register_style( 'plugin', plugins_url( 'style.css' , __FILE__ ) );

wp_enqueue_style( 'plugin' );

}

}

add_action( 'admin_enqueue_scripts', 'pluginScripts' );

将 jQuery 库移动到页脚

你不能将WordPress默认的jQuery 库移动到页面底部,但是你可以将自定义的jQuery 或其他外部jQuery 库(比如Google的)移动到底部。不要将CSS移动到页面底部。

第 3、4 行:最后的 ‘true’告诉WordPress在页面底部加载这些脚本。

/** Moves jQuery to Footer */

function footerScript() {

wp_register_script('jquery', (""), false, '', true );

wp_register_script( 'default', get_template_directory_uri() . '/jquery.js', false, '', true );

if ( !is_admin() ) { /** Load Scripts and Style on Website Only */

wp_deregister_script( 'jquery' );

wp_enqueue_script( 'jquery' );

wp_enqueue_script( 'default' );

}

}

add_action( 'init', 'footerScript' );

vue怎么给路由切换时添加动画

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加 entering/leaving 过渡

条件渲染 (使用 v-if)

条件展示 (使用 v-show)

动态组件

组件根节点

这里是一个典型的例子:

div id="demo"

button v-on:click="show = !show"

Toggle

/button

transition name="fade"

p v-if="show"hello/p

/transition

/div

new Vue({

el: '#demo',

data: {

show: true

}

})

.fade-enter-active, .fade-leave-active {

transition: opacity .5s

}

.fade-enter, .fade-leave-to /* .fade-leave-active in below version 2.1.8 */ {

opacity: 0

}

Toggle

hello

当插入或删除包含在 transition 组件中的元素时,Vue 将会做以下处理:

自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。

如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。

如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作 (插入/删除) 在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和 Vue 的 nextTick 概念不同)

过渡的类名

在进入/离开的过渡中,会有 6 个 class 切换。

v-enter:定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。

v-enter-active:定义过渡的状态。在元素整个过渡过程中作用,在元素被插入时生效,在 transition/animation 完成之后移除。这个类可以被用来定义过渡的过程时间,延迟和曲线函数。

v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入一帧后生效 (于此同时 v-enter 被删除),在 transition/animation 完成之后移除。

v-leave: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。

v-leave-active:定义过渡的状态。在元素整个过渡过程中作用,在离开过渡被触发后立即生效,在 transition/animation 完成之后移除。这个类可以被用来定义过渡的过程时间,延迟和曲线函数。

v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发一帧后生效 (于此同时 v-leave 被删除),在 transition/animation 完成之后移除。

苹果javascript(脚本)在设置什么里面关的

首先打来safari浏览器,找到右上角一个小齿轮图标。点击它

在弹出的菜单,点击偏好设置页面变化后,再找到 安全性 图标点击它。

看到如下图,用红圈起来的地方。

将这个项目前面的的 钩子 全部取消,之后点击红叉

现在再打开有JS内容页面,就会出现提示。(注:这个提示信息是网站制作者设置的,所以不会一样的。有些网页更本不会出现,但是显示内容会出错的)

有哪些用 JavaScript 实现的图形库

JS图形、图标库推荐:

1. JS Charts

JS Charts 是个基于JavaScript的图表生成器,不需要任何编码。JS Charts 非常容易使用,只要用户使用客户端脚本(比如,在 web 浏览器中执行)。它不需要多余的插件和服务器模块,只需要下载 JS Charts 的脚本,准备好 XML,JSON 或者 JavaScript 数组数据。

2. Canvasjs

CanvasJS 是个易用的 HTML5 JavaScript 图表库,基于 Canvas 元素。Graphs 可以通过设备渲染,包括 iPhone,iPad,Android,Windows Phone,Microsoft Surface,Desktops 等等。它允许用户创建适用于所有设备,不影响 web 应用程序的功能和可维护性的富仪表盘。CanvcasJS 有着非常漂亮的主题和超过传统的 Flash 和 SVG 图表 10x 倍以上的速度——生成轻量级,漂亮和响应式的仪表图。

3. Chart.js

Chart.js 是个简单的,面向对象的客户端图形库,用户可以用 6 中不同的方式来可视化数据。每个方式都是动画效果的,完全自定义,而且看起来非常好看,即使在 retina 显示。它使用 HTML5 canvas 元素,支持所有现代浏览器,并且支持 IE7/8。

4. Aristochart

Aristochart 是个高度自定义,灵活的折线 Canvas 图表库,允许用户集中精力在图表的审美方面,后台工作做得非常好。Aristochart 有个持续进步的社区,提供许多不断增长的主题给用户选择。

5. xCharts

xCharts 是一个使用 D3.js 来构建漂亮的可定制的数据驱动的 JavaScript图表库,他使用HTML,CSS,SVG实现图表,xCharts 被设计为一个动态的、流畅的、开放的和可定制化的库。

6. BonsaiJS

BonsaiJS 是个轻量级的 JavaScript图形库,提供直观的图形 API 和 SVG 渲染器。主要特性包括:架构分离的运行器和渲染器;iFrame,Worker 和 Node 运行上下文;形状,路径,Assets(音频,图像,字体,subMovies),Keyframe 和常规动画,等等。支持现代化浏览器: Safari, Chrome 和 Firefox。

7. Sigma.js

Sigma.js 是个免费开源的 JavaScript图形库,使用 HTML5 canvas 元素。它的设计是特别为了在 web 界面分享交互式网络 Map 和动态展示网络数据库。

8. Morris.js

Morris.js 是个轻量级的 JavaScript库,使用 jQuery 和 Raphaenuml 来绘制时序图。 Morris.js 生命周期是从代码驱动 howmanyleft.co.uk 图表开始的。它支持的浏览器有: IE6+, Safari/Chrome/Firefox, iOS 3+ 和 Android 3+。它的公共 API 非常的小,只有一个函数: Morris.Line(选项),包括了许多配置选项。

9. Paper.js

Paper.js 是一个开源的向量图形脚本框架,基于 HTML5Canvas 开发。提供清晰的场景图、DOM和大量强大的功能用来创建各种向量图和贝塞尔曲线。

10. AmCharts

AmCharts 是个高级图表库,适用于所有数据的可视化。AmCharts 包括: Column, Bar, Line, Area, Step, Step without risers, Smoothed line, Candlestick, OHLC, Pie/Donut, Radar/ Polar, XY/Scatter/Bubble, Bullet, Funnel/Pyramid 等等。

11. Smoothie Charts

Smoothie Charts是个极小的图表库,专为实时流媒体数据设计的。Joe Walnes 想展示 WebSocket推动的实时的流数据。虽然很多图表库允许用户动态更新数据,但是没有一个是可以优化源源不断的流数据。

12. Dygraphs

Dygraphs 是个快速,灵活,开源的 JavaScript 图表库。它允许用户展示和解析密集的数据集。可以高亮需要强调的数据集。可以使用鼠标点击或者用鼠标拖动来缩放图表;可以修改数值或者点击条目来调整平均周期。

13. Grafico

Grafico 是 Grafico 是一个基于 Raphaël 和 Prototype.js 构建的 JavaScript 图表库,提供了各种图表类型。这些漂亮的图表,有利于传递他们的信息。

14. Highchart JS

Highcharts JS 是一个制作图表的纯 Javascript类库,主要特性如下:兼容性:兼容当今所有的浏览器,包括 iPhone、IE 和火狐等等;对个人用户完全免 费;纯JS,无BS;支持大部分的图表类型:直线图,曲线图、区域图、区域曲线图、柱状图、饼装图、散布图;跨语言:不管是 PHP、Asp.net 还是 Java 都可以使用。

15. Flotr

Flotr 是一个基于 Prototype 开发的 JavaScript绘图工具。支持图例,鼠标跟踪,图片区域选择,图片缩放,添加事件钩子(event hook),通过CSS设置样式等。

16. Flot

Flot 是受 Plotr 和 PlotKit 的 启发,Ole Laursen 基于 jquery 开发了一个图表绘制(WEB Chart)插件并命名为 flot。 flot 是个纯 JavaSript 库,专注于简单的使用方式,迷人的外观和交互式特性。支持的浏览器有: Internet Explorer 6+, Chrome, Firefox 2+, Safari 3+ and Opera 9.5+。

17. jFreeChart

JFreeChart 主要用来各种各样的图表,这些图表包括:饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。JFreeChart 项目历史悠久,而且有大量的开发者在维护。

18. Plotkit

PlotKit 是一个纯 JavaScript 绘图工具包。它支持 HTML Canvas 和 Adobe SVG。有着很完整的文档,方便用户使用。

19. Planetary.js

Planetary.js 是个令人称奇的创建交互式 web 地球仪的 JavaScript库。它使用 D3 和 TopoJSON 来解析和渲染地理信息。Planetary.js 使用基于插件的架构,甚至默认自身就是个插件!这使得 Planetary.js 非常灵活,而且它是允许用户完全自定义,包括颜色,大小,rotation 等等。更重要的是,用户可以在任意位置使用自定义的颜色和大小来显示动画“pings”;它还支持鼠标拖动和缩放,100% 免费和开源。

20. Ember Charts

Ember Charts 是个图表库,使用 Ember.js 和 d3.js 框架构建的。它包括时间线,条形图,饼图和散点图,非常容易扩展和修改。这些图表组件都是开箱即用的,在图表交互和演示方面应用的很好。

21. Sparky

Sparky 是个免费的 JavaScript 波形图库,依赖于 Raphaël ,非常容易使用。支持多个图表类型(折线,条形,area),折线和区域图可以有多个颜色选择。

22. Envision.js

Envision.js 是个 JavaScript 库,用来简化,快速创建交互式的 HTML5 可视化图表。它包括两个图表类型:时序图和 Finance ,提供 API 给开发者,用户可以直接自定义创建图表。这个库氏基于 Flotr2 和 HTML5 Canvas 的。它与框架无关,依赖于几个小的 JavaScript 库。

23. Dc.js

dc.js 是个 JavaScript 图表库,有着原生的 crossfilter, 支持和允许高效展示大型多维数据集(基于 crossfilter 的示例);图表使用 dc.js 渲染,是使用原生数据驱动,所以能得到用户的实时反馈;dc.js 最大的亮点在于能提供一个简单而强大的 JavaScript 库,能进行数据可视化和分析;不仅支持桌面浏览器还支持移动端。

24. ElyCharts

Elycharts 是一个易于使用的,可定制的 JavaScript图表绘制组件。这个组件可用于绘制大部分常用的图表类型包括:line, column, are, bar, pie, sparklines and combinations。它支持多种交互式功能包括:鼠标跟踪、事件处理、利用各种动画高亮显示选择中的区域,Tooltip,HTML锚点等。可以动 态修改数据,并以漂亮的动画效果展示图表中的变化。图表利用SVG/VML技术生成,基于jQuery + Raphaël开发。

25. AwesomeChartJS

AwesomeChartJS Awesome Chart JS 是一个 JavaScript生成图表的类库,它利用了 HTML5 的 canvas 标签来创建统计图表。此类库就是为了减轻开发者的工作量,使用它只需书写几行代码便能生成漂亮的图表。

26. Arbor.js

Arbor.js 是一个利用 Web Works 和 jQuery创建的可视化图形库,它为图形组织和屏幕刷新处理提供了一个高效的、力导向的布局算法。

27. CanvasXpress

canvasXpress 是一个基于HTML5 canvas标签实现的 JavaScript图表类库,它能够支持线性图、柱形图、饼图和热点图等多种常见的图表类型。它所生成的图表交互性很强,鼠标放 上去时会动态显示值。除此之外,它也具有相当高的可定制性,可设置图表的文字、颜色和要显示/隐藏的元素等。当然更重要的一点是,虽然它使用了 HTML5,但是依然支持IE6浏览器。

28. JSXGraph

JSXGraph 是一个支持各种浏览器的交互式几何图库绘制。JSXGraph 使用 SVG 和 VML。

29. Rickshaw

Rickshaw 是一个用于绘制时序图的简单 jS 库,基于 Mike Bostock’s delightful D3 库构建。

30. rGraph

RGraph 是基于HTML5 canvas标签的HTML5 canvas图形库,支持 20 种不同的可视化类型。使用 canvas 标签,RGraph 创建“HTML5 图表”,意味着更快的 web 页面加载和更少的 web 服务器加载。这能帮助减小 web 页面的大小,低能耗和更快的浏览速度。

31. Fusion Chart

FusionCharts Suite XT 是个专业的 JavaScript图表库,能创建任何类型的图表。它创建的图表都是可以进行完全自定义的,标签,字体,边界等等,都可以进行修改。它有很强的交互功能,有许多信息提示,可 点击的 legend 关键字,还有 dril-down,缩放/滚动 和单击打印图表功能。

32. Graph Dracula

Dracula 是用一系列的工具来显示和布局互动图表,包括各种相关的算法。它只是纯 JavaScript 和 SVG ,并无 Flash,Java,其他插件。它非常容易使用,用户可以很简单的自定义任意的元素。

33. Bluff

Bluff 是个 JavaScript 的 Ruby 的 Gruff graphing library端口。它支持所有 Gruff 的特性,但是有着最小的依赖。用户只需要运行一个第三方脚本: JS.Class 副本(压缩后只有 2.6kB ) 和 Google 的 ExCanvas 副本,用来支持 IE 中的 canvas。这两个脚本在 Bluff 中都有下载。Bluff 自身压缩后大小大概有 11KB 。

34. Pizza Pie Chart

Pizza Pie Charts 是个响应式饼图图表,基于 Adobe Snap SVG 框架,通过 HTML 标记和 CSS 来替代 JavaScript 对象,更容易集成各种先进的技术。

35. jGraph

HTML5 图表组件,完全支持l IE 6-8 和触屏设备。 JGraph 自2001年来就一直提供最先进的图表软件组件,是第一个流行的 JGraph Swing 库。然后在 2005 年走在时代的前沿开发 mxGraph。

JavaScript清除历史记录的一点问题

1.不要做任何假设

(JavaScript是一个不可靠的助手)

可能不唐突的JavaScript 的最重要的一个特性就是——你要停止任何假设:

* 不要假设JavaScript是可用的,你最好认为它很有可能是不可用的,而不是直接依赖于它。

* 在你经过测试确认一些方法和属性可以使用之前,不要假设浏览器支持它们。

* 不要假设HTML代码如你想象的那样正确,每次都要进行检查,并且当其不可用的时候就什么也不要做。

* 让JavaScript的功能独立于输入设备

* 要记住其他的脚本可能会影响你的JavaScript的功能,所以要保证你的脚本的作用域尽可能地安全。

在开始设计你的脚本之前,要考虑的第一件事情就是检查一下你要为其编写脚本的HTML代码,看看有什么东西可以帮助你达到目的。

2.找出钩子和节点关系

(HTML是脚本的基石)

在开始编写脚本之前,要先看一下你要为之编写JavaScript的HTML。如果HTML是未经组织的或者未知的,那么你几乎不可能有一个好的脚本编写方案——很可能就会出现下面的情况:要么是会用JavaScript创建太多标记,要么就是应用太依赖于JavaScript。

在HTML中有一些东西需要考虑,那就是钩子和节点关系。

1.HTML 钩子

HTML最初的和最重要的钩子就是ID,而且ID可以通过最快的DOM方法——getElementById 访问到。如果在一个有效的HTML文档中所有的ID都是独一无二的话(在IE中关于name 和 ID 有一个bug,不过有些好的类库解决了这个问题),使用ID就是安全可靠的,并且易于测试。

其他一些钩子就是是HTML元素和CSS类,HTML元素可以通过getElementsByTagName方法访问,而在多数浏览器中都还不能通过原生的DOM方法来访问CSS类。不过,有很多外部类库提供了可以访问CSS类名(类似于 getElementsByClassName) 的方法。

2.HTML 节点关系

关于HTML的另外比较有意思的一点就是标记之间的关系,思考下面的问题:

* 要怎样才可以最容易地、通过最少的DOM遍历来到达目标节点?

* 通过修改什么标记,可以尽可能多地访问到需要修改的子节点?

* 一个给定的元素有什么属性或信息可以用来到达另外一个元素?

遍历DOM很耗资源而且速度很慢,这就是为什么要尽量使用浏览器中已经在使用的技术来做这件事情。

3.把遍历交给专家来做

(CSS,更快地遍历DOM)

有关DOM的脚本和使用方法或属性(getElementsByTagName, nextSibling, previousSibling, parentNode以及其它)来遍历DOM似乎迷惑了很多人,这点很有意思。而有趣的是,我们其实早已经通过另外一种技术—— CSS ——做了这些事情。

CSS 是这样一种技术,它使用CSS选择器,通过遍历DOM来访问目标元素并改变它们的视觉属性。一段复杂的使用DOM的JavaScript可以用一个CSS选择器取代:

Java代码 var n = document.getElementById('nav'); if(n){ var as = n.getElementsByTagName('a'); if(as.length 0){ for(var i=0;as[i];i++){ as[i].style.color = ‘#369′; as[i].style.textDecoration = ‘none’; } } } /* 下面的代码与上面功能一样 */ #nav a{ color:#369; text-decoration:none; } var n = document.getElementById('nav'); if(n){ var as = n.getElementsByTagName('a'); if(as.length 0){ for(var i=0;as[i];i++){ as[i].style.color = ‘#369′; as[i].style.textDecoration = ‘none’; } } } /* 下面的代码与上面功能一样 */ #nav a{ color:#369; text-decoration:none; }

这是一个可以好好利用的很强大的技巧。你可以通过动态为DOM中高层的元素添加class 或者更改元素ID来实现这一点。如果你使用DOM为文档的body添加了一个CSS类,那么设计师就很可以容易地定义文档的静态版本和动态版本。

Java代码 JavaScript: var dynamicClass = 'js'; var b = document.body; b.className = b.className ? b.className + ' js' : 'js'; CSS: /* 静态版本 */ #nav { .... } /* 动态版本 */ body.js #nav { .... } JavaScript: var dynamicClass = 'js'; var b = document.body; b.className = b.className ? b.className + ' js' : 'js'; CSS: /* 静态版本 */ #nav { .... } /* 动态版本 */ body.js #nav { .... }

4.理解浏览器和用户

(在既有的使用模式上创建你所需要的东西)

不唐突的JavaScript 中很重要的一部分就是理解浏览器是如何工作的(尤其是浏览器是如何崩溃的)以及用户期望的是什么。不考虑浏览器你也可以很容易地使用JavaScript 创建一个完全不同的界面。拖拽界面,折叠区域,滚动条和滑动块都可以使用JavaScript创建,但是这个问题并不是个简单的技术问题,你需要思考下面的问题:

* 这个新界面可以独立于输入设备么?如果不能,那么可以依赖哪些东西?

* 我创建的这个新界面是否遵循了浏览器或者其它富界面的准则(你可以通过鼠标在多级菜单中直接切换吗?还是需要使用tab键?)

* 我需要提供什么功能但是这个功能是依赖于JavaScript的?

最后一个问题其实不是问题,因为如果需要你就可以使用DOM来凭空创建HTML。关于这点的一个例子就是“打印”链接,由于浏览器没有提供一个非 JavaScript的打印文档功能,所以你需要使用DOM来创建这类链接。同样地,一个实现了展开和收缩内容模块的、可以点击的标题栏也属于这种情况。标题栏不能被键盘激活,但是链接可以。所以为了创建一个可以点击的标题栏你需要使用JavaScript将链接加入进去,然后所有使用键盘的用户就可以收缩和展开内容模块了。

解决这类问题的极好的资源就是设计模式库。至于要知道浏览器中的哪些东西是独立于输入设备的,那就要靠经验的积累了。首先你要理解的就是事件处理机制。

5.理解事件

(事件处理会引起改变)

事件处理是走向不唐突的JavaScript的第二步。重点不是让所有的东西都变得可以拖拽、可以点击或者为它们添加内联处理,而是理解事件处理是一个可以完全分离出来的东西。我们已经将HTML,CSS和JavaScript分离开来,但是在事件处理的分离方面却没有走得很远。

事件处理器会监听发生在文档中元素上的变化,如果有事件发生,处理器就会找到一个很奇妙的对象(一般会是一个名为e的参数),这个对象会告诉元素发生了什么以及可以用它做什么。

对于大多数事件处理来说,真正有趣的是它不止发生在你想要访问的元素上,还会在DOM中较高层级的所有元素上发生(但是并不是所有的事件都是这样,focus和blur事件是例外)。举例来说,利用这个特性你可以为一个导航列表只添加一个事件处理器,并且使用事件处理器的方法来获取真正触发事件的元素。这种技术叫做事件委托,它有几点好处:

* 你只需要检查一个元素是否存在,而不需要检查每个元素

* 你可以动态地添加或者删除子节点而并不需要删除相应的事件处理器

* 你可以在不同的元素上对相同的事件做出响应

需要记住的另一件事是,在事件向父元素传播的时候你可以停止它而且你可以覆写掉HTML元素(比如链接)的缺省行为。不过,有时候这并不是个好主意,因为浏览器赋予HTML元素那些行为是有原因的。举个例子,链接可能会指向页面内的某个目标,不去修改它们能确保用户可以将页面当前的脚本状态也加入书签。

6.为他人着想

(命名空间,作用域和模式)

你的代码几乎从来不会是文档中的唯一的脚本代码。所以保证你的代码里没有其它脚本可以覆盖的全局函数或者全局变量就显得尤为重要。有一些可用的模式可以来避免这个问题,最基础的一点就是要使用 var 关键字来初始化所有的变量。假设我们编写了下面的脚本:

Java代码 var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff } function reset(){ // do stuff } var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff } function reset(){ // do stuff }

上面的代码中包含了一个叫做nav的全局变量和名字分别为 init,show 和 reset 的三个函数。这些函数都可以访问到nav这个变量并且可以通过函数名互相访问:

Java代码 var nav = document.getElementById('nav'); function init(){ show(); if(nav.className === 'show'){ reset(); } // do stuff } function show(){ var c = nav.className; // do stuff } function reset(){ // do stuff } var nav = document.getElementById('nav'); function init(){ show(); if(nav.className === 'show'){ reset(); } // do stuff } function show(){ var c = nav.className; // do stuff } function reset(){ // do stuff }

你可以将代码封装到一个对象中来避免上面的那种全局式编码,这样就可以将函数变成对象中的方法,将全局变量变成对象中的属性。 你需要使用“名字+冒号”的方式来定义方法和属性,并且需要在每个属性或方法后面加上逗号作为分割符。

Java代码 var myScript = { nav:document.getElementById('nav'), init:function(){ // do stuff }, show:function(){ // do stuff }, reset:function(){ // do stuff } } var myScript = { nav:document.getElementById('nav'), init:function(){ // do stuff }, show:function(){ // do stuff }, reset:function(){ // do stuff } }

所有的方法和属性都可以通过使用“类名+点操作符”的方式从外部和内部访问到。

Java代码 var myScript = { nav:document.getElementById('nav'), init:function(){ myScript.show(); if(myScript.nav.className === 'show'){ myScript.reset(); } // do stuff }, show:function(){ var c = myScript.nav.className; // do stuff }, reset:function(){ // do stuff } } var myScript = { nav:document.getElementById('nav'), init:function(){ myScript.show(); if(myScript.nav.className === 'show'){ myScript.reset(); } // do stuff }, show:function(){ var c = myScript.nav.className; // do stuff }, reset:function(){ // do stuff } }

这种模式的缺点就是,你每次从一个方法中访问其它方法或属性都必须在前面加上对象的名字,而且对象中的所有东西都是可以从外部访问的。如果你只是想要部分代码可以被文档中的其他脚本访问,可以考虑下面的模块(module)模式:

Java代码 var myScript = function(){ //这些都是私有方法和属性 var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff } function reset(){ // do stuff } //公有的方法和属性被使用对象语法包装在return 语句里面 return { public:function(){ }, foo:'bar' } }(); var myScript = function(){ //这些都是私有方法和属性 var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff } function reset(){ // do stuff } //公有的方法和属性被使用对象语法包装在return 语句里面 return { public:function(){ }, foo:'bar' } }();

你可以使用和前面的代码同样的方式访问返回的公有的属性和方法,在本示例中可以这么访问:myScript.public() 和 myScript.foo 。但是这里还有一点让人觉得不舒服:当你想要从外部或者从内部的一个私有方法中访问公有方法的时候,还是要写一个冗长的名字(对象的名字可以非常长)。为了避免这一点,你需要将它们定义为私有的并且在return语句中只返回一个别名:

Java代码 var myScript = function(){ // 这些都是私有方法和属性 var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff // do stuff } function reset(){ // do stuff } var foo = 'bar'; function public(){ } var myScript = function(){ // 这些都是私有方法和属性 var nav = document.getElementById('nav'); function init(){ // do stuff } function show(){ // do stuff // do stuff } function reset(){ // do stuff } var foo = 'bar'; function public(){ }

//只返回指向那些你想要访问的私有方法和属性的指针

Java代码 return { public:public, foo:foo } }(); return { public:public, foo:foo } }();

这就保证了代码风格一致性,并且你可以使用短一点的别名来访问其中的方法或属性。

如果你不想对外部暴露任何的方法或属性,你可以将所有的代码封装到一个匿名方法中,并在它的定义结束后立刻执行它:

Java代码 (function(){ // these are all private methods and properties var nav = document.getElementById('nav'); function init(){ // do stuff show(); // 这里不需要类名前缀 } function show(){ // do stuff } function reset(){ // do stuff } })(); (function(){ // these are all private methods and properties var nav = document.getElementById('nav'); function init(){ // do stuff show(); // 这里不需要类名前缀 } function show(){ // do stuff } function reset(){ // do stuff } })();

对于那些只执行一次并且对其它函数没有依赖的代码模块来说,这种模式非常好。

通过遵循上面的那些规则,你的代码更好地为用户工作,也可以使你的代码在机器上更好地运行并与其他开发者的代码和睦相处。不过,还有一个群体需要考虑到。

7.为接手的开发者考虑

(使维护更加容易)

使你的脚本真正地unobtrusive的最后一步是在编写完代码之后仔细检查一遍,并且要照顾到一旦脚本上线之后要接手你的代码的开发者。考虑下面的问题:

* 所有的变量和函数名字是否合理并且易于理解?

* 代码是否经过了合理的组织?从头到尾都很流畅吗?

* 所有的依赖都显而易见吗?

* 在那些可能引起混淆的地方都添加了注释吗?

最重要的一点是:要认识到文档中的HTML和CSS代码相对于JavaScript来说更有可能被改变(因为它们负责视觉效果)。所以不要在脚本代码中包含任何可以让终端用户看到的class和ID,而是要将它们分离出来放到一个保存配置信息的对象中。

Java代码 myscript = function(){ var config = { navigationID:'nav', visibleClass:'show' }; var nav = document.getElementById(config.navigationID); function init(){ show(); if(nav.className === config.visibleClass){ reset(); }; // do stuff }; function show(){ var c = nav.className; // do stuff }; function reset(){ // do stuff }; }(); myscript = function(){ var config = { navigationID:'nav', visibleClass:'show' }; var nav = document.getElementById(config.navigationID); function init(){ show(); if(nav.className === config.visibleClass){ reset(); }; // do stuff }; function show(){ var c = nav.className; // do stuff }; function reset(){ // do stuff }; }();

这样维护者就知道去哪里修改这些属性,而不需要改动其他代码。


名称栏目:javascript钩子,web 钩子
本文网址:http://kswjz.com/article/dsdeccs.html
扫二维码与项目经理沟通

我们在微信上24小时期待你的声音

解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流