Browse Source

feat:添加回到顶部组件

jin cao 7 years ago
parent
commit
0671d4e461

+ 6 - 5
package.json

@@ -59,7 +59,6 @@
     "@babel/preset-env": "7.1.0",
     "@nutui/carefree": "^0.4.0",
     "@tweenjs/tween.js": "17.2.0",
-    "istanbul-instrumenter-loader": "3.0.1",
     "@vue/test-utils": "1.0.0-beta.25",
     "autoprefixer": "9.1.3",
     "babel-eslint": "8.2.6",
@@ -73,6 +72,7 @@
     "babel-preset-env": "1.7.0",
     "babel-preset-stage-2": "6.24.1",
     "chalk": "2.4.1",
+    "clipboard": "2.0.1",
     "copy": "0.3.2",
     "copy-webpack-plugin": "4.5.4",
     "coveralls": "^3.0.2",
@@ -86,8 +86,10 @@
     "friendly-errors-webpack-plugin": "1.7.0",
     "google-code-prettify": "1.0.5",
     "has": "1.0.3",
+    "highlight.js": "^9.13.1",
     "html-webpack-plugin": "3.2.0",
     "inquirer": "6.2.0",
+    "istanbul-instrumenter-loader": "3.0.1",
     "jest": "23.5.0",
     "jest-serializer-vue": "2.0.2",
     "jsdom": "13.0.0",
@@ -103,6 +105,7 @@
     "offline-plugin": "^5.0.6",
     "optimize-css-assets-webpack-plugin": "5.0.0",
     "ora": "3.0.0",
+    "path": "^0.12.7",
     "portfinder": "1.0.17",
     "postcss-import": "12.0.0",
     "postcss-loader": "3.0.0",
@@ -123,6 +126,7 @@
     "vue-i18n": "8.1.0",
     "vue-jest": "2.6.0",
     "vue-loader": "15.4.0",
+    "vue-router": "^3.0.2",
     "vue-style-loader": "4.1.2",
     "vue-template-compiler": "2.5.17",
     "vueg": "1.3.4",
@@ -131,10 +135,7 @@
     "webpack-cli": "3.1.0",
     "webpack-dev-server": "3.1.11",
     "webpack-merge": "4.1.4",
-    "webpack-node-externals": "1.7.2",
-    "clipboard": "2.0.1",
-    "highlight.js": "^9.13.1",
-    "path": "^0.12.7"
+    "webpack-node-externals": "1.7.2"
   },
   "browserslist": [
     "> 3%",

+ 22 - 13
src/config.json

@@ -359,25 +359,34 @@
       "author": "Vicky.Ye"
     },
     {
-      "version":"1.0.0",
-      "name":"ShortPassword",
-      "chnName":"短密码",
-      "des":"短密码",
-      "type":"component",
-      "sort":"1",
+      "version": "1.0.0",
+      "name": "ShortPassword",
+      "chnName": "短密码",
+      "des": "短密码",
+      "type": "component",
+      "sort": "1",
       "showDemo": true,
       "author": "wangnan31"
-
     },
     {
-      "version":"1.0.0",
-      "name":"Skeleton",
-      "chnName":"骨架屏",
-      "des":"在页面上待加载区域填充灰色的占位图,本质上是界面加载过程中的过渡效果",
-      "type":"component",
-      "sort":"0",
+      "version": "1.0.0",
+      "name": "Skeleton",
+      "chnName": "骨架屏",
+      "des": "在页面上待加载区域填充灰色的占位图,本质上是界面加载过程中的过渡效果",
+      "type": "component",
+      "sort": "0",
       "showDemo": true,
       "author": "wangnan31"
+    },
+    {
+      "version": "1.0.0",
+      "name": "BackTop",
+      "chnName": "回到顶部",
+      "desc": "用于页面内容高度过长,快捷回到顶部使用。",
+      "type": "component",
+      "sort": "2",
+      "showDemo": true,
+      "author": "永无止晋"
     }
   ]
 }

+ 28 - 0
src/packages/backtop/backtop.scss

