mirror of
https://github.com/tenrok/vue-meta.git
synced 2026-06-24 16:50:34 +03:00
feat: implement first useApi basics
This commit is contained in:
@@ -48,7 +48,7 @@ export default {
|
|||||||
targets[target].push(vnodes)
|
targets[target].push(vnodes)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
console.log('TARGETS', targets)
|
// console.log('TARGETS', targets)
|
||||||
return Object.keys(targets).map(target => {
|
return Object.keys(targets).map(target => {
|
||||||
return h(Teleport, { to: target }, targets[target])
|
return h(Teleport, { to: target }, targets[target])
|
||||||
})
|
})
|
||||||
|
|||||||
+106
-47
@@ -1,68 +1,127 @@
|
|||||||
import { markRaw, reactive, onMounted } from 'vue'
|
import { markRaw, reactive, onMounted, customRef, getCurrentInstance } from 'vue'
|
||||||
|
import { def, hasOwn, isObject, isArray, isPlainObject } from '@vue/shared'
|
||||||
import { defaultMapping } from './config'
|
import { defaultMapping } from './config'
|
||||||
|
|
||||||
const apps = {}
|
let appId = 0
|
||||||
let appId = 1
|
|
||||||
|
|
||||||
export function createMeta ({ config }) {
|
export function createMeta ({ resolver, config }) {
|
||||||
const id = Symbol(`vue-meta-${appId++}`)
|
const id = Symbol(`vueMeta[${appId++}]`)
|
||||||
|
|
||||||
const Meta = {
|
|
||||||
id,
|
|
||||||
|
|
||||||
|
return {
|
||||||
install (app) {
|
install (app) {
|
||||||
let watchersAdded = false
|
const $metaInfo = {
|
||||||
|
id,
|
||||||
|
resolver,
|
||||||
|
shadow: markRaw({}),
|
||||||
|
metainfo: reactive({})
|
||||||
|
}
|
||||||
|
|
||||||
|
app.config.globalProperties.$metaInfo = $metaInfo
|
||||||
|
app.provide('metainfo', $metaInfo.metainfo)
|
||||||
app.provide('__vueMetaConfig', {
|
app.provide('__vueMetaConfig', {
|
||||||
|
id,
|
||||||
...defaultMapping,
|
...defaultMapping,
|
||||||
...config
|
...config
|
||||||
})
|
})
|
||||||
|
|
||||||
app.mixin({
|
|
||||||
created () {
|
|
||||||
if (this === this.$root) {
|
|
||||||
watchersAdded = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.metaData || watchersAdded) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let depth = 0
|
|
||||||
let parent = this
|
|
||||||
while (parent) {
|
|
||||||
parent = parent.$parent
|
|
||||||
depth++
|
|
||||||
|
|
||||||
if (parent === this.$root) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.__meta = markRaw({
|
|
||||||
depth
|
|
||||||
})
|
|
||||||
console.log('CREATED', this, this.metaData, depth)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
app.config.globalProperties.$meta = this
|
app.config.globalProperties.$meta = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apps[id] = Meta
|
|
||||||
|
|
||||||
return Meta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMeta (rawMetainfo) {
|
export function useMeta (obj) {
|
||||||
onMounted(vmMounted)
|
const vm = getCurrentInstance()
|
||||||
|
|
||||||
const metainfo = reactive(rawMetainfo)
|
const { shadow, metainfo } = vm.ctx.$metaInfo
|
||||||
|
addMetainfoRecursive(obj, vm, shadow, metainfo)
|
||||||
|
|
||||||
return metainfo
|
return createProxy(obj, createHandler(vm))
|
||||||
}
|
}
|
||||||
|
|
||||||
function vmMounted () {
|
function createProxy (obj, handler) {
|
||||||
console.log('MOUNTED', this, arguments)
|
return new Proxy(obj, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createHandler (vm, keyPath = []) {
|
||||||
|
return {
|
||||||
|
get (target, prop) {
|
||||||
|
const value = target[prop]
|
||||||
|
|
||||||
|
if (isObject(value)) {
|
||||||
|
if (!value.__vm_proxy) {
|
||||||
|
const newKeyPath = [...keyPath, prop]
|
||||||
|
|
||||||
|
const handler = createHandler(vm, newKeyPath)
|
||||||
|
value.__vm_proxy = createProxy(value, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.__vm_proxy
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
set (target, prop, value) {
|
||||||
|
updateMetainfo(keyPath, vm, prop, value)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMetainfoRecursive (obj, vm, shadowParent, liveParent) {
|
||||||
|
for (const key in obj) {
|
||||||
|
if (isPlainObject(obj[key])) {
|
||||||
|
if (!shadowParent[key]) {
|
||||||
|
shadowParent[key] = {}
|
||||||
|
liveParent[key] = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMetainfoRecursive(obj[key], vm, shadowParent[key], liveParent[key])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shadowParent[key]) {
|
||||||
|
shadowParent[key] = []
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowParent[key].push({ vm, value: obj[key] })
|
||||||
|
|
||||||
|
setLive(vm, key, shadowParent, liveParent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateMetainfo (keyPath, vm, key, value) {
|
||||||
|
let { shadow: shadowParent, metainfo: liveParent } = vm.ctx.$metaInfo
|
||||||
|
|
||||||
|
for (const _key of keyPath) {
|
||||||
|
shadowParent = shadowParent[_key]
|
||||||
|
liveParent = liveParent[_key]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlainObject(value)) {
|
||||||
|
if (!shadowParent[key]) {
|
||||||
|
shadowParent[key] = {}
|
||||||
|
liveParent[key] = {}
|
||||||
|
}
|
||||||
|
// TODO: fix this shit
|
||||||
|
addMetainfoRecursive(value, vm, shadowParent[key], liveParent[key])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const idx = shadowParent[key].findIndex(({ vm: _vm }) => _vm === vm)
|
||||||
|
shadowParent[key][idx].value = value
|
||||||
|
|
||||||
|
setLive(vm, key, shadowParent, liveParent)
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLive (vm, key, shadowParent, liveParent) {
|
||||||
|
let value
|
||||||
|
if (shadowParent[key].length > 1) {
|
||||||
|
value = vm.ctx.$metaInfo.resolver(shadowParent[key])
|
||||||
|
} else {
|
||||||
|
value = shadowParent[key][0].value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasOwn(liveParent, key) || liveParent[key] !== value) {
|
||||||
|
liveParent[key] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { h } from 'vue'
|
|||||||
import { getConfigKey } from './config'
|
import { getConfigKey } from './config'
|
||||||
|
|
||||||
export function renderMeta (ctx, key, data, config) {
|
export function renderMeta (ctx, key, data, config) {
|
||||||
console.info('renderMeta', key, data, config)
|
// console.info('renderMeta', key, data, config)
|
||||||
|
|
||||||
if (config.group) {
|
if (config.group) {
|
||||||
return renderGroup(ctx, key, data, config)
|
return renderGroup(ctx, key, data, config)
|
||||||
@@ -12,7 +12,7 @@ export function renderMeta (ctx, key, data, config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renderGroup (ctx, key, data, config) {
|
export function renderGroup (ctx, key, data, config) {
|
||||||
console.info('renderGroup', key, data, config)
|
// console.info('renderGroup', key, data, config)
|
||||||
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
config.contentAttributes = getConfigKey([key, config.tag], 'contentAttributes', config)
|
config.contentAttributes = getConfigKey([key, config.tag], 'contentAttributes', config)
|
||||||
@@ -107,10 +107,10 @@ export function renderTag (ctx, key, data, config = {}, groupConfig = {}) {
|
|||||||
? `${groupConfig.tagNamespace}:${tag}`
|
? `${groupConfig.tagNamespace}:${tag}`
|
||||||
: tag
|
: tag
|
||||||
|
|
||||||
console.info('FINAL TAG', finalTag)
|
// console.info('FINAL TAG', finalTag)
|
||||||
console.log(' ATTRIBUTES', attributes)
|
// console.log(' ATTRIBUTES', attributes)
|
||||||
console.log(' CONTENT', content)
|
// console.log(' CONTENT', content)
|
||||||
// console.log(data, attributes, config)
|
// // console.log(data, attributes, config)
|
||||||
|
|
||||||
if (hasChilds) {
|
if (hasChilds) {
|
||||||
for (const child of content) {
|
for (const child of content) {
|
||||||
|
|||||||
@@ -20,15 +20,15 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/nuxt/vue-meta#readme",
|
"homepage": "https://github.com/nuxt/vue-meta#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.9.0",
|
"@babel/core": "^7.9.6",
|
||||||
"@babel/node": "^7.8.7",
|
"@babel/node": "^7.8.7",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/preset-env": "^7.9.5",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@vue/compiler-sfc": "^3.0.0-alpha.10",
|
"@vue/compiler-sfc": "^3.0.0-alpha.10",
|
||||||
"@vue/server-renderer": "^3.0.0-alpha.10",
|
"@vue/server-renderer": "^3.0.0-alpha.10",
|
||||||
"babel-loader": "^8.1.0",
|
"babel-loader": "^8.1.0",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.0",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"consola": "^2.11.3",
|
"consola": "^2.12.1",
|
||||||
"core-js": "3",
|
"core-js": "3",
|
||||||
"cross-env": "^7.0.2",
|
"cross-env": "^7.0.2",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
@@ -40,9 +40,9 @@
|
|||||||
"vue-meta": "^2.3.3",
|
"vue-meta": "^2.3.3",
|
||||||
"vue-router": "next",
|
"vue-router": "next",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.6.11",
|
||||||
"vuex": "^3.1.3",
|
"vuex": "^3.4.0",
|
||||||
"webpack": "^4.42.1",
|
"webpack": "^4.43.0",
|
||||||
"webpack-dev-server": "^3.10.3",
|
"webpack-dev-server": "^3.11.0",
|
||||||
"webpackbar": "^4.0.0"
|
"webpackbar": "^4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-23
@@ -1,10 +1,10 @@
|
|||||||
import { createApp, defineComponent, reactive, toRefs, h } from 'vue'
|
import { createApp, defineComponent, reactive, inject, markRaw, toRefs, h, customRef, watch, watchEffect } from 'vue'
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import Metainfo from '../next/Metainfo.vue'
|
import Metainfo from '../next/Metainfo.vue'
|
||||||
import { createMeta, useMeta } from '../next'
|
import { createMeta, useMeta } from '../next'
|
||||||
import About from './about.vue'
|
import About from './about.vue'
|
||||||
|
|
||||||
let metaUpdated = 'no'
|
const metaUpdated = 'no'
|
||||||
|
|
||||||
const ChildComponent = defineComponent({
|
const ChildComponent = defineComponent({
|
||||||
name: 'child-component',
|
name: 'child-component',
|
||||||
@@ -16,19 +16,8 @@ const ChildComponent = defineComponent({
|
|||||||
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
|
<h3>You're looking at the <strong>{{ page }}</strong> page</h3>
|
||||||
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
|
<p>Has metaInfo been updated due to navigation? {{ metaUpdated }}</p>
|
||||||
</div>`,
|
</div>`,
|
||||||
metaInfo () {
|
|
||||||
return {
|
|
||||||
title: `${this.page} - ${this.date && this.date.toTimeString()}`,
|
|
||||||
bodyAttrs: {
|
|
||||||
class: 'child-component'
|
|
||||||
},
|
|
||||||
afterNavigation () {
|
|
||||||
metaUpdated = 'yes'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created () {
|
created () {
|
||||||
//console.log(this)
|
// console.log(this)
|
||||||
},
|
},
|
||||||
setup () {
|
setup () {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@@ -36,7 +25,16 @@ const ChildComponent = defineComponent({
|
|||||||
metaUpdated
|
metaUpdated
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const metainfo = useMeta({
|
||||||
|
charset: 'utf16',
|
||||||
|
description: 'Description 2',
|
||||||
|
og: {
|
||||||
|
title: 'Og Title 2'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
metainfo,
|
||||||
...toRefs(state)
|
...toRefs(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +51,7 @@ function view (page) {
|
|||||||
|
|
||||||
const App = {
|
const App = {
|
||||||
setup () {
|
setup () {
|
||||||
const metainfo = useMeta({
|
/* const metainfo = useMeta({
|
||||||
base: { href: '/vue-router', target: '_blank' },
|
base: { href: '/vue-router', target: '_blank' },
|
||||||
charset: 'utf8',
|
charset: 'utf8',
|
||||||
title: 'My Title',
|
title: 'My Title',
|
||||||
@@ -104,7 +102,24 @@ const App = {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setTimeout(() => (metainfo.title = 'My Updated Title'), 2000)
|
setTimeout(() => (metainfo.title = 'My Updated Title'), 2000) */
|
||||||
|
|
||||||
|
const meta = useMeta({
|
||||||
|
charset: 'utf8',
|
||||||
|
title: 'Title 1',
|
||||||
|
og: {
|
||||||
|
title: 'Og Title 1'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setTimeout(() => (meta.charset = 'utf17'), 2000)
|
||||||
|
setTimeout(() => (meta.og = { title: 'Updated Og Title 1' }), 3000) // TODO: fix
|
||||||
|
|
||||||
|
const metainfo = inject('metainfo')
|
||||||
|
|
||||||
|
watch(metainfo, (newValue, oldValue) => {
|
||||||
|
console.log('UPDATE', newValue)
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
metainfo
|
metainfo
|
||||||
@@ -131,15 +146,21 @@ const App = {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
const router = createRouter({
|
function decisionMaker5000000 (options) {
|
||||||
history: createWebHistory('/vue-router'),
|
let theChosenOne
|
||||||
routes: [
|
|
||||||
{ name: 'home', path: '/', component: view('home') },
|
for (const option of options) {
|
||||||
{ name: 'about', path: '/about', component: About }
|
if (!theChosenOne || theChosenOne.vm.id < option.vm.id) {
|
||||||
]
|
theChosenOne = option
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(theChosenOne.value)
|
||||||
|
return theChosenOne.value
|
||||||
|
}
|
||||||
|
|
||||||
const meta = createMeta({
|
const meta = createMeta({
|
||||||
|
resolver: decisionMaker5000000,
|
||||||
config: {
|
config: {
|
||||||
esi: {
|
esi: {
|
||||||
group: true,
|
group: true,
|
||||||
@@ -153,6 +174,14 @@ const meta = createMeta({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory('/vue-router'),
|
||||||
|
routes: [
|
||||||
|
{ name: 'home', path: '/', component: view('home') },
|
||||||
|
{ name: 'about', path: '/about', component: About }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.component('metainfo', Metainfo)
|
app.component('metainfo', Metainfo)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|||||||
Reference in New Issue
Block a user