ソースを参照

Merge branch 'v2' of https://github.com/jdf2e/nutui into v2

songchenglin3 6 年 前
コミット
98594e39bf

+ 10 - 0
src/config.json

@@ -502,6 +502,16 @@
       "sort": "5",
       "showDemo": true,
       "author": "杨凯旋"
+    },
+    {
+      "version": "1.0.0",
+      "name": "LeftSlip",
+      "chnName": "侧滑删除",
+      "desc": "手势侧滑删除元素",
+      "type": "component",
+      "sort": "2",
+      "showDemo": true,
+      "author": "vickyYE"
     }
   ]
 }

+ 203 - 200
src/nutui.js

@@ -1,149 +1,153 @@
-import { version } from "../package.json";
-import { packages as pkgList } from "./config.json";
-import { locale } from "./locales";
-import Cell from "./packages/cell/index.js";
-import "./packages/cell/cell.scss";
-import Dialog from "./packages/dialog/index.js";
-import "./packages/dialog/dialog.scss";
-import Icon from "./packages/icon/index.js";
-import "./packages/icon/icon.scss";
-import Toast from "./packages/toast/index.js";
-import "./packages/toast/toast.scss";
-import ActionSheet from "./packages/actionsheet/index.js";
-import "./packages/actionsheet/actionsheet.scss";
-import Tab from "./packages/tab/index.js";
-import "./packages/tab/tab.scss";
-import TabPanel from "./packages/tabpanel/index.js";
-import "./packages/tabpanel/tabpanel.scss";
-import TabBar from "./packages/tabbar/index.js";
-import "./packages/tabbar/tabbar.scss";
-import Calendar from "./packages/calendar/index.js";
-import "./packages/calendar/calendar.scss";
-import DatePicker from "./packages/datepicker/index.js";
-import "./packages/datepicker/datepicker.scss";
-import NavBar from "./packages/navbar/index.js";
-import "./packages/navbar/navbar.scss";
-import NoticeBar from "./packages/noticebar/index.js";
-import "./packages/noticebar/noticebar.scss";
-import Switch from "./packages/switch/index.js";
-import "./packages/switch/switch.scss";
-import Slider from "./packages/slider/index.js";
-import "./packages/slider/slider.scss";
-import Range from "./packages/range/index.js";
-import "./packages/range/range.scss";
-import Picker from "./packages/picker/index.js";
-import "./packages/picker/picker.scss";
-import Progress from "./packages/progress/index.js";
-import "./packages/progress/progress.scss";
-import Price from "./packages/price/index.js";
-import "./packages/price/price.scss";
-import Flex from "./packages/flex/index.js";
-import "./packages/flex/flex.scss";
-import Col from "./packages/col/index.js";
-import "./packages/col/col.scss";
-import Row from "./packages/row/index.js";
-import "./packages/row/row.scss";
-import Steps from "./packages/steps/index.js";
-import "./packages/steps/steps.scss";
-import Button from "./packages/button/index.js";
-import "./packages/button/button.scss";
-import Badge from "./packages/badge/index.js";
-import "./packages/badge/badge.scss";
-import Rate from "./packages/rate/index.js";
-import "./packages/rate/rate.scss";
-import Swiper from "./packages/swiper/index.js";
-import "./packages/swiper/swiper.scss";
-import Menu from "./packages/menu/index.js";
-import "./packages/menu/menu.scss";
-import Stepper from "./packages/stepper/index.js";
-import "./packages/stepper/stepper.scss";
-import ButtonGroup from "./packages/buttongroup/index.js";
-import "./packages/buttongroup/buttongroup.scss";
-import SearchBar from "./packages/searchbar/index.js";
-import "./packages/searchbar/searchbar.scss";
-import ImagePicker from "./packages/imagepicker/index.js";
-import "./packages/imagepicker/imagepicker.scss";
-import Radio from "./packages/radio/index.js";
-import "./packages/radio/radio.scss";
-import RadioGroup from "./packages/radiogroup/index.js";
-import "./packages/radiogroup/radiogroup.scss";
-import CheckBox from "./packages/checkbox/index.js";
-import "./packages/checkbox/checkbox.scss";
-import CheckBoxGroup from "./packages/checkboxgroup/index.js";
-import "./packages/checkboxgroup/checkboxgroup.scss";
-import ShortPassword from "./packages/shortpassword/index.js";
-import "./packages/shortpassword/shortpassword.scss";
-import Skeleton from "./packages/skeleton/index.js";
-import "./packages/skeleton/skeleton.scss";
-import Scroller from "./packages/scroller/index.js";
-import "./packages/scroller/scroller.scss";
-import BackTop from "./packages/backtop/index.js";
-import "./packages/backtop/backtop.scss";
-import CountDown from "./packages/countdown/index.js";
-import "./packages/countdown/countdown.scss";
-import InfiniteLoading from "./packages/infiniteloading/index.js";
-import "./packages/infiniteloading/infiniteloading.scss";
-import Uploader from "./packages/uploader/index.js";
-import "./packages/uploader/uploader.scss";
-import TextInput from "./packages/textinput/index.js";
-import "./packages/textinput/textinput.scss";
-import Avatar from "./packages/avatar/index.js";
-import "./packages/avatar/avatar.scss";
-import Lazyload from "./packages/lazyload/index.js";
-import "./packages/textbox/textbox.scss";
-import TextBox from "./packages/textbox/index.js";
-import Elevator from "./packages/elevator/index.js";
-import "./packages/elevator/elevator.scss";
-import Popup from "./packages/popup/index.js";
-import "./packages/popup/popup.scss";
+import {version} from '../package.json';
+import {packages as pkgList} from './config.json';
+import {locale} from './locales';
+import Cell from './packages/cell/index.js';
+import './packages/cell/cell.scss';
+import Dialog from './packages/dialog/index.js';
+import './packages/dialog/dialog.scss';
+import Icon from './packages/icon/index.js';
+import './packages/icon/icon.scss';
+import Toast from './packages/toast/index.js';
+import './packages/toast/toast.scss';
+import ActionSheet from './packages/actionsheet/index.js';
+import './packages/actionsheet/actionsheet.scss';
+import Tab from './packages/tab/index.js';
+import './packages/tab/tab.scss';
+import TabPanel from './packages/tabpanel/index.js';
+import './packages/tabpanel/tabpanel.scss';
+import TabBar from './packages/tabbar/index.js';
+import './packages/tabbar/tabbar.scss';
+import Calendar from './packages/calendar/index.js';
+import './packages/calendar/calendar.scss';
+import DatePicker from './packages/datepicker/index.js';
+import './packages/datepicker/datepicker.scss';
+import NavBar from './packages/navbar/index.js';
+import './packages/navbar/navbar.scss';
+import NoticeBar from './packages/noticebar/index.js';
+import './packages/noticebar/noticebar.scss';
+import Switch from './packages/switch/index.js';
+import './packages/switch/switch.scss';
+import Slider from './packages/slider/index.js';
+import './packages/slider/slider.scss';
+import Range from './packages/range/index.js';
+import './packages/range/range.scss';
+import Picker from './packages/picker/index.js';
+import './packages/picker/picker.scss';
+import Progress from './packages/progress/index.js';
+import './packages/progress/progress.scss';
+import Price from './packages/price/index.js';
+import './packages/price/price.scss';
+import Flex from './packages/flex/index.js';
+import './packages/flex/flex.scss';
+import Col from './packages/col/index.js';
+import './packages/col/col.scss';
+import Row from './packages/row/index.js';
+import './packages/row/row.scss';
+import Steps from './packages/steps/index.js';
+import './packages/steps/steps.scss';
+import Button from './packages/button/index.js';
+import './packages/button/button.scss';
+import Badge from './packages/badge/index.js';
+import './packages/badge/badge.scss';
+import Rate from './packages/rate/index.js';
+import './packages/rate/rate.scss';
+import Swiper from './packages/swiper/index.js';
+import './packages/swiper/swiper.scss';
+import Menu from './packages/menu/index.js';
+import './packages/menu/menu.scss';
+import Stepper from './packages/stepper/index.js';
+import './packages/stepper/stepper.scss';
+import ButtonGroup from './packages/buttongroup/index.js';
+import './packages/buttongroup/buttongroup.scss';
+import SearchBar from './packages/searchbar/index.js';
+import './packages/searchbar/searchbar.scss';
+import ImagePicker from './packages/imagepicker/index.js';
+import './packages/imagepicker/imagepicker.scss';
+import Radio from './packages/radio/index.js';
+import './packages/radio/radio.scss';
+import RadioGroup from './packages/radiogroup/index.js';
+import './packages/radiogroup/radiogroup.scss';
+import CheckBox from './packages/checkbox/index.js';
+import './packages/checkbox/checkbox.scss';
+import CheckBoxGroup from './packages/checkboxgroup/index.js';
+import './packages/checkboxgroup/checkboxgroup.scss';
+import ShortPassword from './packages/shortpassword/index.js';
+import './packages/shortpassword/shortpassword.scss';
+import Skeleton from './packages/skeleton/index.js';
+import './packages/skeleton/skeleton.scss';
+import Scroller from './packages/scroller/index.js';
+import './packages/scroller/scroller.scss';
+import BackTop from './packages/backtop/index.js';
+import './packages/backtop/backtop.scss';
+import CountDown from './packages/countdown/index.js';
+import './packages/countdown/countdown.scss';
+import InfiniteLoading from './packages/infiniteloading/index.js';
+import './packages/infiniteloading/infiniteloading.scss';
+import Uploader from './packages/uploader/index.js';
+import './packages/uploader/uploader.scss';
+import TextInput from './packages/textinput/index.js';
+import './packages/textinput/textinput.scss';
+import Avatar from './packages/avatar/index.js';
+import './packages/avatar/avatar.scss';
+import Lazyload from './packages/lazyload/index.js';
+import './packages/textbox/textbox.scss';
+import TextBox from './packages/textbox/index.js';
+import Elevator from './packages/elevator/index.js';
+import './packages/elevator/elevator.scss';
+import Popup from './packages/popup/index.js';
+import LeftSlip from './packages/leftslip/index.js';
+import './packages/leftslip/leftslip.scss';
+
+import './packages/popup/popup.scss';
 const packages = {
-  Cell,
-  Dialog,
-  Icon,
-  Toast,
-  ActionSheet,
-  Tab,
-  TabPanel,
-  TabBar,
-  Calendar,
-  DatePicker,
-  NavBar,
-  NoticeBar,
-  Switch,
-  Slider,
-  Range,
-  Picker,
-  Progress,
-  Price,
-  Flex,
-  Col,
-  Row,
-  Steps,
-  Button,
-  Badge,
-  Rate,
-  Swiper,
-  Menu,
-  Stepper,
-  ButtonGroup,
-  SearchBar,
-  ImagePicker,
-  Radio,
-  RadioGroup,
-  CheckBox,
-  CheckBoxGroup,
-  ShortPassword,
-  Skeleton,
-  Scroller,
-  BackTop,
-  CountDown,
-  InfiniteLoading,
-  Uploader,
-  TextInput,
-  TextBox,
-  Avatar,
-  Elevator,
-  Popup
+    Cell,
+    Dialog,
+    Icon,
+    Toast,
+    ActionSheet,
+    Tab,
+    TabPanel,
+    TabBar,
+    Calendar,
+    DatePicker,
+    NavBar,
+    NoticeBar,
+    Switch,
+    Slider,
+    Range,
+    Picker,
+    Progress,
+    Price,
+    Flex,
+    Col,
+    Row,
+    Steps,
+    Button,
+    Badge,
+    Rate,
+    Swiper,
+    Menu,
+    Stepper,
+    ButtonGroup,
+    SearchBar,
+    ImagePicker,
+    Radio,
+    RadioGroup,
+    CheckBox,
+    CheckBoxGroup,
+    ShortPassword,
+    Skeleton,
+    Scroller,
+    BackTop,
+    CountDown,
+    InfiniteLoading,
+    Uploader,
+    TextInput,
+    TextBox,
+    Avatar,
+    Elevator,
+    Popup,
+    LeftSlip
 };
 
 const components = {};