@@ -0,0 +1,28 @@
+.nut-backtop{
+    z-index: 1111;
+    position: fixed;
+    cursor: pointer;
+    display: none;
+    line-height: 0;
+    &.show {
+        display: block;
+    }
+
+    &-main {
+        background-color: rgba(0,0,0,.3);
+        border-radius: 2px;
+        box-shadow: 0 1px 3px rgba(0,0,0,.2);
+        transition: all .2s ease-in-out;
+        
+        &:hover {
+            background-color: rgba(0,0,0,.5);
+        }
+    }
+
+    i{
+        color: #fff;
+        font-size: 24px;
+        padding: 8px 12px;
+        line-height: 0;
+    }
+}

+ 123 - 0
src/packages/backtop/backtop.vue

@@ -0,0 +1,123 @@
+<template>
+    <div :class="['nut-backtop', {'show': backTop}]" :style="styles" @click="goto">
+        <slot>
+            <div class="nut-backtop-main">
+                <nut-icon 
+                    type="top" 
+                    color="#f0250f"
+                >
+                </nut-icon>
+            </div>
+        </slot>
+    </div>
+</template>
+<script>
+
+    export default {
+        name:'nut-backtop',
+        props: {
+            distance: {
+                type: Number,
+                default: 200
+            },
+            bottom: {
+                type: Number,
+                default: 30
+            },
+            right: {
+                type: Number,
+                default: 30
+            },
+            duration: {
+                type: Number,
+                default: 1000
+            },
+            zIndex: {
+                type: Number,
+                default: 1111
+            }
+        },
+        data () {
+            return {
+                backTop: false
+            };
+        },
+        mounted () {
+            window.addEventListener('scroll', this.handleScroll, false);
+            window.addEventListener('resize', this.handleScroll, false);
+        },
+        beforeDestroy () {
+            window.removeEventListener('scroll', this.handleScroll, false);
+            window.removeEventListener('resize', this.handleScroll, false);
+        },
+        computed: {
+            styles () {
+                return {
+                    'bottom': `${this.bottom}px`,
+                    'right': `${this.right}px`,
+                    'z-index': this.zIndex
+                };
+            }
+        },
+        methods: {
+            handleScroll () {
+                this.backTop = window.pageYOffset >= this.distance;
+            },
+            goto () {
+                const sTop = document.documentElement.scrollTop || document.body.scrollTop;
+                this.scrollTop(window, sTop, 0, this.duration);
+                this.$emit('click');
+            },
+            scrollTop(el, from = 0, to, duration = 500, endCallback) {
+                this.el = el;
+                let lastTime = 0;
+                let vendors = ['webkit', 'moz'];
+                for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+                    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
+                    window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||    // name has changed in Webkit
+                                                window[vendors[x] + 'CancelRequestAnimationFrame'];
+                }
+
+                if (!window.requestAnimationFrame) {
+                    window.requestAnimationFrame = function(callback, element) {
+                        var currTime = new Date().getTime();
+                        var timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
+                        var id = window.setTimeout(function() {
+                            callback(currTime + timeToCall);
+                        }, timeToCall);
+                        lastTime = currTime + timeToCall;
+                        return id;
+                    };
+                }
+                if (!window.cancelAnimationFrame) {
+                    window.cancelAnimationFrame = function(id) {
+                        clearTimeout(id);
+                    };
+                }
+                const difference = Math.abs(from - to);
+                const step = Math.ceil(difference / duration * 50);
+
+                
+                this.scroll(from, to, step, endCallback);
+            },
+            scroll(start, end, step, endCallback) {
+                if (start === end) {
+                    endCallback && endCallback();
+                    return;
+                }
+
+                let d = (start + step > end) ? end : start + step;
+                if (start > end) {
+                    d = (start - step < end) ? end : start - step;
+                }
+                if (this.el === window) {
+                    window.scrollTo(d, d);
+                } else {
+                    this.el.scrollTop = d;
+                }
+                window.requestAnimationFrame(() => this.scroll(d, end, step));
+            }
+
+        }
+    };
+</script>

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

