style:首页
Showing
8 changed files
with
810 additions
and
5 deletions
src/components/CheckBox/checkbox.vue
0 → 100644
| 1 | <template> | ||
| 2 | <label class="el-checkbox" :class="[ | ||
| 3 | border && checkboxSize ? 'el-checkbox--' + checkboxSize : '', | ||
| 4 | { 'is-disabled': isDisabled }, | ||
| 5 | { 'is-bordered': border }, | ||
| 6 | { 'is-checked': isChecked } | ||
| 7 | ]" :id="id"> | ||
| 8 | <span class="el-checkbox__input" :class="{ | ||
| 9 | 'is-disabled': isDisabled, | ||
| 10 | 'is-checked': isChecked, | ||
| 11 | 'is-indeterminate': indeterminate, | ||
| 12 | 'is-focus': focus | ||
| 13 | }" :tabindex="indeterminate ? 0 : false" :role="indeterminate ? 'checkbox' : false" | ||
| 14 | :aria-checked="indeterminate ? 'mixed' : false"> | ||
| 15 | <span class="el-checkbox__inner"></span> | ||
| 16 | <input v-if="trueLabel || falseLabel" class="el-checkbox__original" type="checkbox" | ||
| 17 | :aria-hidden="indeterminate ? 'true' : 'false'" :name="name" :disabled="isDisabled" :true-value="trueLabel" | ||
| 18 | :false-value="falseLabel" v-model="model" @change="handleChange" @focus="focus = true" @blur="focus = false"> | ||
| 19 | <input v-else class="el-checkbox__original" type="checkbox" :aria-hidden="indeterminate ? 'true' : 'false'" | ||
| 20 | :disabled="isDisabled" :value="label" :name="name" v-model="model" @change="handleChange" @focus="focus = true" | ||
| 21 | @blur="focus = false"> | ||
| 22 | </span> | ||
| 23 | <span class="el-checkbox__label"> | ||
| 24 | <slot></slot> | ||
| 25 | </span> | ||
| 26 | </label> | ||
| 27 | </template> | ||
| 28 | <script> | ||
| 29 | import Emitter from 'element-ui/src/mixins/emitter'; | ||
| 30 | |||
| 31 | export default { | ||
| 32 | name: 'ElCheckbox', | ||
| 33 | |||
| 34 | mixins: [Emitter], | ||
| 35 | |||
| 36 | inject: { | ||
| 37 | elForm: { | ||
| 38 | default: '' | ||
| 39 | }, | ||
| 40 | elFormItem: { | ||
| 41 | default: '' | ||
| 42 | } | ||
| 43 | }, | ||
| 44 | |||
| 45 | componentName: 'ElCheckbox', | ||
| 46 | |||
| 47 | data () { | ||
| 48 | return { | ||
| 49 | selfModel: false, | ||
| 50 | focus: false, | ||
| 51 | isLimitExceeded: false | ||
| 52 | }; | ||
| 53 | }, | ||
| 54 | |||
| 55 | computed: { | ||
| 56 | model: { | ||
| 57 | get () { | ||
| 58 | return this.isGroup | ||
| 59 | ? this.store : this.value !== undefined | ||
| 60 | ? this.value : this.selfModel; | ||
| 61 | }, | ||
| 62 | |||
| 63 | set (val) { | ||
| 64 | if (this.isGroup) { | ||
| 65 | this.isLimitExceeded = false; | ||
| 66 | (this._checkboxGroup.min !== undefined && | ||
| 67 | val.length < this._checkboxGroup.min && | ||
| 68 | (this.isLimitExceeded = true)); | ||
| 69 | |||
| 70 | (this._checkboxGroup.max !== undefined && | ||
| 71 | val.length > this._checkboxGroup.max && | ||
| 72 | (this.isLimitExceeded = true)); | ||
| 73 | |||
| 74 | this.isLimitExceeded === false && | ||
| 75 | this.dispatch('ElCheckboxGroup', 'input', [val]); | ||
| 76 | } else { | ||
| 77 | this.$emit('input', val); | ||
| 78 | this.selfModel = val; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | }, | ||
| 82 | |||
| 83 | isChecked () { | ||
| 84 | if ({}.toString.call(this.model) === '[object Boolean]') { | ||
| 85 | return this.model; | ||
| 86 | } else if (Array.isArray(this.model)) { | ||
| 87 | return this.model.indexOf(this.label) > -1; | ||
| 88 | } else if (this.model !== null && this.model !== undefined) { | ||
| 89 | return this.model === this.trueLabel; | ||
| 90 | } | ||
| 91 | }, | ||
| 92 | |||
| 93 | isGroup () { | ||
| 94 | let parent = this.$parent; | ||
| 95 | while (parent) { | ||
| 96 | if (parent.$options.componentName !== 'ElCheckboxGroup') { | ||
| 97 | parent = parent.$parent; | ||
| 98 | } else { | ||
| 99 | this._checkboxGroup = parent; | ||
| 100 | return true; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | return false; | ||
| 104 | }, | ||
| 105 | |||
| 106 | store () { | ||
| 107 | return this._checkboxGroup ? this._checkboxGroup.value : this.value; | ||
| 108 | }, | ||
| 109 | |||
| 110 | /* used to make the isDisabled judgment under max/min props */ | ||
| 111 | isLimitDisabled () { | ||
| 112 | const { max, min } = this._checkboxGroup; | ||
| 113 | return !!(max || min) && | ||
| 114 | (this.model.length >= max && !this.isChecked) || | ||
| 115 | (this.model.length <= min && this.isChecked); | ||
| 116 | }, | ||
| 117 | |||
| 118 | isDisabled () { | ||
| 119 | return this.isGroup | ||
| 120 | ? this._checkboxGroup.disabled || this.disabled || (this.elForm || {}).disabled || this.isLimitDisabled | ||
| 121 | : this.disabled || (this.elForm || {}).disabled; | ||
| 122 | }, | ||
| 123 | |||
| 124 | _elFormItemSize () { | ||
| 125 | return (this.elFormItem || {}).elFormItemSize; | ||
| 126 | }, | ||
| 127 | |||
| 128 | checkboxSize () { | ||
| 129 | const temCheckboxSize = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size; | ||
| 130 | return this.isGroup | ||
| 131 | ? this._checkboxGroup.checkboxGroupSize || temCheckboxSize | ||
| 132 | : temCheckboxSize; | ||
| 133 | } | ||
| 134 | }, | ||
| 135 | |||
| 136 | props: { | ||
| 137 | value: {}, | ||
| 138 | label: {}, | ||
| 139 | indeterminate: Boolean, | ||
| 140 | disabled: Boolean, | ||
| 141 | checked: Boolean, | ||
| 142 | name: String, | ||
| 143 | trueLabel: [String, Number], | ||
| 144 | falseLabel: [String, Number], | ||
| 145 | id: String, /* 当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系*/ | ||
| 146 | controls: String, /* 当indeterminate为真时,为controls提供相关连的checkbox的id,表明元素间的控制关系*/ | ||
| 147 | border: Boolean, | ||
| 148 | size: String | ||
| 149 | }, | ||
| 150 | |||
| 151 | methods: { | ||
| 152 | addToStore () { | ||
| 153 | if ( | ||
| 154 | Array.isArray(this.model) && | ||
| 155 | this.model.indexOf(this.label) === -1 | ||
| 156 | ) { | ||
| 157 | this.model.push(this.label); | ||
| 158 | } else { | ||
| 159 | this.model = this.trueLabel || true; | ||
| 160 | } | ||
| 161 | }, | ||
| 162 | handleChange (ev) { | ||
| 163 | if (this.isLimitExceeded) return; | ||
| 164 | let value; | ||
| 165 | if (ev.target.checked) { | ||
| 166 | value = this.trueLabel === undefined ? true : this.trueLabel; | ||
| 167 | } else { | ||
| 168 | value = this.falseLabel === undefined ? false : this.falseLabel; | ||
| 169 | } | ||
| 170 | this.$emit('change', value, ev); | ||
| 171 | this.$nextTick(() => { | ||
| 172 | if (this.isGroup) { | ||
| 173 | this.dispatch('ElCheckboxGroup', 'change', [this._checkboxGroup.value]); | ||
| 174 | } | ||
| 175 | }); | ||
| 176 | } | ||
| 177 | }, | ||
| 178 | |||
| 179 | created () { | ||
| 180 | this.checked && this.addToStore(); | ||
| 181 | }, | ||
| 182 | mounted () { // 为indeterminate元素 添加aria-controls 属性 | ||
| 183 | if (this.indeterminate) { | ||
| 184 | this.$el.setAttribute('aria-controls', this.controls); | ||
| 185 | } | ||
| 186 | }, | ||
| 187 | |||
| 188 | watch: { | ||
| 189 | value (value) { | ||
| 190 | this.dispatch('ElFormItem', 'el.form.change', value); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | }; | ||
| 194 | </script> |
src/components/Tree/src/model/node.js
0 → 100644
This diff is collapsed.
Click to expand it.
src/components/Tree/src/model/tree-store.js
0 → 100644
| 1 | import Node from './node'; | ||
| 2 | import { getNodeKey } from './util'; | ||
| 3 | |||
| 4 | export default class TreeStore { | ||
| 5 | constructor(options) { | ||
| 6 | this.currentNode = null; | ||
| 7 | this.currentNodeKey = null; | ||
| 8 | |||
| 9 | for (let option in options) { | ||
| 10 | if (options.hasOwnProperty(option)) { | ||
| 11 | this[option] = options[option]; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | this.nodesMap = {}; | ||
| 16 | |||
| 17 | this.root = new Node({ | ||
| 18 | data: this.data, | ||
| 19 | store: this | ||
| 20 | }); | ||
| 21 | |||
| 22 | if (this.lazy && this.load) { | ||
| 23 | const loadFn = this.load; | ||
| 24 | loadFn(this.root, (data) => { | ||
| 25 | this.root.doCreateChildren(data); | ||
| 26 | this._initDefaultCheckedNodes(); | ||
| 27 | }); | ||
| 28 | } else { | ||
| 29 | this._initDefaultCheckedNodes(); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | filter(value) { | ||
| 34 | const filterNodeMethod = this.filterNodeMethod; | ||
| 35 | const lazy = this.lazy; | ||
| 36 | const traverse = function(node) { | ||
| 37 | const childNodes = node.root ? node.root.childNodes : node.childNodes; | ||
| 38 | |||
| 39 | childNodes.forEach((child) => { | ||
| 40 | child.visible = filterNodeMethod.call(child, value, child.data, child); | ||
| 41 | |||
| 42 | traverse(child); | ||
| 43 | }); | ||
| 44 | |||
| 45 | if (!node.visible && childNodes.length) { | ||
| 46 | let allHidden = true; | ||
| 47 | allHidden = !childNodes.some(child => child.visible); | ||
| 48 | |||
| 49 | if (node.root) { | ||
| 50 | node.root.visible = allHidden === false; | ||
| 51 | } else { | ||
| 52 | node.visible = allHidden === false; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | if (!value) return; | ||
| 56 | |||
| 57 | if (node.visible && !node.isLeaf && !lazy) node.expand(); | ||
| 58 | }; | ||
| 59 | |||
| 60 | traverse(this); | ||
| 61 | } | ||
| 62 | |||
| 63 | setData(newVal) { | ||
| 64 | const instanceChanged = newVal !== this.root.data; | ||
| 65 | if (instanceChanged) { | ||
| 66 | this.root.setData(newVal); | ||
| 67 | this._initDefaultCheckedNodes(); | ||
| 68 | } else { | ||
| 69 | this.root.updateChildren(); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | getNode(data) { | ||
| 74 | if (data instanceof Node) return data; | ||
| 75 | const key = typeof data !== 'object' ? data : getNodeKey(this.key, data); | ||
| 76 | return this.nodesMap[key] || null; | ||
| 77 | } | ||
| 78 | |||
| 79 | insertBefore(data, refData) { | ||
| 80 | const refNode = this.getNode(refData); | ||
| 81 | refNode.parent.insertBefore({ data }, refNode); | ||
| 82 | } | ||
| 83 | |||
| 84 | insertAfter(data, refData) { | ||
| 85 | const refNode = this.getNode(refData); | ||
| 86 | refNode.parent.insertAfter({ data }, refNode); | ||
| 87 | } | ||
| 88 | |||
| 89 | remove(data) { | ||
| 90 | const node = this.getNode(data); | ||
| 91 | |||
| 92 | if (node && node.parent) { | ||
| 93 | if (node === this.currentNode) { | ||
| 94 | this.currentNode = null; | ||
| 95 | } | ||
| 96 | node.parent.removeChild(node); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | append(data, parentData) { | ||
| 101 | const parentNode = parentData ? this.getNode(parentData) : this.root; | ||
| 102 | |||
| 103 | if (parentNode) { | ||
| 104 | parentNode.insertChild({ data }); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | _initDefaultCheckedNodes() { | ||
| 109 | const defaultCheckedKeys = this.defaultCheckedKeys || []; | ||
| 110 | const nodesMap = this.nodesMap; | ||
| 111 | |||
| 112 | defaultCheckedKeys.forEach((checkedKey) => { | ||
| 113 | const node = nodesMap[checkedKey]; | ||
| 114 | |||
| 115 | if (node) { | ||
| 116 | node.setChecked(true, !this.checkStrictly); | ||
| 117 | } | ||
| 118 | }); | ||
| 119 | } | ||
| 120 | |||
| 121 | _initDefaultCheckedNode(node) { | ||
| 122 | const defaultCheckedKeys = this.defaultCheckedKeys || []; | ||
| 123 | |||
| 124 | if (defaultCheckedKeys.indexOf(node.key) !== -1) { | ||
| 125 | node.setChecked(true, !this.checkStrictly); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | setDefaultCheckedKey(newVal) { | ||
| 130 | if (newVal !== this.defaultCheckedKeys) { | ||
| 131 | this.defaultCheckedKeys = newVal; | ||
| 132 | this._initDefaultCheckedNodes(); | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | registerNode(node) { | ||
| 137 | const key = this.key; | ||
| 138 | if (!key || !node || !node.data) return; | ||
| 139 | |||
| 140 | const nodeKey = node.key; | ||
| 141 | if (nodeKey !== undefined) this.nodesMap[node.key] = node; | ||
| 142 | } | ||
| 143 | |||
| 144 | deregisterNode(node) { | ||
| 145 | const key = this.key; | ||
| 146 | if (!key || !node || !node.data) return; | ||
| 147 | |||
| 148 | node.childNodes.forEach(child => { | ||
| 149 | this.deregisterNode(child); | ||
| 150 | }); | ||
| 151 | |||
| 152 | delete this.nodesMap[node.key]; | ||
| 153 | } | ||
| 154 | |||
| 155 | getCheckedNodes(leafOnly = false, includeHalfChecked = false) { | ||
| 156 | const checkedNodes = []; | ||
| 157 | const traverse = function(node) { | ||
| 158 | const childNodes = node.root ? node.root.childNodes : node.childNodes; | ||
| 159 | |||
| 160 | childNodes.forEach((child) => { | ||
| 161 | if ((child.checked || (includeHalfChecked && child.indeterminate)) && (!leafOnly || (leafOnly && child.isLeaf))) { | ||
| 162 | checkedNodes.push(child.data); | ||
| 163 | } | ||
| 164 | |||
| 165 | traverse(child); | ||
| 166 | }); | ||
| 167 | }; | ||
| 168 | |||
| 169 | traverse(this); | ||
| 170 | |||
| 171 | return checkedNodes; | ||
| 172 | } | ||
| 173 | |||
| 174 | getCheckedKeys(leafOnly = false) { | ||
| 175 | return this.getCheckedNodes(leafOnly).map((data) => (data || {})[this.key]); | ||
| 176 | } | ||
| 177 | |||
| 178 | getHalfCheckedNodes() { | ||
| 179 | const nodes = []; | ||
| 180 | const traverse = function(node) { | ||
| 181 | const childNodes = node.root ? node.root.childNodes : node.childNodes; | ||
| 182 | |||
| 183 | childNodes.forEach((child) => { | ||
| 184 | if (child.indeterminate) { | ||
| 185 | nodes.push(child.data); | ||
| 186 | } | ||
| 187 | |||
| 188 | traverse(child); | ||
| 189 | }); | ||
| 190 | }; | ||
| 191 | |||
| 192 | traverse(this); | ||
| 193 | |||
| 194 | return nodes; | ||
| 195 | } | ||
| 196 | |||
| 197 | getHalfCheckedKeys() { | ||
| 198 | return this.getHalfCheckedNodes().map((data) => (data || {})[this.key]); | ||
| 199 | } | ||
| 200 | |||
| 201 | _getAllNodes() { | ||
| 202 | const allNodes = []; | ||
| 203 | const nodesMap = this.nodesMap; | ||
| 204 | for (let nodeKey in nodesMap) { | ||
| 205 | if (nodesMap.hasOwnProperty(nodeKey)) { | ||
| 206 | allNodes.push(nodesMap[nodeKey]); | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | return allNodes; | ||
| 211 | } | ||
| 212 | |||
| 213 | updateChildren(key, data) { | ||
| 214 | const node = this.nodesMap[key]; | ||
| 215 | if (!node) return; | ||
| 216 | const childNodes = node.childNodes; | ||
| 217 | for (let i = childNodes.length - 1; i >= 0; i--) { | ||
| 218 | const child = childNodes[i]; | ||
| 219 | this.remove(child.data); | ||
| 220 | } | ||
| 221 | for (let i = 0, j = data.length; i < j; i++) { | ||
| 222 | const child = data[i]; | ||
| 223 | this.append(child, node.data); | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | _setCheckedKeys(key, leafOnly = false, checkedKeys) { | ||
| 228 | const allNodes = this._getAllNodes().sort((a, b) => b.level - a.level); | ||
| 229 | const cache = Object.create(null); | ||
| 230 | const keys = Object.keys(checkedKeys); | ||
| 231 | allNodes.forEach(node => node.setChecked(false, false)); | ||
| 232 | for (let i = 0, j = allNodes.length; i < j; i++) { | ||
| 233 | const node = allNodes[i]; | ||
| 234 | const nodeKey = node.data[key].toString(); | ||
| 235 | let checked = keys.indexOf(nodeKey) > -1; | ||
| 236 | if (!checked) { | ||
| 237 | if (node.checked && !cache[nodeKey]) { | ||
| 238 | node.setChecked(false, false); | ||
| 239 | } | ||
| 240 | continue; | ||
| 241 | } | ||
| 242 | |||
| 243 | let parent = node.parent; | ||
| 244 | while (parent && parent.level > 0) { | ||
| 245 | cache[parent.data[key]] = true; | ||
| 246 | parent = parent.parent; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (node.isLeaf || this.checkStrictly) { | ||
| 250 | node.setChecked(true, false); | ||
| 251 | continue; | ||
| 252 | } | ||
| 253 | node.setChecked(true, true); | ||
| 254 | |||
| 255 | if (leafOnly) { | ||
| 256 | node.setChecked(false, false); | ||
| 257 | const traverse = function(node) { | ||
| 258 | const childNodes = node.childNodes; | ||
| 259 | childNodes.forEach((child) => { | ||
| 260 | if (!child.isLeaf) { | ||
| 261 | child.setChecked(false, false); | ||
| 262 | } | ||
| 263 | traverse(child); | ||
| 264 | }); | ||
| 265 | }; | ||
| 266 | traverse(node); | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | setCheckedNodes(array, leafOnly = false) { | ||
| 272 | const key = this.key; | ||
| 273 | const checkedKeys = {}; | ||
| 274 | array.forEach((item) => { | ||
| 275 | checkedKeys[(item || {})[key]] = true; | ||
| 276 | }); | ||
| 277 | |||
| 278 | this._setCheckedKeys(key, leafOnly, checkedKeys); | ||
| 279 | } | ||
| 280 | |||
| 281 | setCheckedKeys(keys, leafOnly = false) { | ||
| 282 | this.defaultCheckedKeys = keys; | ||
| 283 | const key = this.key; | ||
| 284 | const checkedKeys = {}; | ||
| 285 | keys.forEach((key) => { | ||
| 286 | checkedKeys[key] = true; | ||
| 287 | }); | ||
| 288 | |||
| 289 | this._setCheckedKeys(key, leafOnly, checkedKeys); | ||
| 290 | } | ||
| 291 | |||
| 292 | setDefaultExpandedKeys(keys) { | ||
| 293 | keys = keys || []; | ||
| 294 | this.defaultExpandedKeys = keys; | ||
| 295 | |||
| 296 | keys.forEach((key) => { | ||
| 297 | const node = this.getNode(key); | ||
| 298 | if (node) node.expand(null, this.autoExpandParent); | ||
| 299 | }); | ||
| 300 | } | ||
| 301 | |||
| 302 | setChecked(data, checked, deep) { | ||
| 303 | const node = this.getNode(data); | ||
| 304 | |||
| 305 | if (node) { | ||
| 306 | node.setChecked(!!checked, deep); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | getCurrentNode() { | ||
| 311 | return this.currentNode; | ||
| 312 | } | ||
| 313 | |||
| 314 | setCurrentNode(currentNode) { | ||
| 315 | const prevCurrentNode = this.currentNode; | ||
| 316 | if (prevCurrentNode) { | ||
| 317 | prevCurrentNode.isCurrent = false; | ||
| 318 | } | ||
| 319 | this.currentNode = currentNode; | ||
| 320 | this.currentNode.isCurrent = true; | ||
| 321 | } | ||
| 322 | |||
| 323 | setUserCurrentNode(node) { | ||
| 324 | const key = node[this.key]; | ||
| 325 | const currNode = this.nodesMap[key]; | ||
| 326 | this.setCurrentNode(currNode); | ||
| 327 | } | ||
| 328 | |||
| 329 | setCurrentNodeKey(key) { | ||
| 330 | if (key === null || key === undefined) { | ||
| 331 | this.currentNode && (this.currentNode.isCurrent = false); | ||
| 332 | this.currentNode = null; | ||
| 333 | return; | ||
| 334 | } | ||
| 335 | const node = this.getNode(key); | ||
| 336 | if (node) { | ||
| 337 | this.setCurrentNode(node); | ||
| 338 | } | ||
| 339 | } | ||
| 340 | }; |
src/components/Tree/src/model/util.js
0 → 100644
| 1 | export const NODE_KEY = '$treeNodeId'; | ||
| 2 | |||
| 3 | export const markNodeData = function(node, data) { | ||
| 4 | if (!data || data[NODE_KEY]) return; | ||
| 5 | Object.defineProperty(data, NODE_KEY, { | ||
| 6 | value: node.id, | ||
| 7 | enumerable: false, | ||
| 8 | configurable: false, | ||
| 9 | writable: false | ||
| 10 | }); | ||
| 11 | }; | ||
| 12 | |||
| 13 | export const getNodeKey = function(key, data) { | ||
| 14 | if (!key) return data[NODE_KEY]; | ||
| 15 | return data[key]; | ||
| 16 | }; | ||
| 17 | |||
| 18 | export const findNearestComponent = (element, componentName) => { | ||
| 19 | let target = element; | ||
| 20 | while (target && target.tagName !== 'BODY') { | ||
| 21 | if (target.__vue__ && target.__vue__.$options.name === componentName) { | ||
| 22 | return target.__vue__; | ||
| 23 | } | ||
| 24 | target = target.parentNode; | ||
| 25 | } | ||
| 26 | return null; | ||
| 27 | }; |
src/components/Tree/src/tree-node.vue
0 → 100644
| 1 | <template> | ||
| 2 | <div class="el-tree-node" @click.stop="handleClick" @contextmenu="($event) => this.handleContextMenu($event)" | ||
| 3 | v-show="node.visible" :class="{ | ||
| 4 | 'is-expanded': expanded, | ||
| 5 | 'is-current': node.isCurrent, | ||
| 6 | 'is-hidden': !node.visible, | ||
| 7 | 'is-focusable': !node.disabled, | ||
| 8 | 'is-checked': !node.disabled && node.checked | ||
| 9 | }" role="treeitem" tabindex="-1" :aria-expanded="expanded" :aria-disabled="node.disabled" | ||
| 10 | :aria-checked="node.checked" :draggable="tree.draggable" @dragstart.stop="handleDragStart" | ||
| 11 | @dragover.stop="handleDragOver" @dragend.stop="handleDragEnd" @drop.stop="handleDrop" ref="node"> | ||
| 12 | <div class="el-tree-node__content" :style="{ 'padding-left': (node.level - 1) * tree.indent + 'px' }"> | ||
| 13 | <span @click.stop="handleExpandIconClick" :class="[ | ||
| 14 | { 'is-leaf': node.isLeaf, expanded: !node.isLeaf && expanded }, | ||
| 15 | 'el-tree-node__expand-icon', | ||
| 16 | tree.iconClass ? tree.iconClass : 'el-icon-caret-right' | ||
| 17 | ]"> | ||
| 18 | </span> | ||
| 19 | <CheckBox v-if="showCheckbox" v-model="node.checked" :indeterminate="node.indeterminate" | ||
| 20 | :disabled="!!node.disabled" @click.native.stop @change="handleCheckChange"> | ||
| 21 | <node-content :node="node"></node-content> | ||
| 22 | </CheckBox> | ||
| 23 | |||
| 24 | </div> | ||
| 25 | <el-collapse-transition> | ||
| 26 | <div class="el-tree-node__children" v-if="!renderAfterExpand || childNodeRendered" v-show="expanded" role="group" | ||
| 27 | :aria-expanded="expanded"> | ||
| 28 | <el-tree-node :render-content="renderContent" v-for="child in node.childNodes" | ||
| 29 | :render-after-expand="renderAfterExpand" :show-checkbox="showCheckbox" :key="getNodeKey(child)" :node="child" | ||
| 30 | @node-expand="handleChildNodeExpand"> | ||
| 31 | </el-tree-node> | ||
| 32 | </div> | ||
| 33 | </el-collapse-transition> | ||
| 34 | </div> | ||
| 35 | </template> | ||
| 36 | |||
| 37 | <script type="text/jsx"> | ||
| 38 | import CheckBox from '@/components/CheckBox/checkbox' | ||
| 39 | import ElCollapseTransition from 'element-ui/src/transitions/collapse-transition'; | ||
| 40 | import ElCheckbox from 'element-ui/packages/checkbox'; | ||
| 41 | import emitter from 'element-ui/src/mixins/emitter'; | ||
| 42 | import { getNodeKey } from './model/util'; | ||
| 43 | |||
| 44 | export default { | ||
| 45 | name: 'ElTreeNode', | ||
| 46 | |||
| 47 | componentName: 'ElTreeNode', | ||
| 48 | |||
| 49 | mixins: [emitter], | ||
| 50 | |||
| 51 | props: { | ||
| 52 | node: { | ||
| 53 | default () { | ||
| 54 | return {}; | ||
| 55 | } | ||
| 56 | }, | ||
| 57 | props: {}, | ||
| 58 | renderContent: Function, | ||
| 59 | renderAfterExpand: { | ||
| 60 | type: Boolean, | ||
| 61 | default: true | ||
| 62 | }, | ||
| 63 | showCheckbox: { | ||
| 64 | type: Boolean, | ||
| 65 | default: false | ||
| 66 | } | ||
| 67 | }, | ||
| 68 | |||
| 69 | components: { | ||
| 70 | ElCollapseTransition, | ||
| 71 | ElCheckbox, | ||
| 72 | CheckBox, | ||
| 73 | NodeContent: { | ||
| 74 | props: { | ||
| 75 | node: { | ||
| 76 | required: true | ||
| 77 | } | ||
| 78 | }, | ||
| 79 | render (h) { | ||
| 80 | const parent = this.$parent; | ||
| 81 | const tree = parent.tree; | ||
| 82 | const node = this.node; | ||
| 83 | const { data, store } = node; | ||
| 84 | return ( | ||
| 85 | <span class="el-tree-node__label">{node.label}</span> | ||
| 86 | ); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | }, | ||
| 90 | |||
| 91 | data () { | ||
| 92 | return { | ||
| 93 | tree: null, | ||
| 94 | expanded: false, | ||
| 95 | childNodeRendered: false, | ||
| 96 | oldChecked: null, | ||
| 97 | oldIndeterminate: null | ||
| 98 | }; | ||
| 99 | }, | ||
| 100 | |||
| 101 | watch: { | ||
| 102 | 'node.indeterminate' (val) { | ||
| 103 | this.handleSelectChange(this.node.checked, val); | ||
| 104 | }, | ||
| 105 | |||
| 106 | 'node.checked' (val) { | ||
| 107 | this.handleSelectChange(val, this.node.indeterminate); | ||
| 108 | }, | ||
| 109 | |||
| 110 | 'node.expanded' (val) { | ||
| 111 | this.$nextTick(() => this.expanded = val); | ||
| 112 | if (val) { | ||
| 113 | this.childNodeRendered = true; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | }, | ||
| 117 | |||
| 118 | methods: { | ||
| 119 | getNodeKey (node) { | ||
| 120 | return getNodeKey(this.tree.nodeKey, node.data); | ||
| 121 | }, | ||
| 122 | |||
| 123 | handleSelectChange (checked, indeterminate) { | ||
| 124 | if (this.oldChecked !== checked && this.oldIndeterminate !== indeterminate) { | ||
| 125 | this.tree.$emit('check-change', this.node.data, checked, indeterminate); | ||
| 126 | } | ||
| 127 | this.oldChecked = checked; | ||
| 128 | this.indeterminate = indeterminate; | ||
| 129 | }, | ||
| 130 | |||
| 131 | handleClick () { | ||
| 132 | const store = this.tree.store; | ||
| 133 | store.setCurrentNode(this.node); | ||
| 134 | this.tree.$emit('current-change', store.currentNode ? store.currentNode.data : null, store.currentNode); | ||
| 135 | this.tree.currentNode = this; | ||
| 136 | if (this.tree.expandOnClickNode) { | ||
| 137 | this.handleExpandIconClick(); | ||
| 138 | } | ||
| 139 | if (this.tree.checkOnClickNode && !this.node.disabled) { | ||
| 140 | this.handleCheckChange(null, { | ||
| 141 | target: { checked: !this.node.checked } | ||
| 142 | }); | ||
| 143 | } | ||
| 144 | this.tree.$emit('node-click', this.node.data, this.node, this); | ||
| 145 | }, | ||
| 146 | |||
| 147 | handleContextMenu (event) { | ||
| 148 | if (this.tree._events['node-contextmenu'] && this.tree._events['node-contextmenu'].length > 0) { | ||
| 149 | event.stopPropagation(); | ||
| 150 | event.preventDefault(); | ||
| 151 | } | ||
| 152 | this.tree.$emit('node-contextmenu', event, this.node.data, this.node, this); | ||
| 153 | }, | ||
| 154 | |||
| 155 | handleExpandIconClick () { | ||
| 156 | if (this.node.isLeaf) return; | ||
| 157 | if (this.expanded) { | ||
| 158 | this.tree.$emit('node-collapse', this.node.data, this.node, this); | ||
| 159 | this.node.collapse(); | ||
| 160 | } else { | ||
| 161 | this.node.expand(); | ||
| 162 | this.$emit('node-expand', this.node.data, this.node, this); | ||
| 163 | } | ||
| 164 | }, | ||
| 165 | |||
| 166 | handleCheckChange (value, ev) { | ||
| 167 | this.node.setChecked(ev.target.checked, !this.tree.checkStrictly); | ||
| 168 | this.$nextTick(() => { | ||
| 169 | const store = this.tree.store; | ||
| 170 | this.tree.$emit('check', this.node.data, { | ||
| 171 | checkedNodes: store.getCheckedNodes(), | ||
| 172 | checkedKeys: store.getCheckedKeys(), | ||
| 173 | halfCheckedNodes: store.getHalfCheckedNodes(), | ||
| 174 | halfCheckedKeys: store.getHalfCheckedKeys(), | ||
| 175 | }); | ||
| 176 | }); | ||
| 177 | }, | ||
| 178 | |||
| 179 | handleChildNodeExpand (nodeData, node, instance) { | ||
| 180 | this.broadcast('ElTreeNode', 'tree-node-expand', node); | ||
| 181 | this.tree.$emit('node-expand', nodeData, node, instance); | ||
| 182 | }, | ||
| 183 | |||
| 184 | handleDragStart (event) { | ||
| 185 | if (!this.tree.draggable) return; | ||
| 186 | this.tree.$emit('tree-node-drag-start', event, this); | ||
| 187 | }, | ||
| 188 | |||
| 189 | handleDragOver (event) { | ||
| 190 | if (!this.tree.draggable) return; | ||
| 191 | this.tree.$emit('tree-node-drag-over', event, this); | ||
| 192 | event.preventDefault(); | ||
| 193 | }, | ||
| 194 | |||
| 195 | handleDrop (event) { | ||
| 196 | event.preventDefault(); | ||
| 197 | }, | ||
| 198 | |||
| 199 | handleDragEnd (event) { | ||
| 200 | if (!this.tree.draggable) return; | ||
| 201 | this.tree.$emit('tree-node-drag-end', event, this); | ||
| 202 | } | ||
| 203 | }, | ||
| 204 | |||
| 205 | created () { | ||
| 206 | const parent = this.$parent; | ||
| 207 | |||
| 208 | if (parent.isTree) { | ||
| 209 | this.tree = parent; | ||
| 210 | } else { | ||
| 211 | this.tree = parent.tree; | ||
| 212 | } | ||
| 213 | |||
| 214 | const tree = this.tree; | ||
| 215 | if (!tree) { | ||
| 216 | console.warn('Can not find node\'s tree.'); | ||
| 217 | } | ||
| 218 | |||
| 219 | const props = tree.props || {}; | ||
| 220 | const childrenKey = props['children'] || 'children'; | ||
| 221 | |||
| 222 | this.$watch(`node.data.${childrenKey}`, () => { | ||
| 223 | this.node.updateChildren(); | ||
| 224 | }); | ||
| 225 | |||
| 226 | if (this.node.expanded) { | ||
| 227 | this.expanded = true; | ||
| 228 | this.childNodeRendered = true; | ||
| 229 | } | ||
| 230 | |||
| 231 | if (this.tree.accordion) { | ||
| 232 | this.$on('tree-node-expand', node => { | ||
| 233 | if (this.node !== node) { | ||
| 234 | this.node.collapse(); | ||
| 235 | } | ||
| 236 | }); | ||
| 237 | } | ||
| 238 | } | ||
| 239 | }; | ||
| 240 | </script> |
src/components/Tree/src/tree.vue
0 → 100644
This diff is collapsed.
Click to expand it.
| 1 | <template> | 1 | <template> |
| 2 | <dialogBox title="配置常办项目" @submitForm="submitForm" saveButton="保存" :isFullscreen="false" width="50%" | 2 | <dialogBox title="配置常办项目" @submitForm="submitForm" saveButton="保存" :isFullscreen="false" width="50%" |
| 3 | @closeDialog="closeDialog" v-model="myValue"> | 3 | @closeDialog="closeDialog" v-model="myValue"> |
| 4 | <el-tree :data="projectList" show-checkbox node-key="id" :default-checked-keys="defaultCheckeds" ref="tree" | 4 | <Tree :data="projectList" show-checkbox node-key="id" :default-checked-keys="defaultCheckeds" ref="tree" |
| 5 | default-expand-all :props="defaultProps" @check-change="handleClick"></el-tree> | 5 | default-expand-all :props="defaultProps" @check-change="handleClick" /> |
| 6 | </dialogBox> | 6 | </dialogBox> |
| 7 | </template> | 7 | </template> |
| 8 | <script> | 8 | <script> |
| 9 | import { getMenuInfo } from "@/api/user.js"; | 9 | import { getMenuInfo } from "@/api/user.js"; |
| 10 | import Tree from "@/components/Tree/src/tree.vue" | ||
| 10 | import { saveFrequentProjectsList, getHomeFrequentProjects } from "@/api/user.js"; | 11 | import { saveFrequentProjectsList, getHomeFrequentProjects } from "@/api/user.js"; |
| 11 | export default { | 12 | export default { |
| 13 | components: { | ||
| 14 | Tree | ||
| 15 | }, | ||
| 12 | props: { | 16 | props: { |
| 13 | value: { type: Boolean, default: false }, | 17 | value: { type: Boolean, default: false }, |
| 14 | bindItem: { type: Array, default: [] } | 18 | bindItem: { type: Array, default: [] } |
| ... | @@ -73,8 +77,8 @@ export default { | ... | @@ -73,8 +77,8 @@ export default { |
| 73 | } | 77 | } |
| 74 | return arr | 78 | return arr |
| 75 | } | 79 | } |
| 76 | that.defaultCheckeds = lookForAllId() | 80 | this.defaultCheckeds = lookForAllId() |
| 77 | console.log(that.defaultCheckeds); | 81 | console.log(this.defaultCheckeds, 'that.defaultCheckedsthat.defaultCheckedsthat.defaultCheckeds'); |
| 78 | }, | 82 | }, |
| 79 | dealCheckedItem () { | 83 | dealCheckedItem () { |
| 80 | }, | 84 | }, | ... | ... |
| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | <el-card shadow="hover" :body-style="{ padding: '0' }" style="height:260px"> | 6 | <el-card shadow="hover" :body-style="{ padding: '0' }" style="height:260px"> |
| 7 | <div slot="header" class="flexst"> | 7 | <div slot="header" class="flexst"> |
| 8 | <h5 class="title">常办项目</h5> | 8 | <h5 class="title">常办项目</h5> |
| 9 | <el-button type="primary" @click="setFrequencyProject()">配置常办</el-button> | 9 | <el-button type="primary" @click="setFrequencyProject">配置常办</el-button> |
| 10 | </div> | 10 | </div> |
| 11 | <ul class="workbench flexst"> | 11 | <ul class="workbench flexst"> |
| 12 | <li v-for="(item, index) in projectList" @click="handleProject(item)" class="pointer" :key="index" | 12 | <li v-for="(item, index) in projectList" @click="handleProject(item)" class="pointer" :key="index" | ... | ... |
-
Please register or sign in to post a comment