diff --git a/.gitignore b/.gitignore index 9a8d54baf..01e2221be 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build tests_output selenium-debug.log TODOs.md +.idea diff --git a/shells/dev/target/index.js b/shells/dev/target/index.js index aa3b2b17a..6dc7e30a0 100644 --- a/shells/dev/target/index.js +++ b/shells/dev/target/index.js @@ -25,9 +25,9 @@ new Vue({ h(Counter), h(Target, { props: { msg: 'hi', ins: new MyClass() }}), h(Other), - h(Events), - h(NativeTypes), - h(Router) + h(Events, { key: 'foo' }), + h(NativeTypes, { key: new Date() }), + h(Router, { key: [] }) ]) }, data: { diff --git a/src/backend/index.js b/src/backend/index.js index df837190b..c85c097d6 100644 --- a/src/backend/index.js +++ b/src/backend/index.js @@ -284,6 +284,7 @@ function capture (instance, _, list) { const ret = { id: instance.__VUE_DEVTOOLS_UID__, name: getInstanceName(instance), + renderKey: getRenderKey(instance.$vnode ? instance.$vnode['key'] : null), inactive: !!instance._inactive, isFragment: !!instance._isFragment, children: instance.$children @@ -694,6 +695,20 @@ function getUniqueId (instance) { return `${rootVueId}:${instance._uid}` } +function getRenderKey (value) { + if (value == null) return + const type = typeof value + if (type === 'number') { + return value + } else if (type === 'string') { + return `'${value}'` + } else if (Array.isArray(value)) { + return 'Array' + } else { + return 'Object' + } +} + /** * Display a toast message. * @param {any} message HTML content diff --git a/src/devtools/views/components/ComponentInstance.vue b/src/devtools/views/components/ComponentInstance.vue index 9cf81a797..2dcf95977 100644 --- a/src/devtools/views/components/ComponentInstance.vue +++ b/src/devtools/views/components/ComponentInstance.vue @@ -12,7 +12,9 @@ @mouseenter="enter" @mouseleave="leave" :class="{ selected: selected }" - :style="{ paddingLeft: depth * 15 + 'px' }"> + :style="{ paddingLeft: depth * 15 + 'px' }" + > + - <{{ displayName }}> + + < + + {{ displayName }} + + + key={{instance.renderKey}} + + + > inactive + + +
import { mapState } from 'vuex' -import { classify, scrollIntoView } from '../../../util' +import { classify, scrollIntoView, UNDEFINED } from '../../../util' export default { name: 'ComponentInstance', + props: { instance: Object, depth: Number }, + created () { // expand root by default if (this.depth === 0) { this.expand() } }, + computed: { ...mapState('components', [ 'classifyComponents' ]), + scrollToExpanded () { return this.$store.state.components.scrollToExpanded }, + expanded () { return !!this.$store.state.components.expansionMap[this.instance.id] }, + selected () { return this.instance.id === this.$store.state.components.inspectedInstance.id }, + sortedChildren () { return this.instance.children.slice().sort((a, b) => { return a.top === b.top @@ -103,10 +124,16 @@ export default { : a.top - b.top }) }, + displayName () { return this.classifyComponents ? classify(this.instance.name) : this.instance.name + }, + + componentHasKey () { + return !!this.instance.renderKey && this.instance.renderKey !== UNDEFINED } }, + watch: { scrollToExpanded: { handler (value, oldValue) { @@ -117,16 +144,20 @@ export default { immediate: true } }, + methods: { toggle (event) { this.toggleWithValue(!this.expanded, event.altKey) }, + expand () { this.toggleWithValue(true) }, + collapse () { this.toggleWithValue(false) }, + toggleWithValue (val, recursive = false) { this.$store.dispatch('components/toggleInstance', { instance: this.instance, @@ -134,18 +165,23 @@ export default { recursive }) }, + select () { bridge.send('select-instance', this.instance.id) }, + enter () { bridge.send('enter-instance', this.instance.id) }, + leave () { bridge.send('leave-instance', this.instance.id) }, + scrollToInstance () { bridge.send('scroll-to-instance', this.instance.id) }, + scrollIntoView (center = true) { this.$nextTick(() => { scrollIntoView(this.$globalRefs.leftScroll, this.$refs.self, center) @@ -233,16 +269,29 @@ export default { color $component-color margin 0 1px +.attr + opacity .5 + font-size 12px + +.attr-title + color purple + .spacer - flex 100% 1 1 - width 0 + flex auto 1 1 .icon-button - font-size 16px + width 16px + height 16px .self:not(:hover) & visibility hidden .self.selected & >>> svg fill $white + +.self.selected + .attr + opacity 1 + .attr-title + color lighten($purple, 70%)