@@ -0,0 +1,36 @@
+<template>
+    <div class="back-top-demo"> 
+      这个页面很长...<br>       
+      这个页面很长...<br>       
+      这个页面很长...<br>       
+      这个页面很长...<br>       
+      这个页面很长...<br>       
+      这个页面很长...<br>       
+      这个页面很长...<br>             
+      <nut-backtop @click="handleClick"></nut-backtop>
+    </div>
+</template>
+
+<script>
+export default {
+  components: {
+
+  },
+  data() {
+    return {};
+  },
+  methods: {
+      handleClick(){
+        console.log('触发回到顶部')
+      }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+  .back-top-demo {
+    height: 1600px;
+    line-height: 400px;
+    text-align: center;
+  }
+</style>

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

@@ -0,0 +1,70 @@
+# Switch 滑动开关
+
+用于较长的页面快捷回到顶部的组件。
+
+## 基本用法
+
+```html
+<nut-backtop></nut-backtop>
+```
+
+## 设置出现位置
+
+```html
+<nut-backtop 
+  :distance="400"
+>
+</nut-backtop>
+> “页面垂直方向滚动高度”后出现
+
+## click事件
+```html
+<nut-backtop 
+  @click="onClick"
+>
+</nut-backtop>
+```
+```javascript
+export default {
+  methods: {
+    onClick() {
+      console.log("触发回到顶部按钮")
+    }
+  }
+};
+```
+
+## 设置样式
+```html
+<nut-switch 
+  :bottom="20"
+  :right="20"
+  :zIndex="10"
+>
+</nut-switch>
+```
+
+
+## 设置动画持续时间
+```html
+<nut-switch 
+  :duration="1000"  
+>
+</nut-switch>
+```
+
+
+## Prop
+
+| 字段 | 说明 | 类型 | 默认值
+|----- | ----- | ----- | ----- 
+| duration | 设置动画持续时间 | Number | 1000
+| distance | 设置“页面垂直方向滚动高度”后出现 | Number | 200
+| bottom | 设置离页面底部距离 | Number | 30
+| right | 设置离页面右边距离 | Number | 30
+| zIndex | 设置层级 | Number | 1111
+
+## Events
+| 字段 | 说明 | 回调参数 
+|----- | ----- | ----- 
+| click | 按钮点击时触发 | -

+ 8 - 0
src/packages/backtop/index.js

@@ -0,0 +1,8 @@
+import BackTop from './backtop.vue';
+import './backtop.scss';
+
+BackTop.install = function(Vue) {
+  Vue.component(BackTop.name, BackTop);
+};
+
+export default BackTop

+ 7 - 1
src/packages/rate/doc.md

@@ -43,5 +43,11 @@
 | total | star 总数 | Number | 5
 | value | 当前 star 数,可以使用 v-model 双向绑定数据 | Number | 3
 | size | star 大小 | Number | 25
+| spacing | 两个star的间距 | Number | 20
 | uncheckedIcon | 使用图标(未选中) | String | -
-| checkedIcon | 使用图标(选中) | String | -
+| checkedIcon | 使用图标(选中) | String | -
+
+## Events
+| 字段 | 说明 | 回调参数 
+|----- | ----- | ----- 
+| click | 点击star市触发 | star的index

+ 11 - 2
src/packages/rate/rate.vue

@@ -4,7 +4,12 @@
             class="nut-rate-item" 
             :class="['nut-rate-item',{'nut-rate-active':n<=current}]" 
             v-for="n in total" :key="n" @click="onClick($event,n)" 
-            :style="{'height':size+'px','width':size+'px','backgroundImage':n<=current?checkedIcon:uncheckedIcon}">
+            :style="{
+                'height':size+'px',
+                'width':size+'px',
+                'marginRight':spacing+'px',
+                'backgroundImage':n<=current?checkedIcon:uncheckedIcon
+            }">
         </span>
     </div>
 </template>
@@ -36,7 +41,11 @@ export default {
         testProp:{
             type:String,
             default:null
-        } 
+        },
+        spacing:{
+            type:[String,Number],
+            default: 20
+        },
     },
     data() {
         return {