Skip to content

Commit

Permalink
解决resize后, 宽度获取不正确的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
dream2023 committed Apr 30, 2019
1 parent 46e36f2 commit 1b74ad1
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 66 deletions.
37 changes: 35 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,51 @@
<code>vue-affix</code>, 但是其必须指定相对元素, 而不可以默认跟随window, 所以和我的需求略微不同, 就动手做了一个。
</p>

## 文档和示例

[https://dream2023.github.io/easy-affix/](https://dream2023.github.io/easy-affix/)

## 安装

```bash
npm install easy-affix --save
```

## 文档和示例
## 使用

[https://dream2023.github.io/easy-affix/](https://dream2023.github.io/easy-affix/)
```js
// 局部引入
import Affix from 'easy-affix'
export default {
components: {
Affix
}
}
```

```js
// 全局引入
import Affix from 'easy-affix'
Vue.component('affix', Affix)
```

## Props 参数

```html
<!-- 基本用法 -->
<affix>内容....</affix>
```

```html
<!-- 可以指定偏移距离 -->
<affix :offset="50">当距离顶部50px时, 开始绝对定位...</affix>
```

```html
<!-- 相对于窗口底部偏移 -->
<affix type="bottom">内容....</affix>
```

```js
props: {
// 类型(仅能为bottom 和 top)
Expand Down
24 changes: 20 additions & 4 deletions documentation/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,26 @@
</section>
<section id="usage">
<h2>使用</h2>
<blockquote>
<pre class="language-js"><code class="language-js">// 局部引入
import Affix from 'easy-affix'
export default {
components: {
Affix
}
}</code></pre>
</blockquote>
<blockquote>
<pre class="language-js"><code class="language-js">// 全局引入
import Affix from 'easy-affix'
Vue.component('affix', Affix)
</code></pre>
</blockquote>
</section>

<section id="props">
<h2>Props参数</h2>

<p>左侧导航栏使用了最基本的形式:</p>
<blockquote>
<pre class="language-html"><code class="language-html">&lt;affix&gt;导航栏...&lt;/affix&gt;</code></pre>
Expand All @@ -41,10 +61,6 @@
<blockquote>
<pre class="language-html"><code class="language-html">&lt;affix&nbsp;type="bottom"&gt;相对于底部而言&lt;/affix></code></pre>
</blockquote>
</section>

<section id="props">
<h2>Props参数</h2>
<blockquote>
<pre class="language-js">
<code class="language-js">
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=1000, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- <script src="./prism.js"></script> -->
<script src="../dist/easy-affix.umd.min.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>easy-affix</title>
Expand Down
91 changes: 44 additions & 47 deletions src/Affix.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<template>
<div
:style="styles"
ref="wrapper"
>
<slot/>
<div>
<!-- 为了正确获取到宽度, 所以嵌套了一层 -->
<div
:style="styles"
ref="wrapper"
>
<slot/>
</div>
</div>
</template>

Expand Down Expand Up @@ -44,9 +47,11 @@ export default {
},
data () {
return {
throttled: null,
isAffix: false,
scrollDistance: 0,
winHeight: 0,
styles: {},
elOffsetPageTop: 0
}
},
Expand Down Expand Up @@ -76,21 +81,6 @@ export default {
} else {
return null
}
},
// 样式
styles () {
if (this.isAffix && this.enabled) {
const elRect = this.elRect
return {
position: 'fixed',
zIndex: this.zIndex,
left: elRect.left + 'px',
width: elRect.width + 'px',
[this.type]: this.offset + 'px'
}
} else {
return {}
}
}
},
mounted () {
Expand All @@ -101,33 +91,22 @@ export default {
this.elOffsetPageTop = this.getElOffsetPageTop()
// 事件节流(因为不需要页面响应式, 所以没有在data中设置)
this.scrollFn = throttle(this.delay, () => {
this.updateScrollDistance()
})
this.resizeFn = throttle(this.delay, () => {
this.updateWinHeight()
this.throttled = throttle(this.delay, () => {
this.handleChange()
})
// 初始化时需要执行一次
this.updateScrollDistance()
this.updateWinHeight()
this.handleChange()
// 开启事件监听
window.addEventListener('scroll', this.scrollFn, false)
window.addEventListener('resize', this.resizeFn, false)
this.startListen()
})
}
},
beforeDestroy () {
this.stopListen()
},
watch: {
scrollDistance () {
this.handleChange()
},
winHeight () {
this.handleChange()
},
enabled (value) {
if (value === false) {
this.stopListen()
Expand All @@ -147,18 +126,11 @@ export default {
return selfTop + scrollDistance - this.offsetTop - clientTop
},
// 更新滚动距离
updateScrollDistance () {
this.scrollDistance = window.pageYOffset || document.documentElement.scrollTop
},
// 窗口高度
updateWinHeight () {
this.winHeight = window.innerHeight
},
// 检测变化
handleChange () {
this.winHeight = window.innerHeight
this.scrollDistance = window.pageYOffset || document.documentElement.scrollTop
const isAffix = this.isAffix
if (this.type === 'top') {
if (!isAffix && this.scrollDistance >= this.elOffsetPageTop) {
Expand All @@ -179,12 +151,37 @@ export default {
this.isAffix = false
}
}
// 设置样式
this.setStyles()
},
// 设置样式
setStyles () {
let styles = {}
if (this.isAffix && this.enabled) {
const elRect = this.elRect
styles = {
position: 'fixed',
zIndex: this.zIndex,
left: elRect.left + 'px',
width: this.$el.offsetWidth + 'px',
[this.type]: this.offset + 'px'
}
}
this.styles = styles
},
// 开启事件监听
startListen () {
window.addEventListener('scroll', this.throttled, false)
window.addEventListener('resize', this.throttled, false)
},
// 删除事件监听
stopListen () {
window.removeEventListener('scroll', this.scrollFn, false)
window.removeEventListener('resize', this.resizeFn, false)
window.removeEventListener('scroll', this.throttled, false)
window.removeEventListener('resize', this.throttled, false)
}
}
}
Expand Down
12 changes: 0 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
import Affix from './Affix'

const Plugin = {}

Plugin.install = Vue => {
if (Plugin.install.installed) return

Vue.component('affix', Affix)
}

if (typeof window !== 'undefined' && window.Vue) {
Plugin.install(window.Vue)
}

export default Affix

0 comments on commit 1b74ad1

Please sign in to comment.