Vue.js解析(四)【Vue.js事件机制】 - 极客神殿 - CSDN博客
document.getElementById("popuLayer_js_q").onload = function () { var styObjd = styObj = { width: "300px", "height": parseInt(250) + 28 }; window.CSDN.Layer.PopuLayer("#layerd", { storageName: "layerd", styleObj: styObjd, total: 50, expoire: 1000 * 60 });
var username = "WuLex"; var _blogger = username; var blog_address = "http://blog.csdn.net/wulex"; var static_host = "http://static.blog.csdn.net"; var currentUserName = "nappingCat_Wang";
window.quickReplyflag = true; var isBole = false; var fasrc="http://my.csdn.net/my/favorite/miniadd?t=Vue.js%e8%a7%a3%e6%9e%90(%e5%9b%9b)%e3%80%90Vue.js%e4%ba%8b%e4%bb%b6%e6%9c%ba%e5%88%b6%e3%80%91&u=http://blog.csdn.net/wulex/article/details/78553352?utm_source=debugrun&utm_medium=referral"
(function () {('pre.prettyprint code').each(function () { var lines =
(this).text().split(′\n′).length;var
numbering = $('
关闭
(function () { var s = “_” + Math.random().toString(36).slice(2); document.write(‘
‘); (window.slotbydup = window.slotbydup || []).push({ id: ‘4740870’, container: s, size: ‘300,250’, display: ‘inlay-fix’ }); })();
<div id="body">
<div id="main">
<div class="main">
<div class="ad_class">
<div class="article_manage clearfix">
<div class="article_l">
<span class="link_categories">
标签:
<a href='http://www.csdn.net/tag/vue' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">vue</a><a href='http://www.csdn.net/tag/%e4%ba%8b%e4%bb%b6' target=_blank onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_tag']);">事件</a>
</span>
</div>
<div class="article_r">
<span class="link_postdate">2017-11-17 10:19</span>
<span class="link_view" title="阅读次数">100人阅读</span>
<span class="link_comments" title="评论次数"> <a href="#comments" onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_pinglun'])">评论</a>(0)</span>
<span class="link_collect tracking-ad" data-mod="popu_171"> <a href="javascript:void(0);" onclick="javascript:collectArticle('Vue.js%e8%a7%a3%e6%9e%90(%e5%9b%9b)%e3%80%90Vue.js%e4%ba%8b%e4%bb%b6%e6%9c%ba%e5%88%b6%e3%80%91','78553352');return false;" title="收藏">收藏</a></span>
<span class="link_report"> <a href="#report" onclick="javascript:report(78553352,2);return false;" title="举报">举报</a></span>
</div>
</div> <style type="text/css">
.embody{
padding:10px 10px 10px;
margin:0 -20px;
border-bottom:solid 1px #ededed;
}
.embody_b{
margin:0 ;
padding:10px 0;
}
.embody .embody_t,.embody .embody_c{
display: inline-block;
margin-right:10px;
}
.embody_t{
font-size: 12px;
color:#999;
}
.embody_c{
font-size: 12px;
}
.embody_c img,.embody_c em{
display: inline-block;
vertical-align: middle;
}
.embody_c img{
width:30px;
height:30px;
}
.embody_c em{
margin: 0 20px 0 10px;
color:#333;
font-style: normal;
}
</style>
<script type="text/javascript">
$(function () {
try
{
var lib = eval("("+$("#lib").attr("value")+")");
var html = "";
if (lib.err == 0) {
$.each(lib.data, function (i) {
var obj = lib.data[i];
//html += '<img src="' + obj.logo + '"/>' + obj.name + " ";
html += ' <a href="' + obj.url + '" target="_blank">';
html += ' <img src="' + obj.logo + '">';
html += ' <em><b>' + obj.name + '</b></em>';
html += ' </a>';
});
if (html != "") {
setTimeout(function () {
$("#lib").html(html);
$("#embody").show();
}, 100);
}
}
} catch (err)
{ }
});
</script>
<div class="category clearfix">
<div class="category_l">
<img src="http://static.blog.csdn.net/images/category_icon.jpg">
<span>分类:</span>
</div>
<div class="category_r">
<label onclick="GetCategoryArticles('7054394','WuLex','top','78553352');">
<span onclick="_gaq.push(['_trackEvent','function', 'onclick', 'blog_articles_fenlei']);">Vue.js<em>(15)</em></span>
<img class="arrow-down" src="http://static.blog.csdn.net/images/arrow_triangle _down.jpg" style="display:inline;">
<img class="arrow-up" src="http://static.blog.csdn.net/images/arrow_triangle_up.jpg" style="display:none;">
<div class="subItem">
<div class="subItem_t"><a href="http://blog.csdn.net/WuLex/article/category/7054394" target="_blank">作者同类文章</a><i class="J_close">X</i></div>
<ul class="subItem_l" id="top_7054394">
</ul>
</div>
</label>
</div>
</div>
Vue事件API
众所周知,Vue.js为我们提供了四个事件API,分别是
$on</code></a>,<a href="https://cn.vuejs.org/v2/api/#vm-once-event-callback"><code>$once
,$off</code></a>,<a href="https://cn.vuejs.org/v2/api/#vm-emit-event-…args"><code>$emit
。
初始化事件
初始化事件在vm上创建一个_events对象,用来存放事件。_events的内容如下:
{
eventName: [func1, func2, func3]
}
存放事件名以及对应执行方法。
/*初始化事件*/
export function initEvents (vm: Component) {
/*在vm上创建一个_events对象,用来存放事件。*/
vm._events = Object.create(null)
/*这个bool标志位来表明是否存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/
vm._hasHookEvent = false
// init parent attached events
/*初始化父组件attach的事件*/
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners)
}
}
$on
$on</code>方法用来在vm实例上监听一个自定义事件,该事件可用$emit触发。
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
const vm: Component = this
/*如果是数组的时候,则递归$on,为每一个成员都绑定上方法*/
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$on(event[i], fn)
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
/*这里在注册事件的时候标记bool值也就是个标志位来表明存在钩子,而不需要通过哈希表的方法来查找是否有钩子,这样做可以减少不必要的开销,优化性能。*/
if (hookRE.test(event)) {
vm._hasHookEvent = true
}
}
return vm
}
$once
$once
监听一个只能触发一次的事件,在触发以后会自动移除该事件。
Vue.prototype.$once = function (event: string, fn: Function): Component {
const vm: Component = this
function on () {
/*在第一次执行的时候将该事件销毁*/
vm.$off(event, on)
/*执行注册的方法*/
fn.apply(vm, arguments)
}
on.fn = fn
vm.$on(event, on)
return vm
}
$off
$off
用来移除自定义事件
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
const vm: Component = this
// all
/*如果不传参数则注销所有事件*/
if (!arguments.length) {
vm._events = Object.create(null)
return vm
}
// array of events
/*如果event是数组则递归注销事件*/
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$off(event[i], fn)
}
return vm
}
// specific event
const cbs = vm._events[event]
/*Github:https://github.com/answershuto*/
/*本身不存在该事件则直接返回*/
if (!cbs) {
return vm
}
/*如果只传了event参数则注销该event方法下的所有方法*/
if (arguments.length === 1) {
vm._events[event] = null
return vm
}
// specific handler
/*遍历寻找对应方法并删除*/
let cb
let i = cbs.length
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break
}
}
return vm
}
$emit
$emit
用来触发指定的自定义事件。
Vue.prototype.$emit = function (event: string): Component {
const vm: Component = this
if (process.env.NODE_ENV !== 'production') {
const lowerCaseEvent = event.toLowerCase()
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
`Event "${lowerCaseEvent}" is emitted in component ` +
`${formatComponentName(vm)} but the handler is registered for "${event}". ` +
`Note that HTML attributes are case-insensitive and you cannot use ` +
`v-on to listen to camelCase events when using in-DOM templates. ` +
`You should probably use "${hyphenate(event)}" instead of "${event}".`
)
}
}
let cbs = vm._events[event]
if (cbs) {
/*将类数组的对象转换成数组*/
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
/*遍历执行*/
for (let i = 0, l = cbs.length; i < l; i++) {
cbs[i].apply(vm, args)
}
}
return vm
}
- ').addClass('pre-numbering').hide(); (this).addClass(′has−numbering′).parent().append( numbering); for (i = 1; i