@@ -151,80 +155,79 @@ const methods = {};
 const filters = {};
 const directives = {};
 pkgList.map(item => {
-  const pkg = packages[item.name];
-  if (!pkg) return;
+    const pkg = packages[item.name];
+    if (!pkg) return;
 
-  if (item.type == "component") {
-    if (pkg.name) {
-      components[pkg.name] = pkg;
-    } else {
-      for (let n in pkg) {
-        components[n] = pkg[n];
-      }
+    if (item.type == 'component') {
+        if (pkg.name) {
+            components[pkg.name] = pkg;
+        } else {
+            for (let n in pkg) {
+                components[n] = pkg[n];
+            }
+        }
+    } else if (item.type == 'method') {
+        methods[item.name] = pkg;
+    } else if (item.type == 'filter') {
+        filters[item.name] = pkg;
+    } else if (item.type == 'directive') {
+        directives[item.name] = pkg;
     }
-  } else if (item.type == "method") {
-    methods[item.name] = pkg;
-  } else if (item.type == "filter") {
-    filters[item.name] = pkg;
-  } else if (item.type == "directive") {
-    directives[item.name] = pkg;
-  }
 });
 
 const install = function(Vue, opts = {}) {
-  if (install.installed) return;
+    if (install.installed) return;
 
-  if (opts.locale) {
-    Vue.config.lang = opts.locale;
-  }
+    if (opts.locale) {
+        Vue.config.lang = opts.locale;
+    }
 
-  if (opts.lang) locale(Vue.config.lang, opts.lang);
+    if (opts.lang) locale(Vue.config.lang, opts.lang);
 
-  for (let cptName in methods) {
-    if (Array.isArray(methods[cptName])) {
-      Vue.prototype["$" + cptName.toLowerCase()] = methods[cptName][0];
-      Vue.component(methods[cptName][1].name, methods[cptName][1]);
-    } else {
-      Vue.prototype["$" + cptName.toLowerCase()] = methods[cptName];
+    for (let cptName in methods) {
+        if (Array.isArray(methods[cptName])) {
+            Vue.prototype['$' + cptName.toLowerCase()] = methods[cptName][0];
+            Vue.component(methods[cptName][1].name, methods[cptName][1]);
+        } else {
+            Vue.prototype['$' + cptName.toLowerCase()] = methods[cptName];
+        }
     }
-  }
 
-  for (let cptName in components) {
-    if (components[cptName] && components[cptName].name) {
-      Vue.component(components[cptName].name, components[cptName]);
+    for (let cptName in components) {
+        if (components[cptName] && components[cptName].name) {
+            Vue.component(components[cptName].name, components[cptName]);
+        }
     }
-  }
 
-  for (let cptName in filters) {
-    if (filters[cptName] && filters[cptName].name) {
-      Vue.filter(cptName, filters[cptName]);
+    for (let cptName in filters) {
+        if (filters[cptName] && filters[cptName].name) {
+            Vue.filter(cptName, filters[cptName]);
+        }
     }
-  }
 
-  for (let cptName in directives) {
-    if (directives[cptName] && directives[cptName].name) {
-      Vue.directive(directives[cptName].name, directives[cptName]);
+    for (let cptName in directives) {
+        if (directives[cptName] && directives[cptName].name) {
+            Vue.directive(directives[cptName].name, directives[cptName]);
+        }
     }
-  }
 
-  Vue.use(Lazyload, {
-    lazyComponent: true,
-    loading:
-      "//img12.360buyimg.com/imagetools/jfs/t1/73967/28/14561/916/5dc142e4E0666555b/bf33454553c6035e.png"
-  });
+    Vue.use(Lazyload, {
+        lazyComponent: true,
+        loading: '//img12.360buyimg.com/imagetools/jfs/t1/73967/28/14561/916/5dc142e4E0666555b/bf33454553c6035e.png'
+    });
 };
 
-if (typeof window !== "undefined" && window.Vue) {
-  install(window.Vue);
+if (typeof window !== 'undefined' && window.Vue) {
+    install(window.Vue);
 }
 
 export default {
-  version,
-  locale,
-  install,
-  Lazyload,
-  ...components,
-  ...filters,
-  ...directives,
-  ...methods
+    version,
+    locale,
+    install,
+    Lazyload,
+    ...components,
+    ...filters,
+    ...directives,
+    ...methods
 };

+ 160 - 157
src/packages/checkboxgroup/checkboxgroup.vue

@@ -1,181 +1,184 @@
 <template>
-    <div :class="['nut-checkboxgroup',{'vertical':vertical},customClass]" >
-        <div class="checkbox-item" v-for="(item,index) in checkBoxData" :key="item[keys.id]">
-            <nut-checkbox 
-            :name="name||item[keys.name]" 
-            :disabled=" disabled || item[keys.disabled]" 
-            :label="item[keys.label]"
-            :animation="animation"
-            :size="item.size ? item.size : size"
-            
-            :id="item[keys.id]"
-            :checked.sync="item.checked"
-            
-            
-            v-model="checkboxValues[index]"
-            @change="changeEvt(arguments,item)"
-
-            >{{ item[keys.label] || item[keys.value] || item}}
-            </nut-checkbox>
-        </div>
+  <div :class="['nut-checkboxgroup', { vertical: vertical }, customClass]">
+    <div
+      class="checkbox-item"
+      v-for="(item, index) in initData"
+      :key="item[keys.id]"
+    >
+      <nut-checkbox
+        :name="name || item[keys.name]"
+        :disabled="disabled || item[keys.disabled]"
+        :label="item[keys.label]"
+        :animation="animation"
+        :size="item.size ? item.size : size"
+        :id="item[keys.id]"
+        :checked.sync="item.checked"
+        v-model="checkboxValues[index]"
+        @change="changeEvt(arguments, item)"
+        >{{ item[keys.label] || item[keys.value] || item }}
+      </nut-checkbox>
     </div>
+  </div>
 </template>
 <script>
 import nutcheckbox from "../checkbox/checkbox.vue";
-import "../checkbox/checkbox.scss";	
+import "../checkbox/checkbox.scss";
 export default {
-    name:'nut-checkboxgroup',
-    props: {
-        name: String,
-    	checkBoxData:{
-    		type:Array,
-            required:true,
-            
-    	},
+  name: "nut-checkboxgroup",
+  props: {
+    name: String,
+    checkBoxData: {
+      type: Array,
+      required: true
+    },
 
-        value: {
-            type: Array,
-            required: true
-        },
-        keys: {
-            type: Object,
-            default() {
-                return {
-                    id: 'id',
-                    name: 'name',
-                    class: 'class',
-                    label: 'label',
-                    value: 'value',
-                    disabled: 'disabled'
-                };
-            }
-        },
-        customClass:{
-            type: String,
-            default: ''
-        },
-        label:{
-            type: [String, Number, Boolean],
-            default: ''
-        },
-        size: {
-            type: [String, Number],
-            default: 'base'
-        },
-        disabled: {
-            type: Boolean,
-            default: false
-        },
-        animation: {
-            type: Boolean,
-            default: true
-        },
-        vertical:{
-            type: Boolean,
-            default: false
-        }
+    value: {
+      type: Array,
+      required: true
     },
-    data() {
+    keys: {
+      type: Object,
+      default() {
         return {
-            ignoreChange: false,
-        	checkboxValues: [],
-            initialValue: []
+          id: "id",
+          name: "name",
+          class: "class",
+          label: "label",
+          value: "value",
+          disabled: "disabled"
         };
+      }
+    },
+    customClass: {
+      type: String,
+      default: ""
     },
-    components: {
-	    [nutcheckbox.name]: nutcheckbox
+    label: {
+      type: [String, Number, Boolean],
+      default: ""
     },
-    watch:{
-        value(){
-            this.init();
+    size: {
+      type: [String, Number],
+      default: "base"
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    },
+    animation: {
+      type: Boolean,
+      default: true
+    },
+    vertical: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      ignoreChange: false,
+      initData: [],
+      checkboxValues: [],
+      initialValue: []
+    };
+  },
+  components: {
+    [nutcheckbox.name]: nutcheckbox
+  },
+  watch: {
+    value() {
+      this.init();
+    }
+  },
+  mounted() {
+    this.init();
+  },
+  methods: {
+    init() {
+      this.initialValue = this.value;
+      this.checkBoxData.map(item => {
+        if (typeof item === "object") {
+          item.checked = this.isOptionCheckedByDefault(item);
         }
+      });
     },
-    mounted(){
-        this.init()
+    isObject(obj) {
+      return obj !== null && typeof obj === "object";
     },
-    methods: {
-        init(){
-            this.initialValue = this.value;
-            this.checkBoxData.map(item=>{
-                if(typeof item ==="object"){
-                    item.checked = this.isOptionCheckedByDefault(item)
-                }
-            })
-        },
-        isObject(obj) {
-            return obj !== null && typeof obj === 'object';
-        },
-        looseIndexOf(arr, val) {
-            for (let i = 0; i < arr.length; i++) {
-                if (this.looseEqual(arr[i], val)) {
-                    return i;
-                }
-            }
-
-            return -1;
-        },
-        isOptionCheckedByDefault(item) {
-            return this.looseIndexOf(this.initialValue, item[this.keys.value] || item) > -1;
-        },
-        looseEqual(a, b) {
-            return a == b || (
-               this.isObject(a) && this.isObject(b) ? JSON.stringify(a) === JSON.stringify(b) : false
-            );
-        },
-        changeEvt(args,item) {
-            if (this.ignoreChange) {
-                return;
-            }
+    looseIndexOf(arr, val) {
+      for (let i = 0; i < arr.length; i++) {
+        if (this.looseEqual(arr[i], val)) {
+          return i;
+        }
+      }
 
-            const checked = args[0];
-            const label = args[1];
-            const e = args[2];
+      return -1;
+    },
+    isOptionCheckedByDefault(item) {
+      return (
+        this.looseIndexOf(this.initialValue, item[this.keys.value] || item) > -1
+      );
+    },
+    looseEqual(a, b) {
+      return (
+        a == b ||
+        (this.isObject(a) && this.isObject(b)
+          ? JSON.stringify(a) === JSON.stringify(b)
+          : false)
+      );
+    },
+    changeEvt(args, item) {
+      if (this.ignoreChange) {
+        return;
+      }
 
-            let value = [];
-            const itemValue = item[this.keys.value] || item;
-            const i = this.looseIndexOf(this.value, itemValue);
+      const checked = args[0];
+      const label = args[1];
+      const e = args[2];
 
-            if (checked && i < 0) {
-                value = this.value.concat(itemValue);
-            }
+      let value = [];
+      const itemValue = item[this.keys.value] || item;
+      const i = this.looseIndexOf(this.value, itemValue);
 
-            if (!checked && i > -1) {
-                value = this.value.slice(0, i).concat(this.value.slice(i + 1));
-            }
+      if (checked && i < 0) {
+        value = this.value.concat(itemValue);
+      }
 
-            this.$emit('input', value);
-            this.$emit('change', value,label, e);
+      if (!checked && i > -1) {
+        value = this.value.slice(0, i).concat(this.value.slice(i + 1));
+      }
 
-           
-        },
-        toggleAll(checked) {
-            if (checked === false) {
-                this.$emit("input", []);
-                return;
-            }
-            if(checked === true){
-                this.checkBoxData.map(item => {
-                    item.checked = true;
-                });
-            }
-            if (!checked) {
-                this.checkBoxData.map(item => {
-                    item.checked = !item.checked;
-                });
-            }
+      this.$emit("input", value);
+      this.$emit("change", value, label, e);
+    },
+    toggleAll(checked) {
+      if (checked === false) {
+        this.$emit("input", []);
+        return;
+      }
+      if (checked === true) {
+        this.checkBoxData.map(item => {
+          item.checked = true;
+        });
+      }
+      if (!checked) {
+        this.checkBoxData.map(item => {
+          item.checked = !item.checked;
+        });
+      }
 
-            let value = [],
-                label = [];
-            let resData = this.checkBoxData.filter(item => {
-                if (item.checked) {
-                value.push(item.value);
-                label.push(item.label);
-                }
-                return item.checked;
-            });
-            this.$emit("input",value);
-            this.$emit("change", value, label, null);
+      let value = [],
+        label = [];
+      let resData = this.checkBoxData.filter(item => {
+        if (item.checked) {
+          value.push(item.value);
+          label.push(item.label);
         }
+        return item.checked;
+      });
+      this.$emit("input", value);
+      this.$emit("change", value, label, null);
     }
-}
-</script>
+  }
+};
+</script>

ファイルの差分が大きいため隠しています
+ 137 - 0
src/packages/leftslip/demo.vue


+ 62 - 0
src/packages/leftslip/doc.md

@@ -0,0 +1,62 @@
+# LeftSlip 左滑删除
+
+列表元素向左滑出现删除等按钮
+
+## 基本用法
+
+```html
+<div>
+    <nut-leftslip>
+        <div slot="slip-main" class="slip-main">向左滑动我</div>
+        <div slot="slipbtns" class="slipbtns"><a href="javascript:;">删除</a><a href="javascript:;" class="favorite">收藏</a></div>
+    </nut-leftslip>
+</div>
+```
+
+### 单个按钮
+
+```html
+<div>
+    <nut-leftslip>
+        <div slot="slip-main" class="slip-main">
+            {{ 222 }}
+        </div>
+        <div slot="slipbtns" class="slipbtns"><a href="javascript:;">删除</a></div>
+    </nut-leftslip>
+</div>
+```
+
+### 列表
+
+```html
+<nut-leftslip @slide-left="slideLeft" @slide-right="slideRight" @slide-no="slideNo" during="0.2">
+    <div slot="slip-main" class="slip-main">
+        <div class="addr">
+            <p class="name-mobile">159****8888</p>
+            <p class="full-addr">北京市大兴区亦庄经济开发中心京东大厦B座</p>
+        </div>
+        <a class="addr-edit" href="javascript:void(0)"></a>
+    </div>
+    <div slot="slipbtns" class="slipbtns"> <a href="javascript:;">删除</a><a href="javascript:;">收藏</a> </div>
+</nut-leftslip>
+```
+
+```javascript
+export default {
+    components: {},
+    data() {
+        return {};
+    },
+    methods: {
+        slideLeft() {
+            console.log('左划了');
+        },
+        slideRight() {
+            console.log('右划了');
+        },
+        slideNo() {
+            console.log('没有划动');
+        }
+    }
+};
+```

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

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

+ 60 - 0
src/packages/leftslip/leftslip.scss

@@ -0,0 +1,60 @@
+.nut-leftslip {
+    position: relative;
+    overflow: hidden;
+    &:first-child .slip-main {
+        border-top: 1px solid #d8d8d8;
+    }
+    .slip-main {
+        padding: 10px;
+        position: relative;
+        overflow: hidden;
+        display: flex;
+        border-bottom: 1px solid #d8d8d8;
+        background: #fff;
+    }
+    .leftslip-item {
+        transition: all 0.6s ease;
+    }
+    .delbtn{
+        position: absolute;
+        right: -80px;
+        top: 0;
+        width: 40px;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        // transform: translateX(100%);
+        background: #ff4949;
+        color: #fff;
+        padding: 0 5px;
+        font-size: 14px;
+        span{
+            // width: 40px;
+            display: block;
+        }
+    }
+    .slipbtns {
+        position: absolute;
+        right: -0px;
+        top: 0;
+        // width: 80px;
+        height: 100%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        transform: translateX(100%);
+        
+        a {
+            display: flex;
+            width: 40px;
+            background: #ff4949;
+            color: #fff;
+            height: 100%;
+            padding: 0 5px;
+            font-size: 14px;
+            align-items: center;
+            justify-content: center;
+        }
+    }
+}

+ 206 - 0
src/packages/leftslip/leftslip.vue

@@ -0,0 +1,206 @@
+<template>
+    <div class="nut-leftslip">
+        <div class="leftslip-item" ref="slipItem" :style="deleteSlider">
+            <div @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)">
+                <slot name="slip-main"></slot>
+            </div>
+            <div>
+                <!-- <div>删除</div> -->
+                <div v-if="onlyDel" :style="delBtnStyle" @click="handleClick" class="delbtn" ref="delBtn"><span>删除</span></div>
+                <slot name="slipbtns" v-else @click="handleClick"></slot>
+            </div>
+        </div>
+    </div>
+</template>
+<script>
+export default {
+    name: 'nut-leftslip',
+    props: {
+        during: {
+            type: [Number, String],
+            default: 1
+        },
+        isClickRestore: {
+            type: [Boolean],
+            default: true
+        },
+        customClass: {
+            type: String,
+            default: ''
+        },
+        onlyDel: {
+            type: [Boolean],
+            default: false
+        }
+    },
+    data() {
+        return {
+            startX: 0,
+            startY: 0,
+            moveX: 0,
+            moveY: 0,
+            left: 0,
+            buttonWidth: 0,
+            disX: 0, //移动距离
+            deleteSlider: '', //滑动时的效果,使用v-bind:style="deleteSlider"
+            delBtnStyle: '' //单个删除键拖拽删除效果
+        };
+    },
+    mounted() {
+        this.$nextTick(() => {
+            if (this.onlyDel) {
+                return;
+            }
+            for (var slot of this.$slots.slipbtns) {
+                this.buttonWidth = this.buttonWidth + slot.elm.offsetWidth;
+            }
+        });
+        window.addEventListener('scroll', this.handleScroll, true);
+    },
+    beforeDestroy() {
+        // 移除监听
+        window.removeEventListener('scroll', this.handleScroll, true);
+    },
+    methods: {
+        handleScroll() {
+            if (this.disX) {
+                this.restSlide();
+            }
+            // this.restSlide();
+        },
+        handleClick(v) {
+            this.restSlide();
+        },
+        touchStart(e) {
+            this.restSlide();
+            // console.log('rest', e.touches.length);
+            e = e || event;
+
+            //tounches类数组,等于1时表示此时有只有一只手指在触摸屏幕
+            if (e.touches.length == 1) {
+                // 记录开始位置
+                this.startX = e.touches[0].clientX;
+                this.startY = e.touches[0].clientY;
+            }
+        },
+        touchMove(e) {
+            e = e || event;
+            // let parentElement = e.currentTarget.parentElement;
+            //获取删除按钮的宽度,此宽度为滑块左滑的最大距离
+            let itemWd = this.$refs.slipItem.offsetWidth;
+            // console.log(this.$refs.delBtn.offsetWidth);
+            let wd = this.onlyDel ? 40 : this.buttonWidth;
+            if (e.touches.length == 1) {
+                // 滑动时距离浏览器左侧实时距离
+                this.moveY = e.touches[0].clientY;
+                this.moveX = e.touches[0].clientX;
+                if (Math.abs(this.moveY - this.startY) < 40) {
+                    //起始位置减去 实时的滑动的距离,得到手指实时偏移距离
+                    this.disX = this.startX - this.moveX;
+                    // console.log(this.disX);
+                    if (this.onlyDel) {
+                        //一键删除
+                        this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+                        this.delBtnStyle = 'width:' + this.disX + 'px;right:-' + this.disX + 'px';
+                        if (this.disX < wd || this.disX == 0) {
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            this.delBtnStyle = 'width:40px;right:-0px';
+                        } else {
+                            this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+                            this.delBtnStyle = 'width:' + this.disX + 'px;right:-' + this.disX + 'px';
+                            if (this.disX > itemWd - 20) {
+                                this.deleteSlider = 'transform:translateX(-' + itemWd + 'px)';
+                                this.delBtnStyle = 'width:' + itemWd + 'px;right:-' + itemWd + 'px';
+                                // alert(111);
+                            }
+                        }
+                    } else {
+                        // 如果是向右滑动或者不滑动,不改变滑块的位置
+                        if (this.disX < wd / 3 || this.disX == 0) {
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            // parentElement.dataset.type = 0;
+                            // 大于0,表示左滑了,此时滑块开始滑动
+                        } else if (this.disX > wd / 3) {
+                            //具体滑动距离我取的是 手指偏移距离*5。
+                            // parentElement.dataset.type = 1;
+                            this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+
+                            // 最大也只能等于删除按钮宽度
+                            if (this.disX * 1.5 >= wd) {
+                                // parentElement.dataset.type = 1;
+                                if (wd >= itemWd) {
+                                    this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                                } else {
+                                    this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        },
+        touchEnd(e) {
+            e = e || event;
+            // let parentElement = e.currentTarget.parentElement;
+            let itemWd = this.$refs.slipItem.offsetWidth;
+            let wd = this.onlyDel ? 40 : this.buttonWidth;
+            if (e.changedTouches.length == 1) {
+                let endY = e.changedTouches[0].clientY;
+                if (Math.abs(this.startY - endY) < 40) {
+                    let endX = e.changedTouches[0].clientX;
+                    this.disX = this.startX - endX;
+                    console.log('touchEndthis.disX:', this.disX);
+                    if (this.onlyDel) {
+                        // this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+                        // this.delBtnStyle = 'width:' + this.disX + 'px;right:-' + this.disX + 'px';
+                        if (this.disX < wd) {
+                            // parentElement.dataset.type = 0;
+                            this.deleteSlider = 'transform:translateX(0px)';
+                            this.delBtnStyle = 'width:40px;right:-0px';
+                        } else {
+                            this.deleteSlider = 'transform:translateX(-' + this.disX + 'px)';
+                            this.delBtnStyle = 'width:' + this.disX + 'px;right:-' + this.disX + 'px';
+                            if (this.disX > itemWd - 20) {
+                                this.deleteSlider = 'transform:translateX(-' + itemWd + 'px)';
+                                this.delBtnStyle = 'width:' + itemWd + 'px;right:-' + itemWd + 'px';
+                                this.$emit('oneDelete', e);
+                            }
+                        }
+                    } else {
+                        //如果距离小于删除按钮一半,强行回到起点
+
+                        if (this.disX < wd / 3) {
+                            // parentElement.dataset.type = 0;
+                            this.deleteSlider = 'transform:translateX(0px)';
+                        } else {
+                            //大于一半 滑动到最大值
+                            // parentElement.dataset.type = 1;
+                            if (wd >= itemWd) {
+                                //按钮数不可超出整行宽度
+                                this.deleteSlider = 'transform:translateX(-' + (itemWd - 40) + 'px)';
+                            } else {
+                                this.deleteSlider = 'transform:translateX(-' + wd + 'px)';
+                            }
+                        }
+                    }
+
+                    // console.log('touchEnd:dataset', parentElement.dataset.type);
+                }
+            }
+        },
+        restSlide() {
+            let listItems = document.querySelectorAll('.leftslip-item');
+            let delBtns = document.querySelectorAll('.delbtn');
+            console.log(delBtns);
+            // 复位
+            for (let i = 0; i < listItems.length; i++) {
+                listItems[i].style = 'transform:translateX(0' + 'px)';
+            }
+            for (let j = 0; j < delBtns.length; j++) {
+                delBtns[j].style = '';
+            }
+            // this.delBtnStyle = '';
+        }
+    }
+};
+</script>

+ 1 - 0
types/nutui.d.ts

@@ -64,3 +64,4 @@ export declare class Avatar extends UIComponent {}
 export declare class Infiniteloading extends UIComponent {}
 export declare class Lazyload extends UIComponent {}
 export declare class Elevator extends UIComponent {}
+export declare class SlipesideBotdeslip[Cefttonutton extends UIComponent {}