如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
打电话分下面4步:
ajax也分下面4步:
下面是原生js写ajax的具体写法 :
但是,不能每次用ajax的时候都写那么多代码,要把这段ajax代码封装起来,方便使用。
封装ajax代码如下:
将封装的ajax调用:
原生js写ajax可以类比打电话
1.拿出手机
2.拨号
3.说话
4.听对方说话
1.创建ajax对象
2.连接到服务器
3.发送请求(告诉服务器我要什么文件)
4.接收返回值
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
遮罩层为一张边框样式图(如下图):
边框样式遮罩层显示在最上方,然后是中间的列表,最下层是一个透明黑色遮罩层,滚动鼠标滚轮,能控制列表滚动
注册最上面遮罩层的滚动事件,拿到滚动滚动方向,然后控制列表滚动的方向和距离
效果
实现原理
上代码
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务注册事件 /**
* 增加滚轮滚动事件(暂时只实现了chrome的滚动效果)
* @param modalDomId 遮罩层domId
* @param domId 需要滚动下层列表domId
*/ addMousewheelListener(modalDomId:string,domId:string){ //添加页面监听 let modalAwardPanel = document.getElementById(modalDomId);
modalAwardPanel.addEventListener('mousewheel',function(e){
let scrollContentDom = document.getElementById(domId); //向上滚 if (e.wheelDelta > 0){ if (scrollContentDom.scrollTop -20 >= 0){
scrollContentDom.scrollTop = scrollContentDom.scrollTop - 20;
} else{
scrollContentDom.scrollTop = 0 ;
}
} //向下滚 else{ if(scrollContentDom.scrollTop + scrollContentDom.clientHeight < scrollContentDom.scrollHeight){
scrollContentDom.scrollTop = scrollContentDom.scrollTop + 20;
}
}
});
}
组件调用: this.addMousewheelListener("你的最上方遮罩层id","你想要滚动的列表id");
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
大家都说前端写页面较多,几乎用不到算法。本文愿从弹幕设计这个场景来描述算法在前端中的应用,我们先来看下实现效果:
开场之前我们先来描述弹幕开发的难度,再集中精力描述算法设计的思路。
* 如何保证不同字号的弹幕不碰撞
***如何保证不同字号的弹幕不碰撞***
如果弹幕采用相同的字号,碰撞的问题处理起来比较简单,只要考虑相邻弹幕的播放速度和偏移的位置就可以计算出来。然而使用不同字号的弹幕处理起来就麻烦了许多,弹幕的起始位置不可以线性的增加,比如第一行放了字幕,接下来的字幕可以按顺序从上至下依次放置即可。
***弹幕的位置计算***
只有设计好弹幕的初始位置,才可以动态、的管理不同字号弹幕的碰撞问题。打个比方,我们通过接口获取了2秒之内的弹幕数据1000条,每个字幕的长度、速度、字号都不同,怎么管理这些弹幕,示意图如下:
这是第一种情况,按照从上到啊的顺序依次摆放以后会有几个问题:
一系列问题就不统统列举出来了,基于这个背景我们结合数学建模的思维方式,找到了弹幕场景相似度非常高的机场运营。我们可以把弹幕当做飞机,每个时间段播放多少弹幕和机场每个时间段放飞多少飞机一个道理。
首都国际机场一共有3条跑道,两条4E级跑道、一条4F级跑道,2016年的吞吐量为9000万人次。它的运行机制就是所有飞机通过搭台有顺序的共用3条跑道来完成运输任务的。
同理,我们也设计了几个个角色:一个是轨道(跑道)、一个是调度(塔台)、一个是弹幕(飞机),我们为每个角色设计一个类分为为Track、Main、Bullet。
* 轨道
其次我们来回忆下机场的工作流程:
按照这个思路,我们的弹幕工作流程:
关于轨道的基本原理我们整理清楚了,当然还有不少细节比如如何和调度通信、如何和弹幕通信以及虚拟轨道检测算法等。有兴趣的同学可以参考代码吧。https://github.com/bytedance/xgplayer/blob/master/packages/xgplayer/src/control/makeBullet.js
* 弹幕
在弹幕启动之后,首先要检查本地是否已有缓存数据,没有的话直接请求数据并缓存,然后执行数据读取,首次过滤数据进入弹幕队列,同时启动定时器。弹幕队列的数据会定期请求轨道,检测队列里的弹幕是否可以进入,一旦确认后轨道做好登记,弹幕就可以进入播放器开启动画播放了。定时器每隔2秒就会再次更新数据进入到弹幕队列(这块不同的业务可以定制不同的规则)。弹幕播放结束后会通知调度和轨道,调度会在弹幕队列中移除该弹幕实例,轨道也会移除该弹幕实例的轨道占用。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
图1.1 弹幕效果
* 弹幕的位置计算
* 弹幕的速度控制及动画实现
* 弹幕与视频的同步
图2.1 弹幕管理示意图
1. 弹幕五、六、七该怎么计算位置,按top值循环取模+累加吗?
2. 当弹幕一或者弹幕三足够长的时候,如何准时的跳过当前位置计算?
3. 当前屏幕的弹幕播放结束,如何再计算的时候利用空出来的位置
4. 空出的位置是否满足当前弹幕的高度
5. ……
轨道这个角色很重要,它可以解决弹幕位置计算、速度控制、碰撞检测问题。
首先,我们要来初始化轨道。通俗的说我们要修建几个跑道呢,我们不是实物,可以动态调整轨道的 数量,计算的原则:
轨道数量 = 播放器有效高度 / 设备基准字号
* 播放器有效高度:播放器的实际高度减去控制条的高度,因为弹幕不可以遮挡控制条。
* 设备基准字号:移动端是10px,pc端是12px;
为啥计算公式是这样的?因为我们要支持不同字号的弹幕。试想不同的字号对物理空间的占用是不同的,然而如果要求轨道的尺寸是动态的,那就带来很复杂的计算。本文提出“虚拟轨道”的概念,在交通管制中最常见的就是道路合并或者改向。我们也是采用将相邻的物理轨道临时合并为一条轨道。这样就可以轻松的解决不同字号的轨道占用问题。原理图如下:
图2.2 轨道计算示意图
1. 机长呼叫塔台,CZ6132请求起飞
* 目前跑道均被占用,请等待
* N时刻后再次执行步骤1
* 目前跑道 A1 空闲,准许进入
* 执行步骤3
2. 塔台查看跑道使用情况
3. 进入跑道,起飞完成
4. 机长通知塔台,本次起飞完成,释放跑道的占用
5. 其他飞机同样执行上述步骤
1. 弹幕进入播放器
2. 轨道根据弹幕的播放速度、尺寸计算是否有合适的轨道提供
* 没有
* 通知弹幕尚无合适轨道提供,请等待;同时,弹幕队列中的其他弹幕依次执行步骤1
* 有
* 执行步骤3
3. 播放器加载弹幕DOM,开始播放,待播放完成
4. 播放完成通知轨道更新轨道占用情况
5. 其他弹幕同样执行上述步骤
图2.3 轨道可用性计算示意图
弹幕基本是实现“飞机”的角色,我们要求它具有自身的属性和方法。比如调度中心通过id能拿到它所有的基本信息,轨道控制也可以通过弹幕进行检查和更新。当然弹幕也必须具备状态自动更新、移动、播放结束通知、自动销毁等功能。
* 调度
调度就是搭台的化身,承接着轨道、弹幕的控制,也保持着与播放器的步调一致。它的职责如下:
1. 播放器交互控制
2. 弹幕队列控制
3. 自身状态更新
4. 数据格式转换
5. 动画执行
还是直接用流程图来描述更直接些:
图2.4 弹幕运行机制流程图
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
一.写在前面
1.为什么要学小程序开发?
对于前端开发而言,微信小程序因为其简单快速、开发成本低、用户流量巨大等特点,也就成了前端开发工程师必会的一个技能。
2.开发准备:
(1)有人开玩笑说,会vue小程序根本都不用学:
微信小程序虽然是腾讯自己搞的,但是核心的思想跟vue等框架是一样一样的哦~
(2)善于搜集精美的小组件: “我们不生产代码,我们只是代码的搬运工”,善于找到想要的组件并把他们巧妙优雅的组装成一个大项目,也算是程序员一项基本技能了。
具体怎么找到想要的小程序demo,篇末会给大家推荐小程序的资源,有很多大神的项目哦
撸起袖子开干了
一.注册小程序账号,下载IDE
1.官网注册https://mp.weixin.qq.com/,并下载IDE。
2.官方文档一向都是最好的学习资料。
注意:
(1)注册账号之后会有一个appid,新建项目的时候需要填上,不然很多功能是用不了的,比如不能预览,不能上传代码等等。
(2)如果你注册过微信公众号的话,一定要注意,微信公众号和小程序是两个账号,二者的appid也是不同,小程序开发必须使用小程序的appid哦。
二.小程序框架介绍和运行机制
1.我们建立了“普通快速启动模板”,然后整个项目目录如下:
2.app.js
整个项目的启动文件,如注释写的onlaunch方法有三大功能,浏览器缓存进行存和取数据;用登陆成功的回调;获取用户信息。
globalData是定义整个项目的全局变量或者常量哦。
3.app.json
整个项目的配置文件,比如注册页面,配置tab页,设置整个项目的样式,页面标题等等;
!注意:小程序启动默认的第一个页面,就是app.json的pages中的第一个页面哦。
4.pages
小程序的页面组件,有几个页面就会有几个子文件夹。比如快速启动模板,就有两个页面,index和logs
5.打开index目录
可以看到有三个文件,其实和我们web开发的文件是一一对应的。
index.wxml对应index.html;
index.wxss对应index.css;
index.js就是js文件哦。
一般我们还会给每个页面组件添加一个.json文件,作为该页面组件的配置文件,设置页面标题等功能
6.双击index.js文件
(1)var app = getApp();
引入整个项目的app.js文件,用来取期中的公共变量等信息。
如果要使用util.js工具库中的某个方法,在util.js中module.exports导出,然后在需要的页面中require即可得到哦。
(2)比如,我们要获取豆瓣电影的时候,我们需要调用豆瓣的api;我们先在app.js中的gloabData中定义doubanBase
然后在index.js中使用app.globaData.doubanBase即可取到这个值。
当然这些常量你也可以在页面需要的时候,再用写死的值,但是为了整个项目的维护,还是建议把这种公用参数统一写在配置文件中哦。
(3)接下来在整个page({})中,第一个data,就是本页面组件的内部数据,会渲染到该页面的wxml文件中,类似于vue、react哦~
通过setData修改data数据,驱动页面渲染
(4)一些生命周期函数
比如onload(), onready(), onshow(), onhide()等等,监听页面加载、页面初次渲染、页面显示、页面隐藏等等
更多的可以查官网API哦。其中用的最多的就是onload()方法,和onShareAppMessage()方法(设置页面分享的信息)
7 .wxml模板的使用。
比如本项目电影页面,就是以最小的星级评价组件wxml当做模板,star到movie到movie-list,一级一级的嵌套使用。
star-template.wxml页面写好name属性;然后import引入的时候通过name获得即可
8.常用的wxml标签
view,text,icon,swiper,block,scroll-view等等,这些标签直接查官网文档即可
三.小程序框架、各个页面以及发布上线的注意点
1.整个框架中的一些注意点
(1)整个wxml页面,最底层的标签是哦。
(2) 每个页面顶部导航栏的颜色,title在本页面的json中配置,如果没有配置的话,取app.json中的总配置哦。
(3)json中不能写注释哦,不然会报错的。
(4)路由相关
1)使用wx.SwitchTab跳转tab页的话,在app.json中除了注册pages页面,还需要在tabBar中注册tab页,才能生效哦。
注意:tab最多5个,也就是我们说的头部或者底部最多5个菜单。其他的页面只能通过其他路由方法打开哦。
2)navigateTo是跳到某个非tab页,比如欢迎页,电影详情页,城市选择页;在app.json中注册后,不能在tabBar里注册哦,不然同样也是不能跳转的哦。
3)reLaunch跳转,新开的页面左上角是没有退回按钮的,本项目只用了一次,切换城市的时候哦。
(5)页面之间传递参数
参数写在跳转的url之中,然后另一个页面在onload方法中的传参option接收到。如下传递和获取id
(6)data-开头的自定义属性的使用
比如wxml中我们怎么写
点击的事件对象可以这么取,var postId = event.currentTarget.dataset.postid;
注意: 大写会转换成小写,带_符号会转成驼峰形式
(7)事件对象event,event.target和event.currentTarget的区别:
target指的是当前点击的组件 和currentTarget 指的是事件捕获的组件。
比如,轮播图组件,点击事件应该要绑定到swiper上,这样才能监控任意一张图片是否被点击,
这时target这里指的是image(因为点击的是图片),而currentTarget指的是swiper(因为绑定点击事件在swiper上)
(8)使用免费的网络接口:
本项目中用到了 和风天气api,腾讯地图api,百度地图api,豆瓣电影api,聚合头条新闻api等,具体用法可以看各自官网的接口文档哦,很详细的
注意:免费接口是有访问限制的,所以如果用别人的组件用了这种接口的话,最好还是自己注册一个新的key替换上哦
附上一个免费接口大全:
https://github.com/jokermonn/-Api
!!另外还要注意,要把这些接口的域名配置到小程序的合法域名中,不然也是访问不了的
(8)wxss有一个坑:无法读取本地资源,比如背景图片用本地就会报错哦。
把本地图片弄成网络图片的几种方式: 上传到个人网站;QQ空间相册等等也是可以的哦
2.切换城市页面:
(1)首页使用navigateTo跳转到切换城市页,由于首页并没有关闭,导致切换了城市返回来,天气信息还是旧的。
正确的处理逻辑如下:
1)使用reLaunch跳转到切换城市页面,实质是关闭所有页面打开新的页面哦。
2)切换城市页面,更新公共变量中城市信息为手动切换的城区,再switchTab回到首页,触发首页重新加载。
3)首页获取城市信息的时候加一个判断,全局没有才取定位的,全局有(比如刚才设置了)就用全局的哦。
(2)城市列表的滚动和回到顶部
基于scroll-view组件的scroll-top属性,初始就是0,滚动就会增加的;点击回到顶部给它置为0即可回到顶部
3.天气页
(1)初始化页面,天气显示的逻辑
首先调用小程序的wx.getLocation方法获得当前的经纬度,然后调用腾讯地图获得当前的城市名称和区县名称,并存到公共变量中,
再调用查询天气和空气质量的方法哦。
(2)容错处理
城市的名称长短不一,有点名字特别长,比如巴彦淖尔市这种,需要动态的获取完整的城市名称;
有些偏僻的城市暂时没有天气信息,我们需要对返回的结果进行判断,没有信息的需要给用户一个良好的提示信息。
4.周边-地图服务页面
(1)调用百度地图的各种服务,查询酒店,美食,生活服务三种信息,更多信息可以看百度地图的文档
(2)点击时给被点中的图标加个边框,数据驱动视图,所以使用一个长度为3的数组保存三个图标当前是否被点中的状态
然后wxml再根据数据来动态添加class,增加边框样式
5.豆瓣电影页
(1)电影详情页的预览图片,用小程序本身的previewImage实现。
(2)详情页使用onReachBottom()方法,监控用户上拉触底事件,然后发送请求继续获得数据,实现懒加载的效果
(3)用户体验方面的优化,js中将整数评分比如7分统一改为7.0分,然后wxml模板再判断分数是否为0显示“暂无评分”
(4)搜索之后清空搜索框
因为小程序中不能使用getelementbyId这种方式获得元素,只能用数据来控制了
在data中加一个属性searchText来保存搜索框的内容并和 input的value属性绑定,搜索完成或者点击X时,searchText变量清空即可实现清空输入框的效果哦。
6.新闻页面
(1)聚合头条新闻的免费接口,只返回了新闻的基本信息,新闻的主体内容是没有的哦。
我找了好多新闻类的接口,好像都是没有新闻主体内容的。如果谁知道更好的接口欢迎留言告诉我哈~
(2)当然,也可以自己去爬新闻网站的数据哦
7.更多页面
(1)小程序目前开放外链的功能只是给公司组织的小程序开放了,个人开发还是不能使用外链的哦。
(2)彩蛋页面,获得用户信息
通过 wx.setStorageSync('userInfos', userInfos); 可以获得登陆小程序的用户的个人信息,可以发送给后台存到数据库中,方便对用户进行分析
我这里只是存储到浏览器缓存中哦,最大应该是10M缓存;如果用户把这个小程序从小程序列表中删除掉,就会清空这个缓存。
8.发布注意
(1) 新版本小程序发布的限制为2M,一般都是图片最占空间,所以尽量使用网络图片
具体怎么把本地图片变成网络图片,上面有讲哦。
(2)在开发者工具上预览测试没问题,点击上传;网页版小程序个的人中心的左侧“开发管理”菜单,第三块--开发版本就有了内容。
(3)点击提交,填写小程序相关信息,就可以提交审核了哦。
注意:分类最好填写准确,这样才能更快的通过审核哦。我这个小程序一天半时间过审上线的
至此,我就把两天开发内碰到的坑和注意点都过了一遍,据说还有更多的坑,等之后更深入的开发再继续研究咯。
小程序学习资料
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
mongoose保存数据:
如果成功,则可以获取到保存在数据库的值,但是如果保存数据失败,则会抛出异常,好在save可以传入一个回调函数,用法如下:
我们希望根据结果获取到不同的值,但是此时save返回的是undefined,因为save中的回调函数是一个异步操作
使用try catch:
注意:在async函数中才可以这么使用,因为await只能用在async函数中
示例:(注册功能)
user.model.js
service.js
controller.js
const save = new Model(data).save()
const save = new Model(data).save((err, result)=>{ if(err){ // 保存失败执行的操作
}else { // 保存成功执行的操作
}
})
解决方法:
try{
const save = await new Model(data).save();
// 保存成功执行的操作 return ... }catch(err){
// 保存失败执行的操作 return ... }
const mongoose = require("mongoose"); const port = process.env.PORT || "8899"; const UserSchema = mongoose.Schema({
userName: {
type: String,
unique: true },
passWord: String,
createTime: {
type: Date, default: Date.now()
},
updateTime: {
type: Date, default: Date.now()
}
}, {
timestamps: {
createAt: "createTime",
updateTime: "updateTime" }
});
module.exports = mongoose.model("USER", UserSchema);
const User = require("./user.model);
class User{
async login(user){
try{
const result = await new User(user).save();
// 其他操作,如发送注册邮件
return { success: true }
}catch(err){
return { success: false, message: "用户名或密码错误" }
}
}
}
moduel.exports = new User();
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务const server = require("./server); async login(){ // 首先获取请求中携带的用户信息 const result = await server.login(user);
if(result.success){ // 注册成功执行的操作 }else { // 注册失败执行的操作 }
}
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
图片标签<img src=路径属性 alt:加载失败后显示的文本 width:指定图片宽度 height:指定图片高度> 单位: px
绝对路径
同级:直接写文件名.后缀名
<br>标签:换行 <img>标签为内联标签所以不换行,所以添加<br>标签换行。
页面是这样的:
图片标签
路径属性
E:\ruanjian\软件\环境\images
相对路径:相对于主文件位置的路径
引用文件方式:
上级:../文件名.后缀名 ../返回上一级文件夹
下级:文件夹/文件名.后缀名
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
@(Mob前端-冬晨)[JavaScript|技术分享|懒加载]
前端工作中,界面和效果正在变得越来越狂拽炫酷,与此同时性能也是不得不提的问题。有些项目,页面长,图片多,内容丰富。像商城页面。如果同步加载时一次性加载完毕,那肯定是要等到花都谢了,loading转的人都崩溃~。今天分享的是Lazyload技术 是一种延迟加载技术。让页面加载速度快到飞起、减轻服务器压力、节约流量、提升用户体验。
页面较长,屏幕的可视区域有限。
简要流程
.
不做任何处理直接监听scroll必然导致在滚动鼠标滚轮的时候,过于频繁的触发处理函数。
使用节流函数
滚动时间
结语:历史潮流浩浩荡荡,前端技术的发展也是日新月异。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
前端性能优化之Lazyload
Lazyload 简介
一、实现思路
不设置页面中img标签
的src属性
值或者将其指向同一个占位图。
图片的实际地址存在img标签
自定义的一个属性中,如:“data-url”。
监听scroll
,滚动到某个位置时,动态的将url替换成实际的“data-url”。
二、上代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Lazyload</title> <style type="text/css"> .mob-wrap li{list-style: none;width: 100%;height: 345px;} </style> </head> <body> <ul class="mob-wrap"> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/sharesdk-logo.jpg"><p>ShareSDK轻松实现社会化功能</p> </li> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/sms-logo.jpg"><p>短信验证码SDK</p> </li> <li"> <img class="tamp-img" alt="loading" data-src="http://mob.com/public/images/index/rec-logo.jpg"><p>MobLink实现Web与App的无缝链接</p> </li> </ul> </body> </html>
var aImg = [
{"src":"http://mob.com/public/images/index/sharesdk-logo.jpg","txt":"ShareSDK轻松实现社会化功能"},
{"src":"http://mob.com/public/images/index/sms-logo.jpg","txt":"短信验证码SDK"},
{"src":"http://mob.com/public/images/index/rec-logo.jpg","txt":"MobLink实现Web与App的无缝链接"}
]; var sLi = '';
document.getElementsByClassName("mob-wrap")[0].innerHTML=""; for(let i = 0;i<10;i++){
sLi = document.createElement("li");
sLi.innerHTML = `<img class="tamp-img" alt="loading" src="./zwt.gif" data-src="${aImg[i%3].src}"><p>${aImg[i%3].txt}</p>`;
document.getElementsByClassName("mob-wrap")[0].appendChild(sLi);
};
window.onscroll = function () {
var bodyScrollHeight = document.documentElement.scrollTop;// body滚动高度
var windowHeight = window.innerHeight;// 视窗高度
var imgs = document.getElementsByClassName('tamp-img');
for (var i =0; i < imgs.length; i++) { var imgHeight = imgs[i].offsetTop;// 图片距离顶部高度 if (imgHeight < windowHeight + bodyScrollHeight - 340) { imgs[i].src = imgs[i].getAttribute('data-src'); imgs[i].className = imgs[i].className.replace('tamp-img','');
}
}
};
.
.
谢谢观看,搞定收工0.0~~~这样草草了事总是不好的
三、再优化
如果刚巧在处理函数中有大量的操作dom等消耗性能的行为,引发大量操作,导致页面变卡变慢,
甚至浏览器崩溃无响应。
处理这种问题的思路是节流和防抖。
节流函数的概念有一个很形象的比喻:在接咖啡的时候,按了一次按钮会出咖啡,
紧跟着再按几次按钮接到的还是那一杯咖啡,相当于后面几次按的没有起作用。
常规的节流在这里就不多说了,下面介绍的是一种每隔least
时间内至少执行一次的节流函数。
//节流函数 _throttle = (fn, delay, least) => { var timeout = null,
startTime = new Date();
fn(); return function() { var curTime = new Date();
clearTimeout(timeout); if(curTime - startTime >= least) {
fn();
startTime = curTime;
}else {
timeout = setTimeout(fn, delay);
}
}
}
function compare () { var bodyScrollHeight = document.documentElement.scrollTop;// body滚动高度 console.log(bodyScrollHeight+"替换src方法") var windowHeight = window.innerHeight;// 视窗高度 var imgs = document.getElementsByClassName('tamp-img'); for (var i =0; i < imgs.length; i++) { var imgHeight = imgs[i].offsetTop;// 图片距离顶部高度 if (imgHeight < windowHeight + bodyScrollHeight - 340) {
imgs[i].src = imgs[i].getAttribute('data-src');
imgs[i].className = imgs[i].className.replace('tamp-img','');
}
}
}
window.onscroll = _throttle(compare, 350,600);
least
长于600,调用compare,否则延迟350ms执行。
这样相对于直接onscroll性能得到更进一步提升,在功能上也没有什么问题。
不同的业务场景调整一下delay和least就可以。
不断通过一个个小的技术点深入探究,以加深自己对js这门语言的理解。
温故知新,回顾旧的内容,学习新的内容和特性,更好的适应工作中的需求。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
关于跨浏览器问题一直是一个大问题, 所以我决定在此做一个记录, 当然不可能把跨浏览器问题一下子都搞定, 所以该文章将是一个长期的过程, 当coding时遇到了, 就会完善该文。
关于xhr对象, ie7需要之前的需要使用ActiveXObject对象来实现, 而且存在三个不同的版本。 虽然现在已经不用兼容ie7以前的浏览器了, 还是可以了解一下:
//最终版本
写在前面的话
添加事件
var EventUtil = { /*
*添加事件
*/ addHandler: function(element, type, handler) { if(element.addEventListener){ element.addEventListener(type, handler, false)
}else if(element.attachEvent){ element.attachEvent('on'+type, handler)
}else{ element['on'+type] = handler
}
}, /*
*删除事件
*/ removeHandler: function(element, type, handler){ if(element.removeEventListener){ element.removeEventListener(type, handler, false)
}else if(element.detachEvent){ element.detachEvent('on'+type, handler)
}else { element['on'+type] = null }
}, /*
*获得事件对象
*/ getEvent: function(event){ return event ? event : window.event //ie浏览器的事件对象是window对象的属性, 所以需要window.event来获取。 }, /*
*获得事件对象的事件目标(触发事件的事件目标)
*/ getTarget: function(event){ return event.target || event.srcElement //这是||符号的另一种用法, 遇到true就返回。 }, /*
*阻止默认事件
*/ preventDefault: function(event){ if(event.preventDefault){
event.preventDefault
}else{
event.returnValue = false }
}, /*
*阻止事件冒泡
*/ stopPropagation: function(event){ if(event.stopPropagation){
event.stopPropagation()
}else {
event.cancelBubble = true }
}
} // stopPropagation()方法既可以阻止事件冒泡,也可以阻止事件捕获,也可以阻止处于目标阶段。
ajax事件
//适用于IE7之前的版本
function createXHR(){ if(typeof arguments.callee.activeXString != 'string'){ var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
i,
len; for(i = 0; len = version.length; i++){ try{ new ActiveXObject(veersions[i]); arguments.callee.activeXString = versions[i] break }catch(ex){ //跳过 }
}
} return new ActiveXObject(arguments.callee.activeXString)
}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务function createXHR(){ if(typeof XMLHttpRequest != 'undefined'){ return new XMLHttpRequest()
}else if(typeof ActiveXObject != 'undefined'){ if(typeof arguments.callee.activeXString != 'string'){ var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp'],
i,
len; for(i = 0; len = version.length; i++){ try{ new ActiveXObject(veersions[i]); arguments.callee.activeXString = versions[i] break }catch(ex){ //跳过 }
}
} return new ActiveXObject(arguments.callee.activeXString)
}else { throw new Error("NO XHR object availabel")
}
}
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
伪类和伪元素就是为文档中不一定存在的结构指定样式,或者为某些元素(甚至文档本身)的状态所指示的幻象类指定样式。css引入伪类和伪元素概念是为了格式化文档树以外的信息。
伪类的形式:选择符: 伪类{ 属性:属性值 }
伪元素的形式:选择符:: 伪元素{ 属性:属性值 }
CSS3规范中要求使用双冒号(::)表示伪元素,以此来区分伪元素和伪类。
a:link{…} //指向未访问的链接
a:visited{…} //指向已访问的链接
E:hover{…} //元素上有鼠标指针停留
E:active{…} //元素被用户输入激活
E:focus{…} //元素拥有输入焦点
伪类的顺序很重要,一般为link-visited-focus-hover-active。动态伪类可以应用到任何元素,可以为用户提供一种“强调”的作用。
E:first-child{…}
为父元素(可以body,div,ul,ol等)中的第一个子元素E元素设置样式,注意,E必须是父元素中的第一个子元素。
E:lang(value)
为E元素中lang属性为value的元素设置属性。相当于E[lang |= “value”]。
a:link:hover{…}//鼠标停留在未访问的链接上
a:visited:hover{…}//鼠标停留在已访问的链接上
在文档中插入假想元素,导致用户代理对一个假想元素做出响应。
p:first-letter{…} //设置首字母样式,为p块级元素第一个元素设置样式
p:first-line{…} //设置第一行的样式,为p块级元素第一个元素设置样式
所有伪元素都必须放在出现该伪元素的选择器的最后面。
E:before {content:”…”}
E:after {content:”…”}
注:关于伪类和伪元素,我的理解并不是很深,不过掌握上面的这些内容,我想也是够用了。以上内容大部分是《CSS权威指南》中内容,总结了一下方便记忆。关于伪类和伪元素的内容,这里有一个不错的文章,下面是这篇文章的链接:http://www.alloyteam.com/2016/05/summary-of-pseudo-classes-and-pseudo-elements/#prettyPhoto 下面的内容引自这篇文章,可以补充上面的内容,贴在这里方便自己日后查阅。
定义:
链接伪类
动态伪类
结合伪类
伪元素选择器
设置之前和之后元素的样式
伪类与伪元素的具体用法
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
说一下vue的声明周期:
vue 的生命周期11个钩子函数是按照以下的顺序来的 :(不可逆转哦,第11个除外)
如,写一个子组件,然后挂在到父组件,在子组件中,console.log 子组件中的
.
二. vue启动前后
这两个的意思就是,
当
可以获取
.
三. 组件更新前后
这个就不用我多说了吧?当子组件里面的
再点一次
四. 组件销毁前后(一般配合
给这个子组件用
所以
五. 组件激活时,未激活时
这两个钩子函数呢一般配合
这时候我们就可以用
说一下
六. 当捕获一个来自子孙组件的错误时被调用
当子孙组件报错的时候,父组件会触发这个钩子函数,并且会返回三个参数,
具体第11个没深入研究,喜欢的可以去看下官网的 errorCaptured。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
一. 组件创建前后
1.beforeCreate
2.created
data(){ return { a:1 },
beforeCreate(){
console.log(this.a)//undefined },
created(){
console.log(this.a)//1 }
}
.
3.beforeMount 4.mounted
vue在beforeMount
时,还不管事,也就是说,还没有渲染数据到<div id="app"><div/>
里面,此时的这个组件还是空的
mounted
时,才会往<div id="app"><div/>
添加东西,也就是vue正式
接管<div id="app"><div/>
#app
的innerHTML查看差异;
beforeMount(){ console.log(document.getElementById('app').innerHTML)//空的
},
mounted(){ console.log(document.getElementById('app').innerHTML)//#app里的内容 }
.
5.beforeUpdate 6.updated
视图改变
的时候触发。
如,做一个按钮,让data
里面的a
++,假如 一开始a是1
beforeUpdate
返回1
updated
返回2
beforeUpdate(){
console.log(document.getElementById('a').innerHTML)//1 },
updated(){
console.log(document.getElementById('a').innerHTML)//2 }
beforeUpdate
返回2
updated
返回3。。。
.
.
v-if
使用)
7.beforeDestroy
8.destroyed
v-if
来控制它的销毁和创建,注意以下:v-show
不行。
子组件销毁前触发beforeDestroy
子组件销毁后触发destroyed
第一次会触发7.8.
创建子组件后会触发以上的第1.2.3.4.钩子函数。
有一个问题,如果我们在子组件里写一个定时器,然后,子组件被销毁了,定时器还会执行吗?
答案是会的
所以这时候就会用到了destroyed
,在组件被销毁后,我们把定时器给清除就好了。
这两个钩子函数一般用于做性能的优化。
.
.
9.activated
10.deactivated
<keep-alive><keep-alive/>
来使用。
通过看 四。这个例子,你肯定知道了一个组件怎么被销毁和创建。
但是我们知道通常一个组件是很大的,如果我们总是一直创建、销毁、创建、销毁。。。这样很不合理,而且很浪费性能。。。
<keep-alive><keep-alive/>
配合着两个钩子函数来控制组件的激活和不激活。
<keep-alive><keep-alive/>
,它就相当于把你的组件给缓存下来了,目的呢就是不让组件重复的渲染
,然后我们通过v-if
触发,子组件就不会再触发7 和 8 了,而是只会频繁的触发9 和 10
这样性能会比7 和 8 好的多。
.
.
11.errorCaptured
第一个参数是 错误对象
第二个参数是 报错的子孙组件
第三个参数是 报错的子孙组件的具体哪个地方报错。(如,假如我没有定义b这个变量,但是我去console.log(b) 这一句肯定会报错,假如我把这句错误代码写在了created这个钩子函数里,那第三个参数会返回就是:created hook
)
蓝蓝设计的小编 http://www.lanlanwork.com