js/jquery中, 有鼠标移入/移除功能的事件和方法:
-
mouseover/mouseout: 这个是鼠标移入/移除的 , 它会在子元素上绑定 冒泡事件. 所以当鼠标在父元素/子元素之间进行移动的时候, 会 触发元素上的over/out事件多次.
-
mouseenter/leave 这个是鼠标进入/离开, 它不会在子元素上绑定冒泡事件, 所以即使鼠标在父子元素间移动(移入/移出时)都不会触发 enter/leave事件, 整个mouseenter/mouseleave
事件只会触发一次. -
实际上, mouseover就是 普通意义上的 mouse in(鼠标移入)的事件. (因为 jjs中没有 mousein函数的.
-
跟它们相关的还有一个 hover(不是mousehover), 它实际上是等于 hover = mouseenter + mouseleave
-
为什么在某个元素上绑定鼠标移入/移出事件的时候, 控制另一个div中的图片显示/隐藏时, 图片会产生闪烁呢?
- 这个图片闪烁, 还不能用 mouseover/out 改成 mouseenter/leave 来解决; 也不能用 hover来解决.
- 原因是: 因为这个 显示或隐藏的图片的位置, 刚好在 鼠标移入/移除事件的触发目标上了, 这样: 当鼠标进入目标元素中时, 图片被显示, 因为图片又刚好在这个目标元素上, 它就遮住了目标元素, 引起鼠标"移出"目标元素, 从而触发图片的隐藏事件; 当图片隐藏后, 鼠标又进入到目标元素中,从而又触发 显示图片的事件, 当图片显示后, 又遮住了目标元素, 又引起鼠标丢失, 又触发隐藏图片的事件, 如此反复发生, 就引起了图片的闪烁
那么解决方法,就是, 调整一下图片显示的位置, 让图片显示/隐藏的div 容器不要遮住 目标元素就好了
鼠标 over/out 和 enter/leave的区别?
1. 这是mouseover和 mouseout的事件:
<div class="out" style="400px;height:400px;background:red">
outer
<div class="in" style="margin: 80px;150px;height:150px;background:blue">
</div>
</div>
<script>
var out=document.getElementsByClassName('out')[0];
out.onmouseover=function(){
console.log('进入');
}
out.onmouseout=function(){
console.log('出去');
}
// 从div.out 一端进入到另一端出去的输出是: "进入 出去 进入 出去 进入 出去"
</script>
2. 这是 mouseenter和 mouseleave的事件:
<div class="out" style="400px;height:400px;background:red">
outer
<div class="in" style="margin: 80px;150px;height:150px;background:blue">
</div>
</div>
<script>
var out=document.getElementsByClassName('out')[0];
out.onmouseenter=function(){
console.log('进入');
}
out.onmouseleave=function(){
console.log('出去');
}
// 从div.out 一端进入到另一端出去的输出是: "进入 出去"
</script>
css参数可以是 由多个属性名:属性值 组成的对象. 属性名可以不加引号,但是如果是多个单词组成的属性名,则要加引号:
magDiv.css({left:px,top:py,'background-color': '#fc0', border: '1px solid #999','border-radius':'3px'});
要注意,事件发生时鼠标的位置pageX和pageY是 事件event的属性,不是 event.target的属性!!
在判断 图片src没有相应的图片时, 可以显示默认图片, 但是在后面的script脚本中, 如何知道这个img图片没有相应的 真实图片呢? 如果一个一个地在图片所在目录里去查询是否有这个文件, 就太麻烦了几乎不大可能, 解决地方法是: 在 img 的 onerror执行语句集中, 用 原生的js语句添加一个 标识 属性, 然后在后面的js脚本中, 去获取并判断这个属性!比如:
<img order={$i} class="media-object img-rounded mhover" width="48" height="48" jsname="{$rk.jsname}" src="__PUBLIC__/images/members/{$rk.jsname}.jpg" onerror="this.src='__PUBLIC__/images/members/user-default.png';this.setAttribute('hasavatar','no'); this.onerror=null">
最重要的就是 这句: this.setAttribute('hasavatar', 'no');
-- 一般在mouseover和mouseout等对应的函数中, 应该 对 设置对象 进行 相应的 "反设置" 即如果在一个函数中设置了 元素的背景/边框/颜色 等属性, 在另一个对应的函数中, 就要把这些 对应的属性 设置回来. 因为元素的属性设置 具有 粘着性: 即 一旦设置后, 这个属性就一直存在 于元素中了, 所以要将它们这些属性要设置回来!
-- 可以直接将 script脚本的内容, 输出到html文档流中, 使用js的 document.write()方法: 比如始终生成动态的 版权年份: document.write((new Date()).getFullYear())
====================================================================
session的存储并不是说 客户端一点东西都没有, 其中session的id 是通过在 客户端的cookie中存储的 phpsessid(PHPSESSID)中的, 服务器就是通过这个id来读取存储的session的(有的session是存储在数据库中的)
-- session对象的过期并不是 马上的, 关闭浏览器后,session对象可能并没有马上过期,这时如果马上重新打开关闭的页面, 可以直接登录.
-- 要设置 "退出"功能, 马上销毁session/cookie,还是用服务器端的操作方法较好, 不要使用客户端的js代码,因为销毁session等需要服务器语句,而且牵涉到 跳转页面.用js可能会用到ajax,就不划算了.
-- 这个退出功能中, 重要的不是如何清除session等, 而是
如何防止 利用浏览器的后退back按钮返回到已经登录的页面?
history对象表示浏览器的 历史记录 .有back,forward,go等方法: go(-1)等于back, go(1)等于forward, 而go(0)相当于刷新, location.reload会从缓存加载.
利用 h5的 pushState(replaceState)等方法可以阻止浏览器的后退:
history.pushState(stateObj, title, url), 表示向history历史记录的 堆栈中插入push一个新的"假的"浏览页面记录, 并将当前地址栏的url设置为这个新增的url. 其中
- stateObj: 表示关于这个历史记录条目的一些信息,这个stateObj将被作为参数复制一份传入到popstate事件的回调函数中, 一般如果不需要特别的内容时,可以设置为null
- title: 这个新增条目的标题, 一般写作null, 因为没用.
- url: 表示新插入的条目的url地址, 默认的是当前页面的url.所以你写作 空'', 或document.url都是一样的, 当然你也可以写作其他url地址
重要的是: 1. push后, 浏览器的当前url地址会变为第三个参数的地址,但是 它是不会去加载这个地址的页面内容的,甚至不会去检查这个新的url页面是否真的存在, 可以方便地去调试! 所以当前页面显示的内容仍然没有变!
其次, 只有go等函数调用和back/forward按钮操作才会触发 popstate事件. 而pushState调用是不会产生popstate事件的.
console.log中, 字符串和对象相加时, 对象只会显示为[object History], 要显示对象的完整信息, 需要单独地log查看: console.log(history)对象的结果是:
History {length: 1, scrollRestoration: "auto", state:null}
其中history对象的 属性 state是: 当前条目页面所具有的 一些说明信息等 内容, 就是你在pushState时的第一个参数值.这个参数可以是任意的类型, 可以是一个js对象, 也可以是一个说明/描述内容的字符串....
<script>
let iPage=0;
console.log('初次进入页面的history记录条数: ' + history.length);
console.log(history);
++iPage;
var stateObj = {page: iPage+'.html', role: 'test page'+iPage};
history.pushState(stateObj, null, iPage+'.html');
console.log('第一次push后, history记录条数: ' + history.length);
console.log('现在的location url是: ' + window.location);
console.log(history);
window.addEventListener('popstate',function(evt){
console.log('==================================================');
console.log(evt);
++iPage;
let stateObj = {page: iPage+'.html', role: 'test page'+iPage};
history.pushState(stateObj, null, iPage+'.html');
console.log('这时候点击back按钮后, history记录条数: ' + history.length);
console.log('现在的location url是: ' + window.location);
console.log(history);
},false);
</script>
输出console内容:
初次进入页面的history记录条数: 2
History { length: 2, scrollRestoration: "auto", state: null }
第一次push后, history记录条数: 3
"现在的location url是: http://localhost/index.php/1.html"
History { length: 3, scrollRestoration: "auto", state: Object }
==================================================
popstate { target: Window → index.php, isTrusted: true, currentTarget: Window → index.php, eventPhase: 2, bubbles: true, cancelable: false, defaultPrevented: false, timeStamp: 1584519618936290, originalTarget: Window → index.php, explicitOriginalTarget: Window → index.php, NONE: 0 }
这时候点击back按钮后, history记录条数: 3
"现在的location url是: http://localhost/index.php/2.html"
History { length: 3, scrollRestoration: "auto", state: Object }
==================================================
popstate { target: Window → index.php, isTrusted: true, currentTarget: Window → index.php, eventPhase: 2, bubbles: true, cancelable: false, defaultPrevented: false, timeStamp: 1584519620204638, originalTarget: Window → index.php, explicitOriginalTarget: Window → index.php, NONE: 0 } index.php:148:7
这时候点击back按钮后, history记录条数: 3
"现在的location url是: http://localhost/index.php/3.html"
History { length: 3, scrollRestoration: "auto", state: Object }
/////////////////////////////////////////////////////////////////////////
如果将
let stateObj = {page: iPage+'.html', role: 'test page'+iPage};
history.pushState(stateObj, null, iPage+'.html');
修改成:
let state = 'test page'+iPage;
history.pushState(state, null, iPage+'.html');
则得到的History对象就是:
History { length: 3, scrollRestoration: "auto", state: "test page2" }
可以看到, 在上面的console.log 的输出中, history.length 为什么一直没有增加??? :::: 通过点击back/forward按钮产生的 事件 是不会增加 history的length的, 即使你在popstate事件回调回调函数中pushState了新的页面记录, 而且也是在回调函数中查看的history的length. 只有 在浏览器的 一个标签子窗口中: "真实的" 从一个页面 跳转到了一个新的页面, 即使这个新页面是 用pushState得到的. 而不是只是在按 "后退/前进"按钮中push...
<script>
let iPage=0;
console.log('初次进入页面的history记录条数: ' + history.length);
console.log(history);
++iPage;
var state = 'test page'+iPage;
for(var i=0; i<10; i++){
++iPage;
history.pushState(state, null, iPage+'.html'); //此时iPage=11
}
console.log('第一次push后, history记录条数: ' + history.length);
console.log('现在的location url是: ' + window.location);
console.log(history);
....
</script>
此时, 由于有for的 一直插入: history的length就增加了!
=================================================
初次进入页面的history记录条数: 2
History { length: 2, scrollRestoration: "auto", state: null }
第一次push后, history记录条数: 12
"现在的location url是: http://localhost/index.php/11.html"
History { length: 12, scrollRestoration: "auto", state: "test page1" }
- on和addEventListener,前者是要用jquery对象来调用的绑定方法, 不能用dom元素来调用; 相反的, addEventListener则是 原生的js方法, 是要用 dom元素来调用的, 不能用 jquery对象来调用. 它们刚好相反.
======================
html的4.01版本是在99年发布的,h5的正式标准是在2014年10月29日(10月的最后一天)发布的.是w3c和whatwg合作的.w3c:world wide web consortium. (con'sortium联盟,财团,联合体)是web标准的官方机构
为什么js变量名/函数名等 不用引号括起来? js内部的"字符序列"有三种情况: 可能是关键字比如if,while等, 一种是字符串,一种则可能是 变量名/函数名/以及对象内部的成员名称. js解释器是通过一些特殊的单词来识别的,比如var, function,... 所以应用起来觉得很自然,变量名是不能用引号括起来的. 否则,在使用变量的时候就非常麻烦了, 比如要访问一个对象的属性, 你还要这样写: obj."propname" ? (这个主要是要明白, js的对象其属性名, 实际上也是一种变量/变量名称, 所以严格地说, 也是不能加引号的! 比如: var obj={name: 'foo', age: 10};
js的变量名是区分大小写的! 所以JSON不能写成 Json. 而js的变量名只能包含 字母/数字/下划线/$字符(但是也有特殊的: 那就是从json字符串parse而来的对象). 变量的命名方法有 匈牙利命名法, 驼峰法(lower camel case, upper camel case),pascal命名法,而pascal命名法实际上也就是 大驼峰法.
js的对象中,包含的 属性+方法 统称为 成员.
js中用 jquery方法获得的dom 节点,就是一个对象Object,包括的属性有: length, preObject, context等.
js对象的方法只能用点号来访问, 而其属性, 有两种方法来访问, 一种是点语法, 一种是把对象看作是一个关联数组,用中括号法. 点语法和中括号法的区别:
- 点语法必须是该变量名已经存在于 对象中了, 的 "字面量",是硬编码, 而中括号可以是 变量名表示的 属性名,
- 因此, 中括号法 可以用于动态地给对象增加属性, 点语法不可以动态增加??? 点号好像也可以呢???
- 由于对象可能是由 JSON字符串转换而来的,所以js对象的 属性名中,是可以也是可能包含 一些非法字符/特殊字符,甚至是以数字打头的 变量名,这时候, 要访问其属性, 就只能使用中括号法了.
<script>
var jsonstr = '{"1name": "foo"}';
var obj = JSON.parse(jsonstr);
obj.age = 10; /// 点号也可以动态增加属性??
obj['addr'] = 'new york';
console.log(obj);
console.log(obj['1name']) ;
</script>
JSON到底是什么?
json = js object notation js对象标记法. 实质是一种: 用js对象格式的方式来标记的 一种 "字符串", 它是一种字符串.
而JSON则是js提供的一种内置的对象. 是用来操作 json字符串和js对象互相转化的.
定义json字符串时,如果外面用双引号, 那么里面的双引号要用转义: var jsonStr = "{"name": "foo"}";
否则就不是json字符串,只能算一般的普通字符串:var str ="{'name':'foo'}
json字符串要转换为js对象, 可以使用 eval方法或parse方法: var Obj = eval("(" + jsonStr + ")");
或 var Obj2 = JSON.parse(jsonStr);
js对象用 JSON.stringify(jsObj) 来转化为json字符串. 其中对象中没有json表示的值(比如函数和undefined)将会被排除.
- JSON.parse的时候, 会严格检查 要转换的字符串 是否符合JSON格式的要求 , 如果不符合则会报错
<script>
var obj={name: 'foo', age: 10, say: function(){alert()}, };
var jsonstr = JSON.stringify(obj);
console.log(jsonstr);
</script>
在tp的U 方法中, 如果要传递参数, 用array数组, 而数组中的值, 如果要输出后台变量, 这时, 后台变量 不能再用 大括号:
<a href="{:U('stcenter',array('stu' => $stut))}">个人中心</a>
这里的$stut是后台传递过来的变量, 但是在U方法中要使用它, 就不能再加{}了否则就会错误