Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

give the vue dev tool the ablity to select the correspond component w… #469

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 32 additions & 3 deletions src/backend/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,46 @@ function connect () {
}
})

bridge.on('select-instance', id => {
// when select element in dev tool element panel
//find the selected elment and select it in VUE component tree
bridge.on('element-inspected', uuid => {
function findParentComponent (instanceMap, uuid) {
let instanceContainer = []
instanceMap.forEach((instance, id) => {
let curSelectedDom = document.querySelector(`[data-v_track_id="${uuid}"]`)
let isAncestorInstance = instance.$el.contains(curSelectedDom)
if (isAncestorInstance) {
instanceContainer.push(instance)
}
})
//sort ancestor
instanceContainer.sort(function (m, n) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the sort for here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because when find the component containg the dom,there may be many.sort the component,and get the nearest component which is the selected one.

return m._uid < n._uid
})
return instanceContainer[0]
}

let selectedComponent = findParentComponent(instanceMap, uuid)
if (selectedComponent) {
let id = selectedComponent.__VUE_DEVTOOLS_UID__
selectInstance(id, true)
}
})

function selectInstance (id, isSelectedByInspector = false) {
currentInspectedId = id
const instance = instanceMap.get(id)
if (instance) {
if (instance && !isSelectedByInspector) {
scrollIntoView(instance)
highlight(instance)
}
bridge.send('select-instance-by-inspector', isSelectedByInspector)
bindToConsole(instance)
flush()
bridge.send('instance-details', stringify(getInstanceDetails(id)))
})
}

bridge.on('select-instance', selectInstance)

bridge.on('filter-instances', _filter => {
filter = _filter.toLowerCase()
Expand Down
3 changes: 3 additions & 0 deletions src/devtools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ function initApp (shell) {
bridge.on('instance-details', details => {
store.commit('components/RECEIVE_INSTANCE_DETAILS', parse(details))
})
bridge.on('select-instance-by-inspector', isByInspector => {
store.commit('components/SELECT_BY_INSPECTOR', isByInspector)
})

bridge.on('vuex:init', snapshot => {
store.commit('vuex/INIT', snapshot)
Expand Down
65 changes: 65 additions & 0 deletions src/devtools/views/components/ComponentTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import ActionHeader from 'components/ActionHeader.vue'
import ComponentInstance from './ComponentInstance.vue'

import keyNavMixin from '../../mixins/key-nav'
import { findPath } from 'src/util'

export default {
mixins: [keyNavMixin],
Expand All @@ -35,6 +36,11 @@ export default {
props: {
instances: Array
},
watch: {
'$store.state.components.inspectedInstance.id':function (newVal) {
this.intoView(newVal)
}
},
methods: {
filterInstances (e) {
bridge.send('filter-instances', e.target.value)
Expand Down Expand Up @@ -68,7 +74,66 @@ export default {
} else {
findByIndex(all, currentIndex + 1).select()
}
},
// listen element panel dom selected event
//and send select-dom event to notify content-script
listenDomSelected () {
let _this = this
function changeHandler () {
//return if not inspecting
/* if(!_this.$store.state.components.isInspectingComponent){
return
}*/
let uuid = Date.now()
chrome.devtools.inspectedWindow.eval(`$0.dataset.v_track_id=${uuid}`, ()=>{
bridge.send('element-inspected', uuid)
});
}
chrome.devtools.panels.elements.onSelectionChanged.addListener(changeHandler)
},
//scroll the selected component into view
intoView (selectedId) {
// if not inspect component from element panel, return
if (!this.$store.state.components.isSelectedByInspector) {
return
}
let root = {id: '-1:-1', children: this.instances}

let resolvedPaths = findPath(root, selectedId, (nodeId, id) => {
function getId (str) {
return str.split(':')[1]
}

return getId(nodeId) === getId(id)
})
resolvedPaths.slice(1).forEach((instance) => {
this.$store.dispatch('components/toggleInstance', {
instance,
expanded: true
})
})
function scrollIntoView (instance) {
if (instance.$el) {
instance.$el.scrollIntoView()
}
}

this.$nextTick(() => {
const all = getAllInstances(this.$refs.instances)
if (!all.length) {
return
}
all.forEach((instance) => {
if (instance.instance.id === selectedId) {
scrollIntoView(instance)
}
})
})
}
},

mounted () {
this.listenDomSelected()
}
}

Expand Down
6 changes: 5 additions & 1 deletion src/devtools/views/components/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const state = {
inspectedInstance: {},
instances: [],
expansionMap: {},
events: []
events: [],
isSelectByInspecting: false
}

const mutations = {
Expand All @@ -27,6 +28,9 @@ const mutations = {
},
TOGGLE_INSTANCE ({ expansionMap }, { id, expanded }) {
Vue.set(expansionMap, id, expanded)
},
SELECT_BY_INSPECTOR (state, isPassive) {
state.isSelectedByInspector = isPassive
}
}

Expand Down
33 changes: 33 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,36 @@ export function sortByKey (state) {
return 0
})
}

/**
* find a path to the specify node with the id.
* @param root
* @param id
* @param comparator
* @returns {*}
*/
export function findPath (root, id, comparator) {
let paths = [root]
let NOT_FOUND = undefined
if (comparator(root.id, id)) {
return paths
}
if (root.children) {
let isNotFound = true
root.children.some((node) => {
let resolvedPath = findPath(node, id, comparator)
if (resolvedPath) {
paths = [...paths, ...resolvedPath]
isNotFound = false
return true
}
})
if(isNotFound) {
return NOT_FOUND
}

}else{
return NOT_FOUND
}
return paths
}