picker.esm.js 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. import { normalizeComponent, createInjector } from 'vue-runtime-helpers';
  2. //
  3. //
  4. //
  5. //
  6. //
  7. //
  8. //
  9. //
  10. //
  11. //
  12. //
  13. //
  14. // TODO: 支持自定义的render渲染
  15. // import textRender from './render'
  16. var script = {
  17. props: {
  18. cancelText: {
  19. type: String
  20. },
  21. confirmText: {
  22. type: String
  23. },
  24. title: {
  25. type: String
  26. }
  27. },
  28. methods: {
  29. cancel () {
  30. this.$emit('cancel');
  31. },
  32. confirm () {
  33. this.$emit('confirm');
  34. }
  35. }
  36. };
  37. /* script */
  38. const __vue_script__ = script;
  39. /* template */
  40. var __vue_render__ = function() {
  41. var _vm = this;
  42. var _h = _vm.$createElement;
  43. var _c = _vm._self._c || _h;
  44. return _c("div", { staticClass: "header" }, [
  45. _c("div", { staticClass: "left" }, [
  46. _c("span", { staticClass: "btn", on: { click: _vm.cancel } }, [
  47. _vm._v(_vm._s(_vm.cancelText))
  48. ])
  49. ]),
  50. _vm._v(" "),
  51. _c("div", { staticClass: "title" }, [_vm._v(_vm._s(_vm.title))]),
  52. _vm._v(" "),
  53. _c("div", { staticClass: "right" }, [
  54. _c("span", { staticClass: "btn", on: { click: _vm.confirm } }, [
  55. _vm._v(_vm._s(_vm.confirmText))
  56. ])
  57. ])
  58. ])
  59. };
  60. var __vue_staticRenderFns__ = [];
  61. __vue_render__._withStripped = true;
  62. /* style */
  63. const __vue_inject_styles__ = function (inject) {
  64. if (!inject) return
  65. inject("data-v-6ffe26b0_0", { source: ".header[data-v-6ffe26b0] {\n height: 44px;\n line-height: 44px;\n display: -webkit-box;\n display: flex;\n -webkit-box-pack: justify;\n justify-content: space-between;\n position: relative;\n}\n.header[data-v-6ffe26b0]::after {\n position: absolute;\n box-sizing: border-box;\n content: \" \";\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n border-width: 1px 0;\n}\n.title[data-v-6ffe26b0] {\n max-width: 50%;\n font-weight: 500;\n font-size: 16px;\n text-align: center;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.btn[data-v-6ffe26b0] {\n padding: 0 16px;\n color: #1989fa;\n font-size: 14px;\n background-color: transparent;\n}\n\n/*# sourceMappingURL=header.vue.map */", map: {"version":3,"sources":["/Users/naice/my-project/vue-picker/src/header.vue","header.vue"],"names":[],"mappings":"AAuCA;EACA,YAAA;EACA,iBAAA;EACA,oBAAA;EAAA,aAAA;EACA,yBAAA;UAAA,8BAAA;EACA,kBAAA;ACtCA;ADuCA;EACA,kBAAA;EACA,sBAAA;EACA,YAAA;EACA,oBAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,uBAAA;EACA,6BAAA;UAAA,qBAAA;EACA,mBAAA;ACrCA;ADwCA;EACA,cAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ACrCA;ADuCA;EACA,eAAA;EACA,cAAA;EACA,eAAA;EACA,6BAAA;ACpCA;;AAEA,qCAAqC","file":"header.vue","sourcesContent":["<template>\n <div class=\"header\">\n <div class=\"left\">\n <span class=\"btn\" @click=\"cancel\">{{cancelText}}</span>\n </div>\n <div class=\"title\">{{title}}</div>\n <div class=\"right\">\n <span class=\"btn\" @click=\"confirm\">{{confirmText}}</span>\n </div>\n </div>\n</template>\n\n<script>\n // TODO: 支持自定义的render渲染\n // import textRender from './render'\n export default {\n props: {\n cancelText: {\n type: String\n },\n confirmText: {\n type: String\n },\n title: {\n type: String\n }\n },\n methods: {\n cancel () {\n this.$emit('cancel')\n },\n confirm () {\n this.$emit('confirm')\n }\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .header {\n height: 44px;\n line-height: 44px;\n display: flex;\n justify-content: space-between;\n position: relative;\n &::after {\n position: absolute;\n box-sizing: border-box;\n content: ' ';\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n transform: scale(0.5);\n border-width: 1px 0;\n }\n }\n .title {\n max-width: 50%;\n font-weight: 500;\n font-size: 16px;\n text-align: center;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .btn {\n padding: 0 16px;\n color: #1989fa;\n font-size: 14px;\n background-color: transparent;\n }\n</style>\n",".header {\n height: 44px;\n line-height: 44px;\n display: flex;\n justify-content: space-between;\n position: relative;\n}\n.header::after {\n position: absolute;\n box-sizing: border-box;\n content: \" \";\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n transform: scale(0.5);\n border-width: 1px 0;\n}\n\n.title {\n max-width: 50%;\n font-weight: 500;\n font-size: 16px;\n text-align: center;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.btn {\n padding: 0 16px;\n color: #1989fa;\n font-size: 14px;\n background-color: transparent;\n}\n\n/*# sourceMappingURL=header.vue.map */"]}, media: undefined });
  66. };
  67. /* scoped */
  68. const __vue_scope_id__ = "data-v-6ffe26b0";
  69. /* module identifier */
  70. const __vue_module_identifier__ = undefined;
  71. /* functional template */
  72. const __vue_is_functional_template__ = false;
  73. /* style inject SSR */
  74. /* style inject shadow dom */
  75. var Header = normalizeComponent(
  76. { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
  77. __vue_inject_styles__,
  78. __vue_script__,
  79. __vue_scope_id__,
  80. __vue_is_functional_template__,
  81. __vue_module_identifier__,
  82. false,
  83. createInjector,
  84. undefined,
  85. undefined
  86. );
  87. const DEFTAULT_ITEM_HEIGHT = 44;
  88. // 兼容pc 移动端
  89. const HAS_TOUCH = 'ontouchstart' in window;
  90. const START_EVENT = HAS_TOUCH ? 'touchstart' : 'mousedown';
  91. const MOVE_EVENT = HAS_TOUCH ? 'touchmove' : 'mousemove';
  92. const END_EVENT = HAS_TOUCH ? 'touchend' : 'mouseup';
  93. const getClient = e => {
  94. let clientX = HAS_TOUCH ? e.changedTouches[0].clientX : e.clientX;
  95. let clientY = HAS_TOUCH ? e.changedTouches[0].clientY : e.clientY;
  96. return {
  97. x: clientX,
  98. y: clientY
  99. }
  100. };
  101. const isPC = () => {
  102. const userAgentInfo = navigator.userAgent;
  103. const Agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod'];
  104. let flag = true;
  105. for (var v = 0; v < Agents.length; v++) {
  106. if (userAgentInfo.indexOf(Agents[v]) > 0) {
  107. flag = false;
  108. break
  109. }
  110. }
  111. return flag
  112. };
  113. //
  114. const DEFAULT_DURATION = 200;
  115. // 惯性滑动思路:
  116. // 在手指离开屏幕时,如果和上一次 move 时的间隔小于 `LIMIT_TIME` 且 move
  117. // 距离大于 `LIMIT_DISTANCE` 时,执行惯性滑动
  118. const LIMIT_TIME = 300;
  119. const LIMIT_DISTANCE = 15;
  120. const IS_PC = isPC();
  121. var script$1 = {
  122. props: {
  123. defaultIndex: {
  124. type: Number,
  125. default: 0
  126. },
  127. column: {
  128. type: Array,
  129. default: () => ([])
  130. },
  131. boxHeight: Number,
  132. itemHeight: Number,
  133. rowNumber: Number
  134. },
  135. data() {
  136. return {
  137. ulStyle: {
  138. transform: `translate3d(0px, 0px, 0px)`,
  139. transitionDuration: `0ms`,
  140. transitionProperty: `none`,
  141. lineHeight: `${this.itemHeight}px`
  142. }
  143. }
  144. },
  145. computed: {
  146. count() {
  147. return this.column.length
  148. },
  149. getRoNumber() {
  150. return Math.floor(this.rowNumber / 2)
  151. }
  152. },
  153. methods: {
  154. init () {
  155. this.setTop(this.defaultIndex);
  156. const halfBox = (this.boxHeight - this.itemHeight) / 2;
  157. this.bottom = halfBox + this.itemHeight;
  158. this.top = halfBox - this.count * this.itemHeight;
  159. },
  160. // 根据index 设置滚动位置
  161. setTop (index = 0) {
  162. const { boxHeight, itemHeight } = this;
  163. this.startTop = ((boxHeight - itemHeight) / 2) - (index * itemHeight);
  164. this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`;
  165. this.selectIndex = index;
  166. this.change();
  167. },
  168. handleStart (e) {
  169. this.distStartTop = getClient(e).y;
  170. this.touchStartTime = Date.now();
  171. // ----
  172. this.startY = getClient(e).y;
  173. this.momentumTop = this.startTop;
  174. this.ulStyle.transitionDuration = `0ms`;
  175. this.ulStyle.transitionProperty = `none`;
  176. if (IS_PC) {
  177. document.addEventListener(MOVE_EVENT, this.handleMove, false);
  178. document.addEventListener(END_EVENT, this.handleEnd, false);
  179. }
  180. },
  181. handleMove (e) {
  182. e.preventDefault();
  183. e.stopPropagation();
  184. this.disY = getClient(e).y - this.startY;
  185. this.startY = getClient(e).y;
  186. if (this.startTop >= this.bottom) {
  187. this.startTop = this.bottom;
  188. } else if (this.startTop <= this.top) {
  189. this.startTop = this.top;
  190. } else {
  191. this.startTop += this.disY;
  192. }
  193. this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`;
  194. const now = Date.now();
  195. if (now - this.touchStartTime > LIMIT_TIME) {
  196. this.touchStartTime = now;
  197. this.momentumTop = this.startTop;
  198. }
  199. },
  200. handleEnd () {
  201. if (IS_PC) {
  202. document.removeEventListener(MOVE_EVENT, this.handleMove, false);
  203. document.removeEventListener(END_EVENT, this.handleEnd, false);
  204. }
  205. const distance = this.startTop - this.momentumTop;
  206. const duration = Date.now() - this.touchStartTime;
  207. const allowMomentum = duration < LIMIT_TIME && Math.abs(distance) > LIMIT_DISTANCE;
  208. if (allowMomentum) {
  209. this.toMove(distance, duration);
  210. } else {
  211. this.setTranfromTop();
  212. }
  213. },
  214. setTranfromTop () {
  215. this.ulStyle.transitionProperty = `all`;
  216. this.ulStyle.transitionDuration = `${DEFAULT_DURATION}ms`;
  217. if (this.startTop >= this.bottom - this.itemHeight) {
  218. this.setTop();
  219. } else if (this.startTop <= this.top + this.itemHeight) {
  220. this.setTop(this.count - 1);
  221. } else {
  222. let index = Math.round((this.startTop) / this.itemHeight);
  223. this.startTop = index * this.itemHeight;
  224. if (this.startTop > this.bottom) {
  225. this.startTop = this.bottom - this.itemHeight;
  226. index = -this.getRoNumber;
  227. } else if (this.startTop < this.top) {
  228. this.startTop = this.top + this.itemHeight;
  229. index = this.count + 1;
  230. }
  231. this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`;
  232. index = this.getRoNumber - index;
  233. if (this.selectIndex !== index) {
  234. this.selectIndex = index;
  235. this.change();
  236. }
  237. }
  238. },
  239. toMove (distance, duration) {
  240. const speed = Math.abs(distance / duration);
  241. distance = this.startTop + (speed / 0.002) * (distance < 0 ? -1 : 1);
  242. this.ulStyle.transitionProperty = `all`;
  243. this.ulStyle.transitionDuration = `1000ms`;
  244. this.setTop(Math.min(Math.max(Math.round(-distance / this.itemHeight), 0), this.count - 1));
  245. },
  246. change () {
  247. this.$emit('change', this.column[this.selectIndex]);
  248. },
  249. mousewheel (e) {
  250. e.preventDefault();
  251. e.stopPropagation();
  252. this.ulStyle.transitionDuration = `0ms`;
  253. this.ulStyle.transitionProperty = `none`;
  254. const { deltaX, deltaY } = e;
  255. if (Math.abs(deltaX) < Math.abs(deltaY)) {
  256. this.startTop = this.startTop - deltaY;
  257. let b = this.bottom - this.itemHeight;
  258. let t = this.top + this.itemHeight;
  259. let shouldMove = true;
  260. if (this.startTop > b ) {
  261. this.startTop = b;
  262. shouldMove = false;
  263. } else if (this.startTop < t) {
  264. this.startTop = t;
  265. shouldMove = false;
  266. }
  267. this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`;
  268. if (shouldMove) {
  269. clearInterval(this.wheelTimer);
  270. this.wheelTimer = setTimeout(this.setTranfromTop, 100);
  271. }
  272. }
  273. }
  274. },
  275. mounted () {
  276. this.init();
  277. // 监听开始事件
  278. this.$el.addEventListener(START_EVENT, this.handleStart, false);
  279. if (IS_PC) {
  280. this.$el.addEventListener('wheel', this.mousewheel, false);
  281. } else {
  282. this.$el.addEventListener(MOVE_EVENT, this.handleMove, false);
  283. this.$el.addEventListener(END_EVENT, this.handleEnd, false);
  284. }
  285. },
  286. watch: {
  287. column () {
  288. this.init();
  289. },
  290. defaultIndex () {
  291. this.setTop(this.defaultIndex);
  292. }
  293. },
  294. beforeDestroy () {
  295. this.$el.removeEventListener(START_EVENT, this.handleStart, false);
  296. if (IS_PC) {
  297. this.$el.removeEventListener('wheel', this.mousewheel, false);
  298. this.$el.removeEventListener(MOVE_EVENT, this.handleMove, false);
  299. this.$el.removeEventListener(END_EVENT, this.handleEnd, false);
  300. }
  301. }
  302. };
  303. /* script */
  304. const __vue_script__$1 = script$1;
  305. /* template */
  306. var __vue_render__$1 = function() {
  307. var _vm = this;
  308. var _h = _vm.$createElement;
  309. var _c = _vm._self._c || _h;
  310. return _c("div", { ref: "list", staticClass: "list" }, [
  311. _c(
  312. "ul",
  313. { style: _vm.ulStyle },
  314. _vm._l(_vm.column, function(item, index) {
  315. return _c("li", { key: "item" + index }, [_vm._v(_vm._s(item.label))])
  316. }),
  317. 0
  318. )
  319. ])
  320. };
  321. var __vue_staticRenderFns__$1 = [];
  322. __vue_render__$1._withStripped = true;
  323. /* style */
  324. const __vue_inject_styles__$1 = function (inject) {
  325. if (!inject) return
  326. inject("data-v-ec129ff4_0", { source: ".list[data-v-ec129ff4] {\n margin: 0;\n padding: 0;\n -webkit-box-flex: 1;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.list ul[data-v-ec129ff4] {\n margin: 0;\n padding: 0;\n -webkit-transition-timing-function: cubic-bezier(0.23, 1, 0.68, 1);\n transition-timing-function: cubic-bezier(0.23, 1, 0.68, 1);\n line-height: 44px;\n}\n.list li[data-v-ec129ff4] {\n margin: 0;\n padding: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n padding: 0 5px;\n color: #000;\n}\n\n/*# sourceMappingURL=list.vue.map */", map: {"version":3,"sources":["/Users/naice/my-project/vue-picker/src/list.vue","list.vue"],"names":[],"mappings":"AA4MA;EACA,SAAA;EACA,UAAA;EACA,mBAAA;UAAA,OAAA;EACA,WAAA;EACA,YAAA;EACA,gBAAA;AC3MA;AD4MA;EACA,SAAA;EACA,UAAA;EACA,kEAAA;UAAA,0DAAA;EACA,iBAAA;AC1MA;AD4MA;EACA,SAAA;EACA,UAAA;EACA,gBAAA;EACA,mBAAA;EACA,uBAAA;EACA,cAAA;EACA,WAAA;AC1MA;;AAEA,mCAAmC","file":"list.vue","sourcesContent":["<template>\n <div class=\"list\" ref=\"list\">\n <ul :style=\"ulStyle\">\n <li v-for=\"(item, index) in column\" :key=\"'item' + index\">{{item.label}}</li>\n </ul>\n </div>\n</template>\n\n<script>\n import { getClient, START_EVENT, MOVE_EVENT, END_EVENT, isPC } from './utils.js'\n const DEFAULT_DURATION = 200\n // 惯性滑动思路:\n // 在手指离开屏幕时,如果和上一次 move 时的间隔小于 `LIMIT_TIME` 且 move\n // 距离大于 `LIMIT_DISTANCE` 时,执行惯性滑动\n const LIMIT_TIME = 300\n const LIMIT_DISTANCE = 15\n const IS_PC = isPC()\n export default {\n props: {\n defaultIndex: {\n type: Number,\n default: 0\n },\n column: {\n type: Array,\n default: () => ([])\n },\n boxHeight: Number,\n itemHeight: Number,\n rowNumber: Number\n },\n data() {\n return {\n ulStyle: {\n transform: `translate3d(0px, 0px, 0px)`,\n transitionDuration: `0ms`,\n transitionProperty: `none`,\n lineHeight: `${this.itemHeight}px`\n }\n }\n },\n computed: {\n count() {\n return this.column.length\n },\n getRoNumber() {\n return Math.floor(this.rowNumber / 2)\n }\n },\n methods: {\n init () {\n this.setTop(this.defaultIndex)\n const halfBox = (this.boxHeight - this.itemHeight) / 2\n this.bottom = halfBox + this.itemHeight\n this.top = halfBox - this.count * this.itemHeight\n },\n // 根据index 设置滚动位置\n setTop (index = 0) {\n const { boxHeight, itemHeight } = this\n this.startTop = ((boxHeight - itemHeight) / 2) - (index * itemHeight)\n this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`\n this.selectIndex = index\n this.change()\n },\n handleStart (e) {\n this.distStartTop = getClient(e).y\n this.touchStartTime = Date.now()\n // ----\n this.startY = getClient(e).y\n this.momentumTop = this.startTop\n\n this.ulStyle.transitionDuration = `0ms`\n this.ulStyle.transitionProperty = `none`\n if (IS_PC) {\n document.addEventListener(MOVE_EVENT, this.handleMove, false)\n document.addEventListener(END_EVENT, this.handleEnd, false)\n }\n },\n handleMove (e) {\n e.preventDefault()\n e.stopPropagation()\n this.disY = getClient(e).y - this.startY\n this.startY = getClient(e).y\n if (this.startTop >= this.bottom) {\n this.startTop = this.bottom\n } else if (this.startTop <= this.top) {\n this.startTop = this.top\n } else {\n this.startTop += this.disY\n }\n this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`\n const now = Date.now()\n\n if (now - this.touchStartTime > LIMIT_TIME) {\n this.touchStartTime = now\n this.momentumTop = this.startTop\n }\n },\n handleEnd () {\n if (IS_PC) {\n document.removeEventListener(MOVE_EVENT, this.handleMove, false)\n document.removeEventListener(END_EVENT, this.handleEnd, false)\n }\n const distance = this.startTop - this.momentumTop\n const duration = Date.now() - this.touchStartTime\n const allowMomentum = duration < LIMIT_TIME && Math.abs(distance) > LIMIT_DISTANCE\n if (allowMomentum) {\n this.toMove(distance, duration)\n } else {\n this.setTranfromTop()\n }\n },\n setTranfromTop () {\n this.ulStyle.transitionProperty = `all`\n this.ulStyle.transitionDuration = `${DEFAULT_DURATION}ms`\n if (this.startTop >= this.bottom - this.itemHeight) {\n this.setTop()\n } else if (this.startTop <= this.top + this.itemHeight) {\n this.setTop(this.count - 1)\n } else {\n let index = Math.round((this.startTop) / this.itemHeight)\n this.startTop = index * this.itemHeight\n if (this.startTop > this.bottom) {\n this.startTop = this.bottom - this.itemHeight\n index = -this.getRoNumber\n } else if (this.startTop < this.top) {\n this.startTop = this.top + this.itemHeight\n index = this.count + 1\n }\n this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`\n index = this.getRoNumber - index\n if (this.selectIndex !== index) {\n this.selectIndex = index\n this.change()\n }\n }\n },\n toMove (distance, duration) {\n const speed = Math.abs(distance / duration)\n distance = this.startTop + (speed / 0.002) * (distance < 0 ? -1 : 1)\n this.ulStyle.transitionProperty = `all`\n this.ulStyle.transitionDuration = `1000ms`\n this.setTop(Math.min(Math.max(Math.round(-distance / this.itemHeight), 0), this.count - 1))\n },\n change () {\n this.$emit('change', this.column[this.selectIndex])\n },\n mousewheel (e) {\n e.preventDefault()\n e.stopPropagation()\n this.ulStyle.transitionDuration = `0ms`\n this.ulStyle.transitionProperty = `none`\n const { deltaX, deltaY } = e\n if (Math.abs(deltaX) < Math.abs(deltaY)) {\n this.startTop = this.startTop - deltaY\n let b = this.bottom - this.itemHeight\n let t = this.top + this.itemHeight\n let shouldMove = true\n if (this.startTop > b ) {\n this.startTop = b\n shouldMove = false\n } else if (this.startTop < t) {\n this.startTop = t\n shouldMove = false\n }\n this.ulStyle.transform = `translate3d(0px, ${this.startTop}px, 0px)`\n if (shouldMove) {\n clearInterval(this.wheelTimer)\n this.wheelTimer = setTimeout(this.setTranfromTop, 100)\n }\n }\n }\n },\n mounted () {\n this.init()\n // 监听开始事件\n this.$el.addEventListener(START_EVENT, this.handleStart, false)\n if (IS_PC) {\n this.$el.addEventListener('wheel', this.mousewheel, false)\n } else {\n this.$el.addEventListener(MOVE_EVENT, this.handleMove, false)\n this.$el.addEventListener(END_EVENT, this.handleEnd, false)\n }\n },\n watch: {\n column () {\n this.init()\n },\n defaultIndex () {\n this.setTop(this.defaultIndex)\n }\n },\n beforeDestroy () {\n this.$el.removeEventListener(START_EVENT, this.handleStart, false)\n if (IS_PC) {\n this.$el.removeEventListener('wheel', this.mousewheel, false)\n this.$el.removeEventListener(MOVE_EVENT, this.handleMove, false)\n this.$el.removeEventListener(END_EVENT, this.handleEnd, false)\n }\n }\n }\n</script>\n\n<style lang=\"scss\" scoped>\n .list {\n margin: 0;\n padding: 0;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n ul {\n margin: 0;\n padding: 0;\n transition-timing-function: cubic-bezier(0.23, 1, 0.68, 1);\n line-height: 44px;\n }\n li {\n margin: 0;\n padding: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n padding: 0 5px;\n color: #000;\n }\n }\n</style>\n",".list {\n margin: 0;\n padding: 0;\n flex: 1;\n width: 100%;\n height: 100%;\n overflow: hidden;\n}\n.list ul {\n margin: 0;\n padding: 0;\n transition-timing-function: cubic-bezier(0.23, 1, 0.68, 1);\n line-height: 44px;\n}\n.list li {\n margin: 0;\n padding: 0;\n overflow: hidden;\n white-space: nowrap;\n text-overflow: ellipsis;\n padding: 0 5px;\n color: #000;\n}\n\n/*# sourceMappingURL=list.vue.map */"]}, media: undefined });
  327. };
  328. /* scoped */
  329. const __vue_scope_id__$1 = "data-v-ec129ff4";
  330. /* module identifier */
  331. const __vue_module_identifier__$1 = undefined;
  332. /* functional template */
  333. const __vue_is_functional_template__$1 = false;
  334. /* style inject SSR */
  335. /* style inject shadow dom */
  336. var List = normalizeComponent(
  337. { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 },
  338. __vue_inject_styles__$1,
  339. __vue_script__$1,
  340. __vue_scope_id__$1,
  341. __vue_is_functional_template__$1,
  342. __vue_module_identifier__$1,
  343. false,
  344. createInjector,
  345. undefined,
  346. undefined
  347. );
  348. //
  349. var script$2 = {
  350. name: 'VuePicker',
  351. props: {
  352. visible: {
  353. type: Boolean,
  354. default: false
  355. },
  356. data: {
  357. type: Array,
  358. default: () => []
  359. },
  360. layer: {
  361. type: Number,
  362. default: 0
  363. },
  364. itemHeight: {
  365. type: [Number, String],
  366. default: DEFTAULT_ITEM_HEIGHT
  367. },
  368. defaultIndex: {
  369. type: [Number, Array],
  370. default: 0
  371. },
  372. cancelText: {
  373. type: String,
  374. default: '取消'
  375. },
  376. confirmText: {
  377. type: String,
  378. default: '确认'
  379. },
  380. title: {
  381. type: String,
  382. default: ''
  383. },
  384. showToolbar: {
  385. type: Boolean,
  386. default: false
  387. },
  388. maskClick: {
  389. type: Boolean,
  390. default: false
  391. },
  392. rowNumber: {
  393. type: Number,
  394. default: 5
  395. },
  396. appendToBody: {
  397. type: Boolean,
  398. default: false
  399. }
  400. },
  401. components: {
  402. Header,
  403. List
  404. },
  405. data () {
  406. return {
  407. column1: [],
  408. column2: [],
  409. column3: [],
  410. column4: [],
  411. dIndex1: 0,
  412. dIndex2: 0,
  413. dIndex3: 0,
  414. dIndex4: 0
  415. }
  416. },
  417. computed: {
  418. boxHeight () {
  419. let itemHeight = parseInt(this.itemHeight);
  420. itemHeight = itemHeight ? itemHeight : DEFTAULT_ITEM_HEIGHT;
  421. return itemHeight * this.getRowNumber
  422. },
  423. getRowNumber () {
  424. if (this.rowNumber < 3) {
  425. return 3
  426. }
  427. return this.rowNumber % 2 === 0 ? this.rowNumber + 1 : this.rowNumber
  428. },
  429. maskStyle() {
  430. let style = { backgroundSize: '100% 88px' };
  431. if (this.getRowNumber === 3) {
  432. style = { backgroundSize: '100% 44px' };
  433. }
  434. return style
  435. }
  436. },
  437. methods: {
  438. clickMask () {
  439. if (this.maskClick) {
  440. this.looseBody();
  441. this.$emit('update:visible', false);
  442. }
  443. },
  444. formateData () {
  445. if (this.layer > 1) {
  446. this.setLinkColumn();
  447. } else {
  448. this.column1 = this.data[0] || [];
  449. this.column2 = this.data[1] || [];
  450. this.column3 = this.data[2] || [];
  451. this.column4 = this.data[3] || [];
  452. this.setNormalIndex();
  453. }
  454. },
  455. setLinkColumn () {
  456. if (this.layer === 2) {
  457. this.setLinkLayer2();
  458. } else if (this.layer === 3) {
  459. this.setLinkLayer2();
  460. this.setLinkLayer3();
  461. } else if (this.layer === 4) {
  462. this.setLinkLayer2();
  463. this.setLinkLayer3();
  464. this.setLinkLayer4();
  465. }
  466. },
  467. setLinkLayer2 () {
  468. const { defaultIndex } = this;
  469. this.column1 = this.data || [];
  470. if (typeof defaultIndex === 'number') {
  471. this.dIndex1 = defaultIndex;
  472. this.dIndex2 = 0;
  473. if (this.data.length > 1 && this.data[0].children) {
  474. this.column2 = this.data[0].children || [];
  475. }
  476. } else if (Array.isArray(defaultIndex) && defaultIndex.length > 0){
  477. this.dIndex1 = defaultIndex[0] || 0;
  478. this.column2 = this.data[this.dIndex1].children || [];
  479. this.$nextTick(() => {
  480. if (this.column2.length - 1 < defaultIndex[1]) {
  481. this.dIndex2 = this.column2.length - 1;
  482. } else {
  483. this.dIndex2 = defaultIndex[1] || 0;
  484. }
  485. });
  486. }
  487. },
  488. setLinkLayer3 () {
  489. const { defaultIndex } = this;
  490. if (typeof defaultIndex === 'number') {
  491. this.dIndex3 = 0;
  492. if (this.column2.length > 1 && this.column2[0].children) {
  493. this.column3 = this.column2[0].children || [];
  494. }
  495. } else if (Array.isArray(defaultIndex) && defaultIndex.length > 1){
  496. this.$nextTick(() => {
  497. this.column3 = this.column2[this.dIndex2].children || [];
  498. this.$nextTick(() => {
  499. if (this.column3.length - 1 < defaultIndex[2]) {
  500. this.dIndex3 = this.column3.length - 1;
  501. } else {
  502. this.dIndex3 = defaultIndex[2] || 0;
  503. }
  504. });
  505. });
  506. }
  507. },
  508. setLinkLayer4 () {
  509. const { defaultIndex } = this;
  510. if (typeof defaultIndex === 'number') {
  511. this.dIndex4 = 0;
  512. if (this.column3.length > 1 && this.column3[0].children) {
  513. this.column4 = this.column3[0].children || [];
  514. }
  515. } else if (Array.isArray(defaultIndex) && defaultIndex.length > 2){
  516. setTimeout(() => {
  517. this.column4 = this.column3[this.dIndex3].children || [];
  518. this.$nextTick(() => {
  519. if (this.column4.length - 1 < defaultIndex[3]) {
  520. this.dIndex4 = this.column4.length - 1;
  521. } else {
  522. this.dIndex4 = defaultIndex[3] || 0;
  523. }
  524. });
  525. });
  526. }
  527. },
  528. setNormalIndex () {
  529. this.$nextTick(() => {
  530. const { defaultIndex } = this;
  531. if (Array.isArray(defaultIndex)) {
  532. this.setDefaultIndex();
  533. } else {
  534. this.dIndex1 = Number(defaultIndex) || 0;
  535. }
  536. });
  537. },
  538. setDefaultIndex () {
  539. const { indexArr } = this;
  540. const self = this;
  541. function next() {
  542. let promise = Promise.resolve();
  543. let index = 0;
  544. while (index < self.data.length) {
  545. promise = promise.then(indexArr[index]);
  546. index++;
  547. }
  548. }
  549. next();
  550. },
  551. change (index, res) {
  552. this.result[index] = res;
  553. this.$emit('change', this.result);
  554. },
  555. change1 (res) {
  556. if (res) {
  557. this.change(0, res);
  558. if (this.layer > 1) {
  559. this.dIndex2 = 0;
  560. this.changeLink('column2', res);
  561. }
  562. }
  563. },
  564. change2 (res) {
  565. if (res) {
  566. this.change(1, res);
  567. if (this.layer > 2) {
  568. this.dIndex3 = 0;
  569. this.changeLink('column3', res);
  570. }
  571. }
  572. },
  573. change3 (res) {
  574. if (res) {
  575. this.change(2, res);
  576. if (this.layer > 3) {
  577. this.dIndex4 = 0;
  578. this.changeLink('column4', res);
  579. }
  580. }
  581. },
  582. change4 (res) {
  583. if (res) {
  584. this.change(3, res);
  585. }
  586. },
  587. changeLink (key, res) {
  588. if (this.layer) {
  589. // clearTimeout(this.linktimer)
  590. this.linktimer = setTimeout(() => {
  591. this[key] = res.children || [];
  592. }, 1000 / 60);
  593. }
  594. },
  595. cancel () {
  596. this.looseBody();
  597. this.$emit('cancel');
  598. this.$emit('update:visible', false);
  599. },
  600. confirm () {
  601. this.looseBody();
  602. this.$emit('confirm', this.result);
  603. this.$emit('update:visible', false);
  604. },
  605. stopPropagation (e) {
  606. e.stopPropagation();
  607. },
  608. fixedBody() {
  609. const scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  610. this.prevBodyCss = document.body.style.cssText;
  611. document.body.style.cssText += 'position:fixed;width:100%;top:-' + scrollTop + 'px;';
  612. },
  613. looseBody() {
  614. const body = document.body;
  615. const top = body.style.top;
  616. body.style.cssText = this.prevBodyCss;
  617. body.scrollTop = document.documentElement.scrollTop = -parseInt(top);
  618. body.style.top = '';
  619. },
  620. init() {
  621. this.result = [];
  622. this.indexArr = [
  623. () => this.dIndex1 = this.defaultIndex[0] || 0,
  624. () => this.dIndex2 = this.defaultIndex[1] || 0,
  625. () => this.dIndex3 = this.defaultIndex[2] || 0,
  626. () => this.dIndex4 = this.defaultIndex[3] || 0
  627. ];
  628. this.formateData();
  629. }
  630. },
  631. created () {
  632. this.init();
  633. },
  634. mounted () {
  635. this.$refs.picker.addEventListener('click', this.stopPropagation);
  636. if (this.appendToBody) {
  637. document.body.appendChild(this.$el);
  638. }
  639. },
  640. watch: {
  641. visible (v) {
  642. if (v) {
  643. this.fixedBody();
  644. }
  645. },
  646. defaultIndex () {
  647. this.init();
  648. },
  649. data() {
  650. this.init();
  651. }
  652. },
  653. beforeDestroy () {
  654. this.$refs.picker.removeEventListener('click', this.stopPropagation);
  655. }
  656. };
  657. /* script */
  658. const __vue_script__$2 = script$2;
  659. /* template */
  660. var __vue_render__$2 = function() {
  661. var _vm = this;
  662. var _h = _vm.$createElement;
  663. var _c = _vm._self._c || _h;
  664. return _c("transition", { attrs: { name: "fade" } }, [
  665. _c(
  666. "div",
  667. {
  668. directives: [
  669. {
  670. name: "show",
  671. rawName: "v-show",
  672. value: _vm.visible,
  673. expression: "visible"
  674. }
  675. ],
  676. staticClass: "pickerbox",
  677. on: { click: _vm.clickMask }
  678. },
  679. [
  680. _c("transition", { attrs: { name: "toup" } }, [
  681. _c(
  682. "div",
  683. {
  684. directives: [
  685. {
  686. name: "show",
  687. rawName: "v-show",
  688. value: _vm.visible,
  689. expression: "visible"
  690. }
  691. ],
  692. ref: "picker",
  693. staticClass: "vue-picker"
  694. },
  695. [
  696. _vm.showToolbar
  697. ? _c("Header", {
  698. attrs: {
  699. cancelText: _vm.cancelText,
  700. confirmText: _vm.confirmText,
  701. title: _vm.title
  702. },
  703. on: { cancel: _vm.cancel, confirm: _vm.confirm }
  704. })
  705. : _vm._e(),
  706. _vm._v(" "),
  707. _c(
  708. "div",
  709. {
  710. staticClass: "content",
  711. style: { height: _vm.boxHeight + "px" }
  712. },
  713. [
  714. _c(
  715. "div",
  716. { staticClass: "colums" },
  717. [
  718. _c("List", {
  719. attrs: {
  720. column: _vm.column1,
  721. boxHeight: _vm.boxHeight,
  722. itemHeight: _vm.itemHeight,
  723. defaultIndex: _vm.dIndex1,
  724. rowNumber: _vm.getRowNumber
  725. },
  726. on: { change: _vm.change1 }
  727. }),
  728. _vm._v(" "),
  729. _vm.column2.length > 0
  730. ? _c("List", {
  731. attrs: {
  732. column: _vm.column2,
  733. boxHeight: _vm.boxHeight,
  734. itemHeight: _vm.itemHeight,
  735. defaultIndex: _vm.dIndex2,
  736. rowNumber: _vm.getRowNumber
  737. },
  738. on: { change: _vm.change2 }
  739. })
  740. : _vm._e(),
  741. _vm._v(" "),
  742. _vm.column3.length > 0
  743. ? _c("List", {
  744. attrs: {
  745. column: _vm.column3,
  746. boxHeight: _vm.boxHeight,
  747. itemHeight: _vm.itemHeight,
  748. defaultIndex: _vm.dIndex3,
  749. rowNumber: _vm.getRowNumber
  750. },
  751. on: { change: _vm.change3 }
  752. })
  753. : _vm._e(),
  754. _vm._v(" "),
  755. _vm.column4.length > 0
  756. ? _c("List", {
  757. attrs: {
  758. column: _vm.column4,
  759. boxHeight: _vm.boxHeight,
  760. itemHeight: _vm.itemHeight,
  761. defaultIndex: _vm.dIndex4,
  762. rowNumber: _vm.getRowNumber
  763. },
  764. on: { change: _vm.change4 }
  765. })
  766. : _vm._e()
  767. ],
  768. 1
  769. ),
  770. _vm._v(" "),
  771. _c("div", { staticClass: "mask", style: _vm.maskStyle }),
  772. _vm._v(" "),
  773. _c("div", { staticClass: "hairline" })
  774. ]
  775. )
  776. ],
  777. 1
  778. )
  779. ])
  780. ],
  781. 1
  782. )
  783. ])
  784. };
  785. var __vue_staticRenderFns__$2 = [];
  786. __vue_render__$2._withStripped = true;
  787. /* style */
  788. const __vue_inject_styles__$2 = function (inject) {
  789. if (!inject) return
  790. inject("data-v-200a1302_0", { source: ".pickerbox[data-v-200a1302] {\n position: fixed;\n width: 100vw;\n height: 100vh;\n left: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 9999;\n overflow: hidden;\n}\n.fade-enter-active[data-v-200a1302], .fade-leave-active[data-v-200a1302] {\n -webkit-transition: opacity 0.2s;\n transition: opacity 0.2s;\n}\n.fade-enter[data-v-200a1302], .fade-leave-to[data-v-200a1302] {\n opacity: 0;\n}\n.toup-enter-active[data-v-200a1302], .toup-leave-active[data-v-200a1302] {\n -webkit-transition: -webkit-transform 0.3s;\n transition: -webkit-transform 0.3s;\n transition: transform 0.3s;\n transition: transform 0.3s, -webkit-transform 0.3s;\n}\n.toup-enter[data-v-200a1302], .toup-leave-to[data-v-200a1302] {\n -webkit-transform: translate3d(0, 100px, 0);\n transform: translate3d(0, 100px, 0);\n}\n.vue-picker[data-v-200a1302] {\n position: absolute;\n left: 0;\n bottom: 0;\n width: 100%;\n background-color: #fff;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: transparent;\n}\n.content[data-v-200a1302] {\n overflow: hidden;\n height: 220px;\n position: relative;\n display: -webkit-box;\n display: flex;\n}\n.colums[data-v-200a1302] {\n display: -webkit-box;\n display: flex;\n overflow: hidden;\n font-size: 16px;\n text-align: center;\n -webkit-box-flex: 1;\n flex: 1;\n}\n.mask[data-v-200a1302] {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n width: 100%;\n height: 100%;\n background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0.9)), to(rgba(255, 255, 255, 0.4))), -webkit-gradient(linear, left bottom, left top, from(rgba(255, 255, 255, 0.9)), to(rgba(255, 255, 255, 0.4)));\n background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.4)), linear-gradient(0deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.4));\n background-repeat: no-repeat;\n background-position: top, bottom;\n -webkit-backface-visibility: hidden;\n backface-visibility: hidden;\n pointer-events: none;\n background-size: 100% 88px;\n}\n.hairline[data-v-200a1302] {\n position: absolute;\n top: 50%;\n left: 0;\n z-index: 3;\n width: 100%;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n pointer-events: none;\n height: 44px;\n}\n.hairline[data-v-200a1302]::after {\n position: absolute;\n box-sizing: border-box;\n content: \" \";\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n border-width: 1px 0;\n}\n\n/*# sourceMappingURL=index.vue.map */", map: {"version":3,"sources":["/Users/naice/my-project/vue-picker/src/index.vue","index.vue"],"names":[],"mappings":"AA2WA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,OAAA;EACA,SAAA;EACA,8BAAA;EACA,aAAA;EACA,gBAAA;AC1WA;AD4WA;EACA,gCAAA;EAAA,wBAAA;ACzWA;AD2WA;EACA,UAAA;ACxWA;AD0WA;EACA,0CAAA;EAAA,kCAAA;EAAA,0BAAA;EAAA,kDAAA;ACvWA;ADyWA;EACA,2CAAA;UAAA,mCAAA;ACtWA;ADyWA;EACA,kBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,sBAAA;EACA,yBAAA;KAAA,sBAAA;MAAA,qBAAA;UAAA,iBAAA;EACA,8BAAA;EACA,wCAAA;ACtWA;ADwWA;EACA,gBAAA;EACA,aAAA;EACA,kBAAA;EACA,oBAAA;EAAA,aAAA;ACrWA;ADuWA;EACA,oBAAA;EAAA,aAAA;EACA,gBAAA;EACA,eAAA;EACA,kBAAA;EACA,mBAAA;UAAA,OAAA;ACpWA;ADsWA;EACA,kBAAA;EACA,MAAA;EACA,OAAA;EACA,UAAA;EACA,WAAA;EACA,YAAA;EACA,8OAAA;EAAA,wKAAA;EACA,4BAAA;EACA,gCAAA;EACA,mCAAA;UAAA,2BAAA;EACA,oBAAA;EACA,0BAAA;ACnWA;ADqWA;EACA,kBAAA;EACA,QAAA;EACA,OAAA;EACA,UAAA;EACA,WAAA;EACA,mCAAA;UAAA,2BAAA;EACA,oBAAA;EACA,YAAA;AClWA;ADmWA;EACA,kBAAA;EACA,sBAAA;EACA,YAAA;EACA,oBAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;EACA,UAAA;EACA,uBAAA;EACA,6BAAA;EACA,qBAAA;EACA,mBAAA;ACjWA;;AAEA,oCAAoC","file":"index.vue","sourcesContent":["<template>\n <transition name=\"fade\">\n <div class=\"pickerbox\" v-show=\"visible\" @click=\"clickMask\">\n <transition name=\"toup\">\n <div class=\"vue-picker\" ref=\"picker\" v-show=\"visible\">\n <Header v-if=\"showToolbar\"\n :cancelText=\"cancelText\"\n :confirmText=\"confirmText\"\n :title=\"title\"\n @cancel=\"cancel\"\n @confirm=\"confirm\" />\n <div class=\"content\" :style=\"{height: boxHeight + 'px'}\">\n <div class=\"colums\">\n <List :column=\"column1\"\n :boxHeight=\"boxHeight\"\n :itemHeight=\"itemHeight\"\n :defaultIndex=\"dIndex1\"\n :rowNumber=\"getRowNumber\"\n @change=\"change1\" />\n <List v-if=\"column2.length > 0\"\n :column=\"column2\"\n :boxHeight=\"boxHeight\"\n :itemHeight=\"itemHeight\"\n :defaultIndex=\"dIndex2\"\n :rowNumber=\"getRowNumber\"\n @change=\"change2\" />\n <List v-if=\"column3.length > 0\"\n :column=\"column3\"\n :boxHeight=\"boxHeight\"\n :itemHeight=\"itemHeight\"\n :defaultIndex=\"dIndex3\"\n :rowNumber=\"getRowNumber\"\n @change=\"change3\" />\n <List v-if=\"column4.length > 0\"\n :column=\"column4\"\n :boxHeight=\"boxHeight\"\n :itemHeight=\"itemHeight\"\n :defaultIndex=\"dIndex4\"\n :rowNumber=\"getRowNumber\"\n @change=\"change4\" />\n </div>\n <div class=\"mask\" :style=\"maskStyle\"></div>\n <div class=\"hairline\"></div>\n </div>\n </div>\n </transition>\n </div>\n </transition>\n</template>\n<script>\n import Header from './header.vue'\n import List from './list.vue'\n import { DEFTAULT_ITEM_HEIGHT } from './utils.js'\n export default {\n name: 'VuePicker',\n props: {\n visible: {\n type: Boolean,\n default: false\n },\n data: {\n type: Array,\n default: () => []\n },\n layer: {\n type: Number,\n default: 0\n },\n itemHeight: {\n type: [Number, String],\n default: DEFTAULT_ITEM_HEIGHT\n },\n defaultIndex: {\n type: [Number, Array],\n default: 0\n },\n cancelText: {\n type: String,\n default: '取消'\n },\n confirmText: {\n type: String,\n default: '确认'\n },\n title: {\n type: String,\n default: ''\n },\n showToolbar: {\n type: Boolean,\n default: false\n },\n maskClick: {\n type: Boolean,\n default: false\n },\n rowNumber: {\n type: Number,\n default: 5\n },\n appendToBody: {\n type: Boolean,\n default: false\n }\n },\n components: {\n Header,\n List\n },\n data () {\n return {\n column1: [],\n column2: [],\n column3: [],\n column4: [],\n dIndex1: 0,\n dIndex2: 0,\n dIndex3: 0,\n dIndex4: 0\n }\n },\n computed: {\n boxHeight () {\n let itemHeight = parseInt(this.itemHeight)\n itemHeight = itemHeight ? itemHeight : DEFTAULT_ITEM_HEIGHT\n return itemHeight * this.getRowNumber\n },\n getRowNumber () {\n if (this.rowNumber < 3) {\n return 3\n }\n return this.rowNumber % 2 === 0 ? this.rowNumber + 1 : this.rowNumber\n },\n maskStyle() {\n let style = { backgroundSize: '100% 88px' }\n if (this.getRowNumber === 3) {\n style = { backgroundSize: '100% 44px' }\n }\n return style\n }\n },\n methods: {\n clickMask () {\n if (this.maskClick) {\n this.looseBody()\n this.$emit('update:visible', false)\n }\n },\n formateData () {\n if (this.layer > 1) {\n this.setLinkColumn()\n } else {\n this.column1 = this.data[0] || []\n this.column2 = this.data[1] || []\n this.column3 = this.data[2] || []\n this.column4 = this.data[3] || []\n this.setNormalIndex()\n }\n },\n setLinkColumn () {\n if (this.layer === 2) {\n this.setLinkLayer2()\n } else if (this.layer === 3) {\n this.setLinkLayer2()\n this.setLinkLayer3()\n } else if (this.layer === 4) {\n this.setLinkLayer2()\n this.setLinkLayer3()\n this.setLinkLayer4()\n }\n },\n setLinkLayer2 () {\n const { defaultIndex } = this\n this.column1 = this.data || []\n if (typeof defaultIndex === 'number') {\n this.dIndex1 = defaultIndex\n this.dIndex2 = 0\n if (this.data.length > 1 && this.data[0].children) {\n this.column2 = this.data[0].children || []\n }\n } else if (Array.isArray(defaultIndex) && defaultIndex.length > 0){\n this.dIndex1 = defaultIndex[0] || 0\n this.column2 = this.data[this.dIndex1].children || []\n this.$nextTick(() => {\n if (this.column2.length - 1 < defaultIndex[1]) {\n this.dIndex2 = this.column2.length - 1\n } else {\n this.dIndex2 = defaultIndex[1] || 0\n }\n })\n }\n },\n setLinkLayer3 () {\n const { defaultIndex } = this\n if (typeof defaultIndex === 'number') {\n this.dIndex3 = 0\n if (this.column2.length > 1 && this.column2[0].children) {\n this.column3 = this.column2[0].children || []\n }\n } else if (Array.isArray(defaultIndex) && defaultIndex.length > 1){\n this.$nextTick(() => {\n this.column3 = this.column2[this.dIndex2].children || []\n this.$nextTick(() => {\n if (this.column3.length - 1 < defaultIndex[2]) {\n this.dIndex3 = this.column3.length - 1\n } else {\n this.dIndex3 = defaultIndex[2] || 0\n }\n })\n })\n }\n },\n setLinkLayer4 () {\n const { defaultIndex } = this\n if (typeof defaultIndex === 'number') {\n this.dIndex4 = 0\n if (this.column3.length > 1 && this.column3[0].children) {\n this.column4 = this.column3[0].children || []\n }\n } else if (Array.isArray(defaultIndex) && defaultIndex.length > 2){\n setTimeout(() => {\n this.column4 = this.column3[this.dIndex3].children || []\n this.$nextTick(() => {\n if (this.column4.length - 1 < defaultIndex[3]) {\n this.dIndex4 = this.column4.length - 1\n } else {\n this.dIndex4 = defaultIndex[3] || 0\n }\n })\n })\n }\n },\n setNormalIndex () {\n this.$nextTick(() => {\n const { defaultIndex } = this\n if (Array.isArray(defaultIndex)) {\n this.setDefaultIndex()\n } else {\n this.dIndex1 = Number(defaultIndex) || 0\n }\n })\n },\n setDefaultIndex () {\n const { indexArr } = this\n const self = this\n function next() {\n let promise = Promise.resolve()\n let index = 0\n while (index < self.data.length) {\n promise = promise.then(indexArr[index])\n index++\n }\n }\n next()\n },\n change (index, res) {\n this.result[index] = res\n this.$emit('change', this.result)\n },\n change1 (res) {\n if (res) {\n this.change(0, res)\n if (this.layer > 1) {\n this.dIndex2 = 0\n this.changeLink('column2', res)\n }\n }\n },\n change2 (res) {\n if (res) {\n this.change(1, res)\n if (this.layer > 2) {\n this.dIndex3 = 0\n this.changeLink('column3', res)\n }\n }\n },\n change3 (res) {\n if (res) {\n this.change(2, res)\n if (this.layer > 3) {\n this.dIndex4 = 0\n this.changeLink('column4', res)\n }\n }\n },\n change4 (res) {\n if (res) {\n this.change(3, res)\n }\n },\n changeLink (key, res) {\n if (this.layer) {\n // clearTimeout(this.linktimer)\n this.linktimer = setTimeout(() => {\n this[key] = res.children || []\n }, 1000 / 60)\n }\n },\n cancel () {\n this.looseBody()\n this.$emit('cancel')\n this.$emit('update:visible', false)\n },\n confirm () {\n this.looseBody()\n this.$emit('confirm', this.result)\n this.$emit('update:visible', false)\n },\n stopPropagation (e) {\n e.stopPropagation()\n },\n fixedBody() {\n const scrollTop = document.body.scrollTop || document.documentElement.scrollTop\n this.prevBodyCss = document.body.style.cssText\n document.body.style.cssText += 'position:fixed;width:100%;top:-' + scrollTop + 'px;'\n },\n looseBody() {\n const body = document.body\n const top = body.style.top\n body.style.cssText = this.prevBodyCss\n body.scrollTop = document.documentElement.scrollTop = -parseInt(top)\n body.style.top = ''\n },\n init() {\n this.result = []\n this.indexArr = [\n () => this.dIndex1 = this.defaultIndex[0] || 0,\n () => this.dIndex2 = this.defaultIndex[1] || 0,\n () => this.dIndex3 = this.defaultIndex[2] || 0,\n () => this.dIndex4 = this.defaultIndex[3] || 0\n ]\n this.formateData()\n }\n },\n created () {\n this.init()\n },\n mounted () {\n this.$refs.picker.addEventListener('click', this.stopPropagation)\n if (this.appendToBody) {\n document.body.appendChild(this.$el)\n }\n },\n watch: {\n visible (v) {\n if (v) {\n this.fixedBody()\n }\n },\n defaultIndex () {\n this.init()\n },\n data() {\n this.init()\n }\n },\n beforeDestroy () {\n this.$refs.picker.removeEventListener('click', this.stopPropagation)\n }\n }\n</script>\n<style lang=\"scss\" scoped>\n .pickerbox {\n position: fixed;\n width: 100vw;\n height: 100vh;\n left: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 9999;\n overflow: hidden;\n }\n .fade-enter-active, .fade-leave-active {\n transition: opacity .2s;\n }\n .fade-enter, .fade-leave-to {\n opacity: 0;\n }\n .toup-enter-active, .toup-leave-active {\n transition: transform .3s;\n }\n .toup-enter, .toup-leave-to {\n transform: translate3d(0, 100px, 0);\n }\n // ----\n .vue-picker {\n position: absolute;\n left: 0;\n bottom: 0;\n width: 100%;\n background-color: #fff;\n user-select: none;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: transparent;\n }\n .content {\n overflow: hidden;\n height: 220px;\n position: relative;\n display: flex;\n }\n .colums {\n display: flex;\n overflow: hidden;\n font-size: 16px;\n text-align: center;\n flex: 1;\n }\n .mask {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n width: 100%;\n height: 100%;\n background-image: linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));\n background-repeat: no-repeat;\n background-position: top, bottom;\n backface-visibility: hidden;\n pointer-events: none;\n background-size: 100% 88px;\n }\n .hairline {\n position: absolute;\n top: 50%;\n left: 0;\n z-index: 3;\n width: 100%;\n transform: translateY(-50%);\n pointer-events: none;\n height: 44px;\n &::after {\n position: absolute;\n box-sizing: border-box;\n content: ' ';\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n border-width: 1px 0;\n }\n }\n</style>\n",".pickerbox {\n position: fixed;\n width: 100vw;\n height: 100vh;\n left: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.7);\n z-index: 9999;\n overflow: hidden;\n}\n\n.fade-enter-active, .fade-leave-active {\n transition: opacity 0.2s;\n}\n\n.fade-enter, .fade-leave-to {\n opacity: 0;\n}\n\n.toup-enter-active, .toup-leave-active {\n transition: transform 0.3s;\n}\n\n.toup-enter, .toup-leave-to {\n transform: translate3d(0, 100px, 0);\n}\n\n.vue-picker {\n position: absolute;\n left: 0;\n bottom: 0;\n width: 100%;\n background-color: #fff;\n user-select: none;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: transparent;\n}\n\n.content {\n overflow: hidden;\n height: 220px;\n position: relative;\n display: flex;\n}\n\n.colums {\n display: flex;\n overflow: hidden;\n font-size: 16px;\n text-align: center;\n flex: 1;\n}\n\n.mask {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 2;\n width: 100%;\n height: 100%;\n background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.4)), linear-gradient(0deg, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.4));\n background-repeat: no-repeat;\n background-position: top, bottom;\n backface-visibility: hidden;\n pointer-events: none;\n background-size: 100% 88px;\n}\n\n.hairline {\n position: absolute;\n top: 50%;\n left: 0;\n z-index: 3;\n width: 100%;\n transform: translateY(-50%);\n pointer-events: none;\n height: 44px;\n}\n.hairline::after {\n position: absolute;\n box-sizing: border-box;\n content: \" \";\n pointer-events: none;\n top: -50%;\n right: -50%;\n bottom: -50%;\n left: -50%;\n border: 0 solid #ebedf0;\n -webkit-transform: scale(0.5);\n transform: scale(0.5);\n border-width: 1px 0;\n}\n\n/*# sourceMappingURL=index.vue.map */"]}, media: undefined });
  791. };
  792. /* scoped */
  793. const __vue_scope_id__$2 = "data-v-200a1302";
  794. /* module identifier */
  795. const __vue_module_identifier__$2 = undefined;
  796. /* functional template */
  797. const __vue_is_functional_template__$2 = false;
  798. /* style inject SSR */
  799. /* style inject shadow dom */
  800. var index = normalizeComponent(
  801. { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 },
  802. __vue_inject_styles__$2,
  803. __vue_script__$2,
  804. __vue_scope_id__$2,
  805. __vue_is_functional_template__$2,
  806. __vue_module_identifier__$2,
  807. false,
  808. createInjector,
  809. undefined,
  810. undefined
  811. );
  812. export default index;