steps.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <script>
  2. import StepNav from './step-nav'
  3. export default {
  4. name: 'ibps-steps',
  5. components: {
  6. StepNav
  7. },
  8. props: {
  9. value: Number,
  10. active: Number,
  11. space: [Number, String],
  12. direction: {
  13. type: String,
  14. default: 'horizontal'
  15. },
  16. alignCenter: Boolean,
  17. simple: Boolean,
  18. finishStatus: {
  19. type: String,
  20. default: 'finish'
  21. },
  22. processStatus: {
  23. type: String,
  24. default: 'process'
  25. },
  26. disabled: {
  27. type: Boolean,
  28. default: true
  29. }
  30. },
  31. provide() {
  32. return {
  33. rootSteps: this
  34. }
  35. },
  36. data() {
  37. return {
  38. currentActive: this.active,
  39. panes: []
  40. }
  41. },
  42. watch: {
  43. active(val, oldVal) {
  44. if (val !== oldVal) {
  45. this.setCurrentActive(val)
  46. }
  47. },
  48. value(val, oldVal) {
  49. if (val !== oldVal) {
  50. this.setCurrentActive(val)
  51. }
  52. },
  53. currentActive(value) {
  54. // if (this.$refs.nav) {
  55. // this.$nextTick(() => {
  56. // this.$refs.nav.$nextTick(_ => {
  57. // this.$refs.nav.scrollToActiveStep()
  58. // })
  59. // })
  60. // }
  61. }
  62. },
  63. created() {
  64. this.setCurrentActive(0)
  65. this.$on('step-nav-update', this.calcPaneInstances.bind(null, true))
  66. },
  67. mounted() {
  68. this.calcPaneInstances()
  69. },
  70. updated() {
  71. this.calcPaneInstances()
  72. },
  73. methods: {
  74. calcPaneInstances(isForceUpdate = false) {
  75. if (this.$slots.default) {
  76. const paneSlots = this.$slots.default.filter(vnode => {
  77. return vnode.tag &&
  78. vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ibps-step-pane'
  79. }
  80. )
  81. // update indeed
  82. const panes = paneSlots.map(({ componentInstance }) => componentInstance)
  83. const panesChanged = !(panes.length === this.panes.length && panes.every((pane, index) => pane === this.panes[index]))
  84. if (isForceUpdate || panesChanged) {
  85. this.panes = panes
  86. }
  87. } else if (this.panes.length !== 0) {
  88. this.panes = []
  89. }
  90. },
  91. handleStepClick(step, stepIndex, event) {
  92. this.$emit('step-click', stepIndex, step, event)
  93. if (this.disabled || step.disabled) return
  94. this.setCurrentActive(stepIndex)
  95. },
  96. setCurrentActive(value) {
  97. const changeCurrentActive = () => {
  98. this.currentActive = value
  99. this.$emit('input', value)
  100. }
  101. if (this.currentActive !== value && this.beforeLeave) {
  102. const before = this.beforeLeave(value, this.currentActive)
  103. if (before && before.then) {
  104. before
  105. .then(() => {
  106. changeCurrentActive()
  107. this.$refs.nav && this.$refs.nav.removeFocus()
  108. }, () => {
  109. })
  110. } else if (before !== false) {
  111. changeCurrentActive()
  112. }
  113. } else {
  114. changeCurrentActive()
  115. }
  116. }
  117. },
  118. render(h) {
  119. const {
  120. handleStepClick,
  121. panes,
  122. space,
  123. currentActive,
  124. direction,
  125. alignCenter,
  126. simple,
  127. finishStatus,
  128. processStatus
  129. } = this
  130. const stepData = {
  131. props: {
  132. onStepClick: handleStepClick,
  133. panes,
  134. space,
  135. active: currentActive,
  136. direction,
  137. alignCenter,
  138. simple,
  139. finishStatus,
  140. processStatus
  141. },
  142. ref: 'nav'
  143. }
  144. const header = (
  145. <step-nav { ...stepData }></step-nav>
  146. )
  147. const panels = (
  148. <div class='el-steps__content'>
  149. {this.$slots.default}
  150. </div>
  151. )
  152. return (
  153. <div>
  154. {header}
  155. {panels}
  156. </div>
  157. )
  158. }
  159. }
  160. </script>