Browse Source

feat: backtop

“liqiong-lab” 5 years ago
parent
commit
fc27e3a8ae

+ 49 - 0
src/packages/backtop/demo.vue

@@ -0,0 +1,49 @@
+<template>
+  <div class="demo" id="elId" ref="scroll">
+    <div class="text-data">我是测试数据1</div>
+    <div class="text-data">我是测试数据2</div>
+    <div class="text-data">我是测试数据3</div>
+    <div class="text-data">我是测试数据4</div>
+    <div class="text-data">我是测试数据5</div>
+    <div class="text-data">我是测试数据6</div>
+    <div class="text-data">我是测试数据7</div>
+    <div class="text-data">我是测试数据8</div>
+    <div class="text-data">我是测试数据9</div>
+    <div class="text-data">我是测试数据10</div>
+    <div class="text-data">我是测试数据11</div>
+    <div class="text-data">我是测试数据12</div>
+    <div class="text-data">我是测试数据13</div>
+    <div class="text-data">我是测试数据14</div>
+    <div class="text-data">我是测试数据15</div>
+    <div class="text-data">我是测试数据16</div>
+    <div class="text-data">我是测试数据17</div>
+    <div class="text-data">我是测试数据18</div>
+    <div class="text-data">我是测试数据19</div>
+    <div class="text-data">我是测试数据20</div>
+    <div class="text-data">我是测试数据21</div>
+    <div class="text-data">我是测试数据22</div>
+    <div class="text-data">我是测试数据23</div>
+    <div class="text-data">我是测试数据24</div>
+    <nut-backtop @click="handleClick" elId="elId" :distance="100" :bottom="90"><view>无</view></nut-backtop>
+    <nut-backtop @click="handleClick" elId="elId" :distance="200"></nut-backtop>
+  </div>
+</template>
+
+<script>
+import { createComponent } from '@/utils/create';
+const { createDemo } = createComponent('backtop');
+
+export default createDemo({
+  setup(props, { emit }) {
+    const handleClick = () => {
+      console.log('触发回到顶部');
+    };
+
+    return {
+      handleClick
+    };
+  }
+});
+</script>
+
+<style scoped></style>

+ 82 - 0
src/packages/backtop/doc.md

@@ -0,0 +1,82 @@
+# BackTop 回到顶部
+
+### 介绍
+
+提供较长的页面快捷回到顶部功能。
+
+### 安装
+
+```javascript
+
+import { createApp } from 'vue';
+import { BackTop } from '@nutui/nutui';
+
+const app = createApp();
+app.use(BackTop);
+
+```
+
+### 代码实例
+
+### 基本用法
+
+```html
+    <nut-backtop  elId="elId" ></nut-backtop>
+```
+
+### 设置出现位置
+
+```html
+    <nut-backtop :distance="200" ></nut-backtop>
+```
+
+### 自定义样式
+
+```html
+    <nut-backtop @click="handleClick" elId="elId" :distance="100" :bottom="90" ><div>无</div></nut-backtop>
+```
+
+### 设置样式
+<nut-backtop>
+</nut-backtop>
+
+
+### click事件
+
+```html
+    <nut-backtop @click="handleClick" ></nut-backtop>
+```
+
+```html
+<script>
+export default createDemo({
+  setup(props, { emit }) {
+    const handleClick = () => {
+      console.log('触发回到顶部');
+    };
+
+    return {
+      handleClick
+    };
+  }
+});
+</script>
+```
+
+
+### API
+
+### Prop  
+
+| 字段            | 说明                                                                                           | 类型    | 默认值  |
+|-----------------|------------------------------------------------------------------------------------------------|---------|---------|
+| elId           | 获取监听元素的父级元素                                                                           | String  | -       |
+| bottom         | 距离页面底部距离                                                                                | Number  | -       |
+| right        | 距离页面右侧距离                                                                                  | Number |    |
+| distance     | 页面垂直滚动多高后出现                                                            | Number  | -       |
+| zIndex         | 设置组件页面层级                                                         | Number  | -       |                                          
+
+### Event
+| 名称  | 说明     | 回调参数    |
+|-------|----------|-------------|
+| click | 按钮点击时触发事件 | event:Event |

+ 49 - 0
src/packages/backtop/index.scss

