Last active
February 23, 2021 14:56
-
-
Save lihbr/91bc6fc5d1b3cc4557a53d199bce1ed6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const ANCHOR_TAG = "a"; | |
const FRAMEWORK_LINK = "router-link"; // or "nuxt-link", "g-link"... | |
const getLinkTag = ({ href, blank, external }) => { | |
if (blank || external) { | |
return ANCHOR_TAG; | |
} else if (/^\/(?!\/).*$/.test(href)) { // regex101.com/r/LU1iFL/1 | |
return FRAMEWORK_LINK; | |
} else { | |
return ANCHOR_TAG; | |
} | |
}; | |
export { getLinkTag as default, ANCHOR_TAG, FRAMEWORK_LINK }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Vue 2 Functional Component: https://vuejs.org/v2/guide/render-function.html#Functional-Components */ | |
import { mergeData } from "vue-functional-data-merge"; | |
import getLinkTag, { ANCHOR_TAG, FRAMEWORK_LINK } from "./getLinkTag"; | |
const SmartLink = { | |
functional: true, | |
props: { | |
href: { | |
type: String, | |
default: "" | |
}, | |
blank: { | |
type: Boolean, | |
default: false | |
}, | |
external: { | |
type: Boolean, | |
default: false | |
} | |
}, | |
// It's a convention to rename `createElement` to `h` | |
render(h, context) { | |
const tag = getLinkTag(context.props); | |
// Map our attributes & props correctly | |
const attrs = {}; | |
const props = {}; | |
let on = {}; | |
switch (tag) { | |
case ANCHOR_TAG: | |
// Map `href` prop to the correct attribute | |
attrs.href = context.props.href; | |
// Handle `blank` prop | |
if (context.props.blank) { | |
attrs.target = "_blank"; | |
attrs.rel = "noopener"; | |
} | |
// Transform native events to regular events for HTML anchor tag | |
on = { ...context.data.nativeOn }; | |
delete context.data.nativeOn; | |
break; | |
case FRAMEWORK_LINK: | |
// Map `href` prop to the correct prop | |
props.to = context.props.href; | |
break; | |
default: | |
break; | |
} | |
// Merge our new data with existing ones | |
const data = mergeData(context.data, { attrs, props, on }); | |
// Return a new virtual node | |
return h(tag, data, context.children); | |
} | |
}; | |
export default SmartLink; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Vue 3 Render Function: https://v3.vuejs.org/guide/render-function */ | |
// Import utilities from Vue | |
import { h, resolveComponent } from "vue"; | |
import getLinkTag, { ANCHOR_TAG, FRAMEWORK_LINK } from "./getLinkTag"; | |
const SmartLink = { | |
props: { | |
href: { | |
type: String, | |
default: "" | |
}, | |
blank: { | |
type: Boolean, | |
default: false | |
}, | |
external: { | |
type: Boolean, | |
default: false | |
} | |
}, | |
render() { | |
const tag = getLinkTag(this); | |
// Map our attributes & props correctly | |
const attrs = {}; | |
let nodeTag; | |
switch (tag) { | |
case ANCHOR_TAG: | |
// Resolve the final tag | |
nodeTag = tag; | |
// Map `href` prop to the correct attribute | |
attrs.href = this.href; | |
// Handle `blank` prop | |
if (this.blank) { | |
attrs.target = "_blank"; | |
attrs.rel = "noopener"; | |
} | |
break; | |
case FRAMEWORK_LINK: | |
// Resolve the final component | |
nodeTag = resolveComponent(FRAMEWORK_LINK) | |
// Map `href` prop to the correct attribute | |
attrs.to = this.href; | |
break; | |
default: | |
break; | |
} | |
// Return a new virtual node | |
return h(nodeTag, attrs, this.$slots.default()); | |
} | |
}; | |
export default SmartLink; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment