页面常见问题
-
单屏页面,高度给100%,窗口缩小的情况下顶部内容会不显示
解决办法:给一个最小高度。 -
让一张背景图模糊,不能直接在这个div设置filter:blur(5px),如果直接给设置了背景的div元素设置模糊,那么它里面的字什么的都会变模糊
解决方法:给这个元素加一个伪元素,给这个伪元素使用模糊,这时候会有毛边,只需要定位的时候给left:-10px;right:-10px;top:-10px;bottom:-10px;把设置的宽和高去掉就可以。
<div class="cover">
你好
</div>
.cover{
position: relatvie;
}
.cover::before{
content: '',
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparent url('') center center no-repeat;
filter: blur(5px);
background-size: cover
}
或者在最大的父元素里给一个没有子元素的div,设置绝对定位,背景图片和filter
<div class="contain">
<div class="wrapper">
</div>
<div class="main">aaa</div>
</div>
.contain{
width: 400px;
height: 400px;
position: relative;
}
.wrapper{
position: absolute;
left: -10px;
top: -10px;
bottom: -10px;
right: -10px;
display:block;
background: url("http://pkl6kjvxu.bkt.clouddn.com/boy.jpg") no-repeat;
filter: blur(5px);
z-index: -4;
}
- 事件委托的使用
只有可以冒泡的事件才能使用事件委托,因为这样子元素触发事件的时候才能通知父元素(也就是点击子元素会冒泡到父元素),而不支持冒泡的事件就无法使用事件委托
jq的事件委托写法:
//on前面是需要监听的元素的父元素,后面是事件,和需要监听的元素,以及回调
$('ul').on('click','li',(e)=>{
})
4.在循环中有异步事件,如何在循环外获取最后一次异步操作的结果
比如:循环中我需要通过异步操作将每次获得的数据添加到一个数组中,这时我需要在数组外面拿到最后循环结束的结果,如果直接在循环外获取这个数组的值,因为有异步操作所以一开始拿到的会是初始的空数组,而点开这个空数组才是我们的值。
解决方法:
因为是循环也就是会有多个异步事件,所以我们需要创建多个promise,我们需要一开始声明一个promises为空的数组,然后在循环里对这个promises进行push,push里面就是你要进行的异步操作,之所以需要使用多个promise就是因为如果单纯只是使用一个基本类型的promise赋值,每次循环后面的都会把前面的覆盖掉,所以最后通过.then判断的只是最后一次的promise执行的结果,这里通过数组,把所有的promise事件都添加到数组里,然后再循环外使用Promise.all(promises).then()就可以进行循环里所有promise都执行完之后的操作了
let arr = []
let songsId = [1,2,3]
let promises = []
songsId.map(songId=>{
var song = AV.Object.createWithoutData('Song', songId);
// 修改属性
song.set('dependent', this.playlist);
// 保存到云端
promises.push(song.save().then(data=>{
//异步操作直接push进promises数组里
arr.push(data)
}))
})
Promise.all(promises)then(()={
console.log(arr)
})
5.在对dom元素重新渲染的过程中,如果dom元素是一开始就存在于页面中,那么你后期对它里面添加东西,可能不会同步更新,只能刷新页面后才可以,原因是有一部分内容存在了内存里,有一部分留在了dom里,解决方法,将需要添加的元素的父级元素也动态添加,比如通过一个template
如:
<div class="right">
<h1>已有歌单</h1>
<div class="list">
<ul class="list-main"></ul>
</div>
</div>
render(data){
let {playlists} = data
playlists.map(playlist=>{
let {id, name, summary, cover} = playlist
console.log(name)
let $li = $(`
<li>
${name}
<div class="edit">
<button class="edit-playlist">编辑专辑</button>
<button class="edit-songs">编辑歌曲</button>
<button class="delete-playlist">删除专辑</button>
</div>
</li>`).attr('data-playlist-id',id)
this.$el.find('ul').append($li)
})
}
上面的代码,比如你更改了playlists,然后重新调用了一下render,一开始是playlists:[{name:1},{name:2}],后来更改为playlists:[{name:3},{name:2}]后,你会发现dom里显示的还是1,2,但是你在上面打印的name却是最新的3,2,原因就是你的这新的ul留在了内存中,但并未在dom里,解决方法,就是让他的父级ul也动态加载,然后每次重新渲染一下它的父级
<div class="right">
<h1>已有歌单</h1>
<div class="list">
</div>
</div>
template: `
<ul class="list-main"></ul>
`,
render(data){
this.$el.find('.list').html(this.template)
let {playlists} = data
playlists.map(playlist=>{
let {id, name, summary, cover} = playlist
let $li = $(`
<li>
${name}
<div class="edit">
<button class="edit-playlist">编辑专辑</button>
<button class="edit-songs">编辑歌曲</button>
<button class="delete-playlist">删除专辑</button>
</div>
</li>`).attr('data-playlist-id',id)
this.$el.find('ul').append($li)
})
}
6.如何实现单页面里的tab栏每次刷新都定位到点击的位置,而不是初始位置?
实现方法:通过给页面url添加一个#,然后每点击一个tab栏对应的在#后面添加一个参数,每次通过location.hash来获取你#后面的内容,通过后面的参数来对应让哪一个tab里的内容显示
<div class="page tabs">
<ol class="tabs-nav">
<li data-tab-name="page-1"> <div class="text"> 推荐音乐 </div> </li>
<li data-tab-name="page-2"><div class="text">热歌榜</div></li>
<li data-tab-name="page-3"><div class="text">搜索</div></li>
</ol>
<ol class="tab-content noCollapse">
<li class="page-1 active"></li>
<li class="page-2 active"></li>
<li class="page-3 active"></li>
</ol>
</div>
{
let view = {
el: '.tabs',
$el: null,
init(){
this.$el = $(this.el)
}
}
let model = {}
let controller = {
tab: '',
init(view, model){
this.view = view
this.model = model
this.view.init()
this.locationInit()
this.bindEvent()
},
bindEvent(){
this.view.$el.find('.tabs-nav').on('click','li',(e)=>{
let $li = $(e.currentTarget)
$li.addClass('active').siblings().removeClass('active')
let tabName = $li.attr('data-tab-name')
location.href = `index.html#tab=${tabName}`
this.locationInit()
})
},
locationInit(){
let search = location.hash
if(!search){
location.href += `#tab=page-1`
}
this.tab = search.substring(1).split('=')[1]
this.positionTab()
},
positionTab(){
let tabs = ['page-1','page-2','page-3']
tabs.map(tab=>{
if(this.tab === tab){
this.view.$el.find(`.tab-content > .${tab}`).addClass('active')
this.view.$el.find(`.tabs-nav > li[data-tab-name=${tab}]`).addClass('active')
}else{
this.view.$el.find(`.tab-content > .${tab}`).removeClass('active')
this.view.$el.find(`.tabs-nav > li[data-tab-name=${tab}]`).removeClass('active')
}
})
}
}
controller.init(view, model)
}
7.对于事件监听,不管一开始有没有对应的监听事件触发,只要它执行过,后面就只要一触发对应的事件,监听里就会拿到,就像监听一个点击事件一样,一开始页面没有点击事件,但是执行了这个监听事件,后面你每次点击,他都会监听到得到相应的结果,所以在vue中你可以把所有的事件监听都写在created里,只要调用一次就可以
created(){
this.eventBus.$on('new',(data)=>{
console.log(data)
})
}
8.冒泡需要时间,当你给一个点击事件添加一个点击的事件监听的时候,你只需点击一次就可以添加这个事件监听,同时执行它
<div id="app">
<div @click="one">aaa</div>
</div>
<script>
let app = new Vue({
el: '#app',
methods: {
one(){
console.log(0)
document.addEventListener('click',()=>{
console.log(1)
})
}
}
})
</script>
上面的代码,点击一次就可以打印出0和1,具体代码执行是,当你点击aaa触发one,然后开始冒泡,因为冒泡需要时间所以接着就会打印出0,然后给document添加一个监听,之后冒泡到docuemnt,执行了这个事件监听的函数,打印出了1(也就是先监听了docuemnt后冒泡到docuemnt)。所以如果想不让第一次就执行监听里的函数,那么就要给它加一个时间,让它在冒泡后执行