I have the following main.ts file in Vue3:
import { createApp } from "vue"
import App from "./App.vue";
//How to do this in nuxt3?
import OpenLayersMap from "vue3-openlayers";
import "vue3-openlayers/dist/vue3-openlayers.css";
const app = createApp(App);
//How to do this in nuxt3?
app.use(OpenLayersMap);
app.mount("#app");
How can I add the vue3-openlayers plugin to nuxt3?
To auto-install a Vue plugin in Nuxt 3, create a .js/.ts file under <projectDir>/plugins/ (create the directory if needed) with the following boilerplate:
// plugins/my-plugin.js
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(/* MyPlugin */)
})
Since vue3-openlayers depends on window, the plugin can only be installed client side, so use the .client.js extension.
To load vue3-openlayers client side, the plugin file would look like this:
// plugins/vue3-openlayers.client.js
import { defineNuxtPlugin } from '#app'
import OpenLayers from 'vue3-openlayers'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(OpenLayers)
})
Create <projectDir>/components/MyMap.vue with the following example content from the vue3-openlayers docs:
// components/MyMap.vue
<script setup>
import { ref } from 'vue'
const center = ref([40, 40])
const projection = ref('EPSG:4326')
const zoom = ref(8)
const rotation = ref(0)
</script>
<template>
<ol-map :loadTilesWhileAnimating="true" :loadTilesWhileInteracting="true" style="height:400px">
<ol-view :center="center" :rotation="rotation" :zoom="zoom"
:projection="projection" />
<ol-tile-layer>
<ol-source-osm />
</ol-tile-layer>
</ol-map>
</template>
<style scoped>
#import 'vue3-openlayers/dist/vue3-openlayers.css';
</style>
We only want to render MyMap on the client because the plugin is only client-side, so use the <ClientOnly> component as a wrapper:
// app.vue
<template>
<ClientOnly>
<MyMap />
<template #fallback> Loading map... </template>
</ClientOnly>
</template>
demo
Related
I am new to Vue. I am a react developer trying to update some legacy code from my work.
What I want to do is I want to have a screen resize event handler in my component.
I found some helpful code pen https://codepen.io/sandrarodgers/pen/porZbxW
The thing is I don't know how to add those in my existing component.
To give you the general idea. My component already got two script tags
When I try to copy paste from codeine it give me some error on this keyword
Component
<template>
<div :style="styles">
...
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MultipleChoiceField from '../fields/MultipleChoiceField.vue';
import NumberField from '../fields/NumberField.vue';
export default defineComponent({
name: 'Questionnaire',
components: {
MultipleChoiceField,
NumberField,
},
});
</script>
<script setup lang="ts">
import {
defineProps,
defineEmits,
computed,
nextTick,
onMounted,
ref,
toRefs,
watch,
unref,
} from 'vue';
import {
handleQuestionLogicCalculator,
} from '../../lib/main';
import { typeformMarkdownToHtml } from '../../lib/processTypeformMarkdown';
import {
PrefilledAdditionalParameters,
QuestionnaireChoice,
} from '../../lib/types';
import localize from '../../lib/localization';
const props = defineProps<{
additions: PrefilledAdditionalParameters;
questionnaireConfig: QuestionnaireConfig;
styles: QuestionnaireStyles;
submitAnswers: ShowThankYouFunction;
showwelcomeScreen: () => void;
goBack: () => void;
}>();
const emit = defineEmits(['latestQuestionnaireIndex']);
//MORE CODE HERE
</script>
I have the following structure:
src
components
Footer.vue
views
Page.vue
App.vue
I would like to be able to access the 'message' variable in App.vue, but I can´t figure out how to do it when Footer.vue is not a direct child of App.vue (but child of Page.Vue which - via the router - is child App.vue).
What do I need to add in my files? There are now as follows - and (of course) no message appears in App.vue:
//App.vue
<template>
<p>Message is: {{ message }}</p>
<router-view />
</template>
<style lang="scss">
#import "./_scss/main.scss";
</style>
.
//Page.vue
<template>
<Footer/>
</template>
<script>
import Footer from '#/components/Footer.vue'
export default {
components: {
Footer
}
}
</script>
.
//Footer.vue
<template>
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</template>
<script>
export default {
data() {
return {
message: ''
}
}
}
</script>
Maybe Composition API and ES6 modules?
#/compositions/composition.js
import { ref } from 'vue'
const message = ref('test');
export const useComposition = function() {
// other functions, for example to mutate message ref
return {
message,
// ...
}
}
And now you import your composition in the components that need to access message:
// Footer.vue, App.vue
<script>
import { defineComponent } from 'vue'
import { useComposition } from '#/compositions/composition'
export default defineComponent({
setup() {
const { message } = useComposition();
return { // make it available in <template>
message
}
},
})
</script>
If you want to quickly get started with Composition API, see this.
I am using the experimental script setup to create a learn enviroment. I got a selfmade navigation bar with open a single component.
I am having trouble using the <component :is="" /> method. This method is described in the docs under component basics -> dynamic-components
In the Vue 3 Composition API, it works as expected:
<template>
<NavigationBar
#switchTab="changeTab"
:activeTab="tab"
/>
<component :is="tab" />
</template>
<script>
import { ref } from 'vue'
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
export default {
components: {
NavigationBar,
TemplateSyntax,
DataPropsAndMethods
},
setup () {
const tab = ref('DataPropsAndMethods')
function changeTab (newTab) {
tab.value = newTab
}
return {
changeTab,
tab
}
}
}
</script>
My approach with the script setup fails:
<template>
<NavigationBar
#switchTab="changeTab"
:activeTab="tab"
/>
<component :is="tab" />
</template>
<script setup>
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref } from 'vue'
const tab = ref('DataPropsAndMethods')
function changeTab (newTab) {
tab.value = newTab
}
</script>
do you got any idea how to solve this with the script setup method?
It seems with <script setup>, tab needs to reference the component definition itself instead of the component name.
To reference the component definition, which does not need reactivity, use markRaw() before setting tab.value:
<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'
const tab = ref(null)
changeTab(DataPropsAndMethods)
// newTab: component definition (not a string)
function changeTab (newTab) {
tab.value = markRaw(newTab)
}
</script>
demo 1
If you need to pass the component name to changeTab(), you could use a lookup:
<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'
const tab = ref(null)
changeTab('DataPropsAndMethods')
// newTab: component name (string)
function changeTab (newTab) {
const lookup = {
DataPropsAndMethods,
/* ...other component definitions */
}
tab.value = markRaw(lookup[newTab])
}
</script>
demo 2
Tested with Vue 3.0.9 setup with Vue CLI 5.0.0-alpha.8
I'm building my external vue component library and published to npm. My components extends Element UI components.
I followed the steps in this article and so far it works fine. https://medium.com/justfrontendthings/how-to-create-and-publish-your-own-vuejs-component-library-on-npm-using-vue-cli-28e60943eed3
npm package
https://www.npmjs.com/package/#bochen/example-lib
bundle script
"build-bundle": "vue-cli-service build --target lib --name exampleLib ./src/components/index.js",
src/components/index.js
import Vue from 'vue';
import BcButton from './Button.vue';
const Components = {
BcButton,
};
Object.keys(Components).forEach((name) => {
Vue.component(name, Components[name]);
});
export default Components;
src/components/Button.vue
<template>
<el-button v-bind="$props"
:class="{
'button-full': full,
}"
>
<slot/>
</el-button>
</template>
<script>
import { Button } from 'element-ui';
export default {
name: 'BcButton',
extends: Button,
props: {
full: {
type: Boolean,
default: false,
},
},
};
</script>
<style scoped>
.button-full {
width: 100%;
}
</style>
Issue
The problem is after I installed my library at another project, I still need to import Element UI in addition to make it work.
main.js
import Vue from 'vue'
import App from './App.vue'
import Element from 'element-ui';
import ExampleLib from '#bochen/example-lib';
import 'element-ui/lib/theme-chalk/index.css';
import '#bochen/example-lib/dist/exampleLib.css';
Vue.use(Element);
Object.keys(ExampleLib).forEach((name) => {
Vue.component(name, ExampleLib[name]);
});
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
Is there any possible, I could just import my library and work as I expected?
I am trying to use VueRangedatePicker and I can't seem to figure out how to use this on the template of some other vue component. I am using Webpack.
I have registered the component/plugin on my main.js file like this:
import Vue from 'vue'
import App from './App'
import router from './router'
import { store } from './store/store'
import firebase from './firebase-config'
import vuefire from 'vuefire'
//////////////// HERE
import VueRangedatePicker from 'vue-rangedate-picker' // importing the plugin here
Vue.use(VueRangedatePicker) // using it
Vue.component('VueRangedatePicker', { }) // creating the component globally (if I don't add this line the app complains the component is not registered
////////////////
Vue.config.productionTip = false
let app;
Vue.use(vuefire)
firebase.auth().onAuthStateChanged(function(user){
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#app',
template: '<App/>',
components: { App, VueRangedatePicker },
router,
store,
VueRangedatePicker
})
}
})
Then on my component component_A.vue I am again importing the VueRangedatePicker plugin in the following manner:
<template>
<div>
<vue-rangedate-picker #selected="onDateSelected" i18n="EN" />
</div>
</template>
<script>
import firebase,{ itemRef } from '../firebase-config';
import VueRangedatePicker from 'vue-rangedate-picker'
export default {
firebase() {
return {
items: itemsRef,
}
},
name: 'component_A',
data () {
return {
}
},
created() {
console.log(VueRangedatePicker);
},
methods: {
onDateSelected: function (daterange) {
this.selectedDate = daterange
},
}
</script>
I know the plugin/component is registered because when I log the Vue Rangedate Picker on the console I can see the object
However I am getting the an error message like this
I have read the complete readme.md file on the project's github but I am still puzzled. What is Vue_Daterange_picker? Is it a plugin? Is it a component? Is it a plugin that allows me to build a component? I am quite confused. Can you clarify this for me a little better? How can I make this work?
This is because you have registered the component with an empty name.
In main.js :
Vue.component('DatePicker', VueRangedatePicker)
Then in your component use the component as :
<date-picker></date-picker>