Andre Huang


  • 首页

  • 归档

关于 jQuery 几种事件绑定的方式

发表于 2016-09-10

背(chui)景(shui)

用了那么久 jQ,也用过他提供的几种事件绑定的方法,包括 bind、live、delegate 和 on。港真,一开始用的时候还真没有好好区分,各种混用。现在也该藉由当前的经验,对这些方法好好总结一下,加深理解。
(后记:后面三种方法好像应该叫事件委托,因为都是通过将事件处理器绑定到某个祖先元素,让其来代替处理事件,而元素本身不处理)

bind

$( selector ).bind( event, handler )

bind 方法,就是典型的事件绑定了。以 $(‘a’).bind(‘click’, handler) 为栗子,bind 方法是通过遍历找出所有满足
选择器的元素,来给它们一一绑定。

live

$( selector [,context]).live( event, handler )

live 方法,是将事件委托到 document 元素,即事件的处理器 handler 绑定到 $(document) 元素上。当某个事件触发时,live 方法会根据事件类型和选择器对具体元素进行匹配,然后处理事件。
当然,也可以自己手动设置上下文,这样就不用绑定到 $(document),如:$( ‘li’,$(‘#container’)[0] ).live(‘click’,function(event){});
使用 live 方法绑定到 document 时有个缺点,就是中间如果隔着较多层元素的话,在冒泡的过程中会影响性能。
(不过,从 v1.9+ 开始,就不再支持这个方法了)

delegate

$( parent-selector ).delegate( selector, event, handler )

delegate 方法,是通过将 handler 直接绑定到某个祖父元素,在事件触发时,通过找到符合参数中指定选择器的子元素进行处理。

bind 和 live/delegate 的选择

基于这三个方法的特点,可以归纳下列三种情况:

  1. 为 DOM 中的很多不同元素绑定相同的事件,选后两者而不选 bind
  2. 为不存在于 DOM 的元素绑定事件,同样不选 bind
  3. 结构复杂的 DOM 中,使用 delegate

on

$([parent-]selector).on( events [, selector] [, data ], handler(event) )

v1.7+ 开始,逐渐取代了 live、delegate 和 bind。
如果用特定元素绑定事件,如:

$('button').on( 'click', function(){} )

这种形式和 bind 绑定方式一样。因此,这种绑定方法不宜使用于尚未存在的元素。
因此,指定 selector 参数,就是事件委托;否则,就是常规绑定。
其实也就是说,以后只用 on/off 进行绑定/解绑事件就够了。

P.s.

几种绑定方法相应的解绑方法
bind —— unbind
live —— die
delegate —— undelegate
on —— off

Reference

http://www.cnblogs.com/rabbit2012/archive/2013/03/15/2961881.html

表单常用事件

发表于 2016-09-08

onchange

onchange 事件,当文本域的内容发生改变时,就会触发。
支持该事件的元素有:input(type=”text”)、select、textarea
具体触发条件是:当文本域的内容(value)改变,并且离开焦点之后,就会触发事件。
(因此,通过 js 来赋予内容,是不会触发该事件的)

onpropertychange

onpropertychange 事件,当元素的某个属性值(属性值包括样式的属性、自定义属性等)被修改,就会触发该事件。
单击 input 会触发,是因为单击聚焦时,修改了元素的 _change_attached 这个属性值。当同时有多个属性值被改变时,则会触发相应次数的 onpropertychange 事件。
在 onpropertychange 事件的回调函数中,我们可以对其传一个对象,通过对象我们可以获取当前修改的属性值名称,如:

document.getElementById("xxx").attachEvent('onpropertychange', function(obj) {
console.log( obj.propertyName );
// 通过这个属性名,可以进行不同操作
if ( obj.propertyName === "value" ) {
alert( "value change" );
} else {
console.log( "others" );
}
});

然而,onpropertychange 事件只能用于 IE,火狐等非 IE 浏览器应用 oninput 代替。
但是 oninput 事件只在 input 的 value 值发生改变时触发,必须是键盘输入才有效(包括剪切粘贴)。
另外,当使用 jq 的 data() 方法修改变量值时不会触发事件
(没有试验)P.S. onpropertychange的bug
在代码实现时,发现在响应用户onclick了textarea时,如果使用obj.className=”XX”;来改变textarea输入框中字体的样式,会导致在ie下会有在输入第一个字符的时候onpropertychange不会触发的bug,因此需要这样设置:obj.style.color=”#000”;

粘贴事件 onpaste

Opera是不支持onpaste事件的。IE6-8,Safari,firefox 3都支持

复制事件 oncopy

剪切事件 oncut

IE6-8,Safari,firefox 3都支持

学习分页插件 - jQuery.pagination.js

发表于 2016-09-06

pagination

初始化分页插件

$(“#container”).pagination( max_entries, extraOptions );

参数说明

max_entries 为总的条目数

extraOptions 是一个可选的配置对象,具体参数如下:

  • item_per_page
    每页显示的条目数,可选,默认10
  • num_display_entries
    连续分页主体部分显示的分页条目数,默认10
    当取4时:

    取6:
  • current_page
    当前选中的页面,默认0,即第1页
  • num_edge_entries
    两侧显示的首尾分页的条目数,默认0
    默认情况下:

    设置为1:

    设置为2:
  • link_to
    分页的链接,默认”#”
  • prev_text
    “上一页”按钮上显示的文字,默认”Prev”
  • next_text
    “下一页”按钮上显示的文字,默认”Next”
  • ellipse_text
    表示省略页数的文字,默认”…”
  • prev_show_always
    是否显示“上一页”分页按钮,布尔型,默认true
  • next_show_always
    是否显示“下一页”分页按钮,布尔型,默认true
  • callback
    回调函数,默认无执行效果。函数接受两个参数(点击的页码,分页插件的容器 DOM 元素)

CSS 呼吸灯效果

发表于 2016-09-05

DIY 一个呼吸灯

所谓“呼吸灯”,就是指一个元素会不停地类似呼吸的节奏,进行闪烁。

(其实这个概念还是挺耳熟能详的- -)

原理嘛,就是利用了 CSS3 的动画 @keyframes 和 animation 属性,自定义呼吸的节奏(动画的效果和时间)。此外,也利用了 box-shadow 属性来给元素增加阴影,起到了灯光发散的效果。

直接 po 上代码:

/* 定义动画的起始效果,CSS3会在这个区间中平缓过渡 */
/* 背景色 background-color 的变化可以实现灯光闪烁的效果 */
/* 阴影色 box-shadow 的变化可以实现灯光发散的效果 */
@keyframes breathing{
0% {
background-color: #eee;
box-shadow: 0 0 5px #eee;
}
100% {
background-color: #999;
box-shadow: 0 0 15px #eee;
}
}
.breathing-light{
/* 省略一些样式属性 */
animation-name: 'breathing';
animation-duration: 3000ms;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite; /* 动画循环次数,现在是无限循环 */
animation-direction: alternate; /* 动画执行的方向,现在是会在0-100%中来回进行 */
}

Vue学习笔记(十) - 组件

发表于 2016-09-03

组件

概述

所谓组件,在我看来,是一段自定义的可复用的 HTML 代码(包括内容、样式和行为)。

也就是说,一个组件应该要有以下部分:

  • 样式 - style
  • 内容 - template
  • 行为 - script

使用

使用 Vue 的组件,要按照以下步骤进行:

  1. 定义组件,也就是创建一个组件构造器
  2. 注册组件
  3. 使用组件

<!-- HTML part -->
<div id="app">
<simple-component> test1 </simple-component>
</div>
<simple-component> test2 </simple-component>
// JS part
// 定义一个组件,创建构造器
var SimpleComponent = Vue.extend({
template: '<div>先做一个最简单的组件</div>'
});
// 注册组件
Vue.component('simple-component', SimpleComponent);
// 使用组件
var vm = new Vue({
el: '#app'
});

只有当挂载到某个 Vue 实例下,组件才会生效。
从上图可以看出,simple-component 组件在 #app 下才生成,直接放置则没有。

全局注册&局部注册

当依照上述流程来生成一个组件,既通过 Vue.component() 来注册组件的话,这个组件是全局的,每个 Vue 实例都可以插入该组件。

如果不需要全局注册的话,或者只允许某些组件使用,用 Vue 实例化的选项对象的 component 属性来实现局部注册。

<!-- HTML part -->
<div class="group">
<p>局部注册</p>
<p>只允许组件my-component在app1中使用,app2不允许</p>
<div id="app1">
<my-component>生成指令时这句话就会替换掉</my-component>
</div>
<div id="app2">
<my-component>生成指令时这句话就会替换掉</my-component>
</div>
</div>
// JS part
// 局部注册
// 定义一个组件,创建构造器
var MyComponent = Vue.extend({
template: '<div>我是my-component</div>'
});
// 使用组件
var vm1 = new Vue({
el: '#app1',
components: {
'my-component': MyComponent
}
});
var vm2 = new Vue({
el: '#app2'
});

父子组件

父子组件,顾名思义,就是组件之间构成了父子关系,即在组件内部定义并使用了其他组件。

实现方法:在父组件的构造器定义时,在选项对象中加入 components 属性,属性的值为一个对象,自定义标签名为 key,组件构造器为 value。

<!-- HTML part -->
<div id="app">
<parent-component></parent-component>
</div>
// JS part
// 定义子组件
var ChildComponent = Vue.extend({
template: '<span style="background: pink;">这里是子组件</span>'
});
// 定义父组件
var ParentComponent = Vue.extend({
// 把子组件以标签的形式嵌入到当前这个父组件中使用
template: '<div style="background-color:lightgreen;padding:10px">'
+'这里是父组件'
+'<child-component></child-component>'
+'</div>',
// 把 ChildComponent 组件注册到 ParentComponent 中
components: {
'child-component': ChildComponent
}
});
// 注册父组件
Vue.component('parent-component', ParentComponent);
// 生成实例
new Vue({
el: '#app'
});

由于子组件是在父组件中注册的,因此决定了它不能在父组件以外的组件内部使用。子组件只能在父组件的 template 中使用。

因此下面的使用方式是错误的:

  1. 直接在 HTML 文件中以子元素的形式在父组件的标签中使用
    <div id="app">
    <parent-component>
    <child-component></child-component>
    </parent-component>
    </div>

不管是否有在父组件设置了 template 属性,都不允许。因为在组件渲染的时候,HTML 的内容已经确定,子标签因为不是标准的 HTML 标签,因此直接被忽略。

  1. 在父组件标签外部使用子组件
<div id="app">
<parent-component></parent-component>
<child-component></child-component>
</div>

Script 和 Template

在上面的代码中,对于所有组件,它们的模版 template 的属性值都是拼接的 HTML 代码串,这样会使 HTML 代码和 JavaScript 代码高度耦合,不利于维护。

要解决这个问题,可以使用 script 标签或者 template 标签将组件的模版内容放在 HTML 文件中。

  • script

    <!-- HTML -->
    <script type="text/x-template" id="myComponent">
    <div>这里是模版内容</div>
    </script>
  • template

    <!-- HTML -->
    <template id="myComponent">
    <div>这里是模版内容</div>
    </template>

使用模版只需要将模版标签的 id 值赋给 template 属性:

Vue.extend({
template: "#myComponent"
})

使用props

每个组件实例其作用域都是独立的,这样也意味着,无法在子组件直接引用父组件的数据。反之亦然。使用 props 可以将父组件的数据传给子组件。

(为什么文档没有说父组件怎么引用子组件?)

直接传值

直接传值的话,就是说在定义子组件的组件构造器时,添加一个 props 属性,其值为一个数组,数组的元素为子组件用来绑定父组件变量的变量名(string)

// 增加了几个输入框,检测父子组件的变量的变化关系
var cc = Vue.extend({
template: '<p style="color:red;">{{myLyric}}</p>'
+'<p><input type="text" v-model="myLyric"/></p>',
props: ['myLyric'] // 设置和父组件绑定的变量名
});
var cp = Vue.extend({
template: '<p>{{lyric}}</p>'
+'<input type="text" v-model="lyric">'
+'<cc-child v-bind:my-lyric="lyric"></ccc-child>', // 在这里绑定父子组件的变量
components: {
'cc-child': cc
},
data: function(){ // 定义组件内的变量,组件内data属性值应该用函数返回一个对象,而不直接设置为一个对象
return {
lyric: "如日记内的一根倒刺"
}
}
});
var vm2 = new Vue({
el: '#app2',
components: {
'cc-parent': cp
}
});

在这个栗子中,这是一个单向绑定。父组件的变量改变时,子组件绑定的变量会相应改变。反之不然,子组件的变量改变时,父组件的不会改变。

注意:在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,
需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。

假如要实现父子组件的变量双向绑定的话呢?很简单。只要在绑定变量时加上 .sync 后缀修饰符就可以了。

e.g. :my-param .sync =”param”

也可以实现单次绑定:

e.g. :my-param .once =”param”

参考资料:http://www.cnblogs.com/keepfool/p/5625583.html#h2_6
1…345…8
Andre Huang

Andre Huang

40 日志
19 标签
GitHub
© 2018 Andre Huang
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.3