Skip to content

Commit

Permalink
Revert "refactor: popper api调整"
Browse files Browse the repository at this point in the history
This reverts commit 2ce893c.
  • Loading branch information
yt0379 committed Sep 12, 2020
1 parent 2ce893c commit 99db451
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 73 deletions.
6 changes: 4 additions & 2 deletions packages/select/SelectDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ export default {
setup(props, ctx) {
const elSelect = inject('select')
const elms = usePopperElm(elSelect)
const popper = usePopper(props, ctx, elms)
const { referenceElm, popperElm } = usePopperElm(elSelect)
const popper = usePopper(referenceElm, popperElm, props, ctx)
usePopperUpdate(() => {
if (elSelect.visible) {
Expand All @@ -74,6 +74,8 @@ export default {
return {
elSelect,
referenceElm,
popperElm,
minWidth,
popperClass,
...popper
Expand Down
173 changes: 105 additions & 68 deletions src/use/emitter.js
Original file line number Diff line number Diff line change
@@ -1,92 +1,129 @@
import { getCurrentInstance } from 'vue'
import mitt from 'mitt'
import { capitalize } from 'element-ui/src/utils/util'
const EVENT_NAME_KEY = Symbol('ELEMENT_EVENTS')

const DISPATCH = 'dispatch'
const BROADCAST = 'broadcast'
export function useEmitter(instance = getCurrentInstance()) {
return {
dispatch: dispatch(instance),
broadcast: broadcast(instance),
on: on(instance),
once: once(instance),
off: off(instance)
}
}

const wrapper = Symbol('wrapper')
function on(instance) {
return (originalEventName, callback) => {
const eventName = 'on' + capitalize(originalEventName)

const emitter = mitt()
if (!instance.vnode.props) {
instance.vnode.props = {}
}

export function useEmitter() {
const currentComponentInstance = getCurrentInstance()
if (!instance.vnode.props[EVENT_NAME_KEY]) {
instance.vnode.props[EVENT_NAME_KEY] = new Set()
}
instance.vnode.props[EVENT_NAME_KEY].add(eventName)

function on(type, handler) {
const handleWrapper = (e) => {
const { value, type, emitComponentInstance } = e
if (type === BROADCAST) {
if (isChildComponent(currentComponentInstance, emitComponentInstance)) {
handler && handler(value)
}
} else if (type === DISPATCH) {
if (isChildComponent(emitComponentInstance, currentComponentInstance)) {
handler && handler(value)
if (!instance.vnode.props[eventName]) {
instance.vnode.props[eventName] = (...params) => {
const callbacks = instance.vnode.props[eventName].__events
if (callbacks) {
callbacks.forEach((cf) => {
cf(...params)
})
}
} else {
handler && handler(value)
}
instance.vnode.props[eventName].__events = []
}

// Save the real handler because the need to call off
handler[wrapper] = handleWrapper
emitter.on(type, handleWrapper)
instance.vnode.props[eventName].__events.push(callback)
}

function broadcast(type, evt) {
emitter.emit(type, {
type: BROADCAST,
emitComponentInstance: currentComponentInstance,
value: evt
})
}
function once(instance) {
const $off = off(instance)
const $on = on(instance)
return (originalEventName, handle) => {
const _on = (...params) => {
$off(originalEventName, _on)
handle(...params)
}
$on(originalEventName, _on)
}
}

function dispatch(type, evt) {
emitter.emit(type, {
type: DISPATCH,
emitComponentInstance: currentComponentInstance,
value: evt
})
}
function off(instance) {
return (originalEventName, callback) => {
const eventNameList =
instance.vnode.props && instance.vnode.props[EVENT_NAME_KEY]
if (!eventNameList || !eventNameList.size) {
return
}

function off(type, handler) {
emitter.off(type, handler[wrapper])
}
if (!originalEventName) {
eventNameList.forEach((eventName) => {
delete instance.vnode.props[eventName]
})
eventNameList.clear()
return
}

function emit(type, evt) {
emitter.emit(type, {
value: evt
})
}
const eventName = 'on' + capitalize(originalEventName)

function once(type, handler) {
const handleOn = () => {
handler && handler()
off(type, handleOn)
if (!callback) {
delete instance.vnode.props[eventName]
eventNameList.delete(eventName)
return
}
on(type, handleOn)
}

return {
on,
broadcast,
dispatch,
off,
emit,
once
const handlers =
instance.vnode.props[eventName] &&
instance.vnode.props[eventName].__events
if (handlers && handlers.length) {
const index = handlers.indexOf(callback)
if (index > -1) {
handlers.splice(index, 1)
}
}
}
}

/**
* check componentChild is componentParent child components
* @param {*} componentChild
* @param {*} componentParent
*/
function isChildComponent(componentChild, componentParent) {
const parentUId = componentParent.uid
function dispatch(instance) {
return (componentName, eventName, ...params) => {
let parent = instance.parent
while (parent && parent.type.name !== componentName) {
parent = parent.parent
}

while (componentChild && componentChild?.parent?.uid !== parentUId) {
componentChild = componentChild.parent
if (parent) {
parent.emit(eventName, ...params)
}
}
}

function broadcast(instance) {
return (componentName, eventName, ...params) => {
const _broadcast = (componentInstance) => {
if (!componentInstance) return

return Boolean(componentChild)
let children = componentInstance.subTree.children

if (children.default) {
children = children.default()
}

if (children) {
children.forEach((vnode) => {
const childComponent = vnode.component

if (childComponent?.type?.name === componentName) {
childComponent.emit(eventName, ...params)
} else {
_broadcast(childComponent)
}
})
}
}

_broadcast(instance)
}
}
5 changes: 2 additions & 3 deletions src/use/popper.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const popperProps = {
}
}

function usePopper(props, { emit, slots }, { referenceElm, popperElm }) {
function usePopper(referenceElm, props, { emit, slots }) {
const {
transformOrigin,
placement,
Expand All @@ -66,7 +66,7 @@ function usePopper(props, { emit, slots }, { referenceElm, popperElm }) {

const showPopper = ref(false)
const currentPlacement = ref('')
// const popperElm = ref(null)
const popperElm = ref(null)
const popperJS = ref(null)
const instance = getCurrentInstance()

Expand Down Expand Up @@ -221,7 +221,6 @@ function usePopper(props, { emit, slots }, { referenceElm, popperElm }) {
return {
showPopper,
currentPlacement,
referenceElm,
popperElm,
popperJS,
createPopper,
Expand Down

0 comments on commit 99db451

Please sign in to comment.