@@ -0,0 +1,49 @@
+#app .demo {
+  padding: 0 0;
+  padding-top: 57px;
+  z-index: 1;
+  height: 100%;
+  // scroll-behavior: smooth;
+  .text-data {
+    margin: 0 auto;
+    margin-top: 15px;
+    margin-bottom: 20px;
+    padding-left: 16px;
+    display: flex;
+    align-items: center;
+    width: 342px;
+    height: 46px;
+    background: rgba(255, 255, 255, 1);
+    border-radius: 7px;
+    box-shadow: 0px 1px 7px 0px rgba(237, 238, 241, 1);
+    line-height: 19px;
+    font-family: PingFangSC-Medium;
+    font-size: 13px;
+    color: rgba(102, 102, 102, 1);
+  }
+}
+
+.nut-backtop {
+  display: none;
+  position: fixed;
+  bottom: 20px;
+  right: 20px;
+  z-index: 111;
+  &.show {
+    display: block;
+    width: 40px;
+    height: 40px;
+    background: rgba(255, 255, 255, 1);
+    border: 1px solid rgba(224, 224, 224, 1);
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  &.show :active {
+    background: rgba(0, 0, 0, 0.1);
+  }
+  &-main {
+    transition: all 0.2s ease-in-out;
+  }
+}

+ 144 - 0
src/packages/backtop/index.vue

@@ -0,0 +1,144 @@
+<template>
+  <div
+    :class="['nut-backtop', { show: backTop }]"
+    :style="{
+      right: styleRight,
+      bottom: styleBottom,
+      'z-index': zIndex
+    }"
+    @click="click"
+  >
+    <slot>
+      <nut-icon size="19px" class="nut-backtop-main" name="top"></nut-icon>
+    </slot>
+  </div>
+</template>
+
+<script lang="ts">
+import { computed, ref, onMounted, onUnmounted } from 'vue';
+import { createComponent } from '@/utils/create';
+const { create } = createComponent('backtop');
+
+export default create({
+  props: {
+    //距离页面底部
+    bottom: {
+      type: Number,
+      default: 20
+    },
+    //距离页面右侧
+    right: {
+      type: Number,
+      default: 10
+    },
+    ///获取容器ID
+    elId: {
+      type: String,
+      default: ''
+    },
+    //页面垂直滚动多高后出现
+    distance: {
+      type: Number,
+      default: 200
+    },
+    //设置层级
+    zIndex: {
+      type: Number,
+      default: 1111
+    }
+  },
+
+  emits: ['click'],
+
+  components: {},
+
+  setup(props, { emit }) {
+    const styleBottom = computed(() => `${props.bottom}px`);
+    const styleRight = computed(() => `${props.right}px`);
+    // const styleDistance = computed(() => `${props.distance}px`);
+    const zIndex = computed(() => `${props.zIndex}px`);
+
+    //默认图标不出现
+    const backTop = ref(false);
+
+    let scrollEl: Window | HTMLElement = window;
+    const elId = ref(props.elId);
+
+    function scrollListener() {
+      //滚动条偏移量
+      //Window
+      if (scrollEl instanceof Window) {
+        const scrollTop = scrollEl.pageYOffset !== undefined ? scrollEl.pageYOffset : '';
+        backTop.value = scrollTop >= props.distance;
+        //DOM
+      } else if (scrollEl instanceof HTMLElement) {
+        const scrollTop = scrollEl.scrollTop;
+        backTop.value = scrollTop >= props.distance;
+      }
+    }
+
+    //点击按钮返回顶部
+    function scroll(y = 0) {
+      if (scrollEl instanceof Window) {
+        window.scrollTo(0, y);
+      } else if (scrollEl instanceof HTMLElement) {
+        scrollEl.scrollTop = y;
+      }
+    }
+
+    //监听页面滚动事件
+    function addEventListener() {
+      scrollEl.addEventListener('scroll', scrollListener, true);
+    }
+
+    //解绑监听页面滚动事件
+    function removeEventListener() {
+      scrollEl.removeEventListener('scroll', scrollListener, true);
+    }
+    // function deactivated() {
+    //   keepAlive.value = true;
+    //   removeEventListener();
+    // }
+
+    onUnmounted(() => {
+      removeEventListener();
+    });
+
+    //点击回到顶部
+    function click() {
+      scroll();
+      emit('click');
+    }
+
+    function init() {
+      //重新获取容器id
+      const _scrollEl = document.getElementById(elId.value);
+
+      if (elId.value && _scrollEl) {
+        scrollEl = _scrollEl;
+        _scrollEl.style.scrollBehavior = 'smooth';
+      }
+
+      addEventListener();
+      scrollListener();
+    }
+
+    onMounted(() => {
+      init();
+    });
+
+    return {
+      backTop,
+      scrollEl,
+      click,
+      styleBottom,
+      styleRight,
+      zIndex
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>