I've got below code, which I used it in Vue 2 projects to add dynamic styles to components, and when I tried to use it in Vue 3, I've got createElemenet is not a function error.
In Vue 2 :
app.js
Vue.component('v-style', {
render: function (createElement) {
return createElement('style', this.$slots.default)
}
});
In Vue 3 :
app.js
app
.component('err-text', ErrorText)
.component('v-style', {
render: function (createElement : any) {
return createElement('style', this.$slots.default)
}
});
The result of above code provide me option to add my styles like below :
<template>
<v-style>
.foo {
color: red;
}
</v-style>
</template>
In vue 3 createElement is replaced by the h function imported from vue :
import {h} from 'vue'
app.component('err-text', ErrorText)
.component('v-style', {
render: function () {
return h('style', this.$slots.default())
}
});
Related
I have a problem with Vue 3, using vue from CDN.
I want to use a template generated by the server, the template is changed but methods and data are not bound.
<script>
// reproduction of the issue in vue3 vite
import { compile, computed, h } from 'vue/dist/vue.esm-bundler'; // vite
// import { compile, computed, h } from 'vue/dist/vue.esm-bundler'; // webpack
export default {
data() {
return {
htmlTemplate: '<span #click="test()">this is a test {{ testVariable }}</span>', // This is a test from what would be loaded from the server
testVariable: 'test variable',
}
},
methods: {
test() {
console.log('test');
}
},
render() {
const textCompRef = computed(() => ({ render: compile(this.htmlTemplate) }));
console.log('textCompRef', textCompRef);
return h(textCompRef.value);
}
}
</script>
When I click on this is a test then vue#3:1807 Uncaught TypeError: test is not a function
Can someone point me in the right direction?
Thanks in advance
I tried setting the template in the create life cycle with this.$options.template = response from the server that worked on 3-rd click and was not changing when new template is loaded.
Is it possible to create a composable function that would use render function so it can display something?
Example:
import { h } from 'vue'
export function useErrorHandling() {
return {
render() {
return h('div', { class: 'bar', innerHTML: 'world!' })
}
}
}
<script setup>
import { useErrorHandling } from './mouse.js'
useErrorHandling()
</script>
<template>
hello
</template>
plaground with above example
Yes It is possible to do that you need just store the value returned by the composable in a variable and use it as a component
const err = useErrorHandling()
//in template
// <err />
Playground Example
I know that vue doent detect change in array when we directly set an item with the index, instead, Vue.set is used, and works fine in vue.js. But i am using Vue with native script, and when I use Vue.set(myArray,index,newValue), give error. ReferenceError Vue is not defined.
Here is my script:
<script>
export default {
methods: {
comparar: function(caracter, pos) {
//This is NOT reactive
this.palabra_escrita[pos] = caracter
// This must be reactive but throws me error
app.$set(this.palabra_escrita, pos, caracter)
}
}, //End methods
data() {
return {
palabra_escrita: [],
};
}
};
</script>
Here is my app.js file:
import Vue from 'nativescript-vue';
import HelloWorld from './components/HelloWorld';
// Uncommment the following to see NativeScript-Vue output logs
//Vue.config.silent = false;
new Vue({
template: `
<Frame>
<HelloWorld />
</Frame>`,
components: {
HelloWorld
}
}).$start();
I am learning VueJS and I love it! but for the last 2 days I have been stuck on a weird problem.
I made a previous project and there the exact same code DOES work. In my new project (learning project) the identical code does NOT work.
It results in this error:
My code is as follow (everything works perfect except the resource):
Main.js
import Vue from 'vue'
import App from './App.vue'
import VueResource from 'vue-resource'
import router from './router'
Vue.config.productionTip = false
Vue.use(VueResource);
Vue.http.options.root = 'https://myapi.com/v1/list/';
Vue.http.interceptors.push((resource, next) => {
this.method = 'GET';
next();
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
Home.vue code:
<template>
<div>
<StatsRowOne></StatsRowOne>
<button class="btn btn-primary" v-on:click="submit">search</button>
</div>
</template>
<script>
import StatsRowOne from './elements/StatsRowOne';
export default {
data(){
return {
results: [],
resource: {}
}
},
components: {
StatsRowOne: StatsRowOne
},
methods: {
submit() {
this.resource.get().then(function(response) {
alert('done');
});
}
},
created() {
this.resource = this.$resource('auto');
}
}
</script>
<style lang="scss" scoped>
</style>
A further explanation from my comment: the this.method is undefined on line 7 in your main.js file because it is used in an arrow function. Remember that arrow functions in ES6 preserves the lexical this, so you are actually not accessing the property correctly because this does not point to anything exposed by the interceptor in the callback.
Based on the documentation, it appears that you should be using resource.method instead.
I have this vue js component:
<template>
<div>
hello world
</div>
</template>
<script>
export default {
name: 'mycomp',
data: function () {
console.error("window.google_recaptcha_public_key", window.google_recaptcha_public_key);
return {
}
},
mounted() {
let app = this;
console.error("window.google_recaptcha_public_key2", window.google_recaptcha_public_key);
},
}
</script>
<style scoped lang="scss">
</style>
returns:
window.google_recaptcha_public_key undefined
window.google_recaptcha_public_key2 undefined
where can I leave painless and happy all global configuration?
notice this configuration lives in my laravel backend. So I wont copy paste all values from the backend to the front end
U can use Vue.prototype in main.js file, or in file you import Vue
Vue.prototype.Hereanyname = window.hereanyname;
and in your Vue application, you can use it
Hereanyname.thefunction
Real example on Laravel
in main.js
import Vue from 'vue';
Vue.prototype.Routes = window.routes;
new Vue({
el: '#app',
template: '<App/>',
components: {App}
});
in your application
:href="Routes.route('laravel.route.here')"
So for your case
import Vue from 'vue';
Vue.prototype.GoogleRecaptcha = window.google_recaptcha_public_key;
new Vue({
el: '#app',
template: '<App/>',
components: {App}
});
inside application
mounted() {
console.log(this.GoogleRecaptcha)
}
In Vue3, you no longer have the global Vue instance, so you need to assign the window as a global property on your app...
// main.js
app.config.globalProperties.window = window
Then in your components, window will just work.
This info is from an impeccable source.
You should save your window variable in Vue.prototype
main.js
Vue.prototype.$authUser = window.authUser;
After that, you can access your data as follows:
Vue template
<div v-text="$authUser.name"></div>
Vue script
let name = this.$authUser.name;
window is available in the vuex store. This may help if you need to mutate the window property synchronously with other actions/mutations, give you a chance to validate what goes into it, or catch an error if the variable you intend to put there isn't available.
export default new Vuex.store({
state: {
windowFoo: window.foo,
googleRecaptcha: window.google_recaptcha_public_key
},
getters: {
windowFoo: (state) => state.windowFoo,
googleRecaptcha: (state) => state.googleRecaptcha
},
actions: {
barThenFooThenBaz({ commit }, { foo }) {
// ... do some other required actions first
commit("setWindowFoo", foo);
// ... do some dependent actions next
}
},
mutations: {
setWindowFoo(state, foo) {
state.windowFoo = foo;
}
}
});
Then from your Single File Component...
//....
computed: {
windowFoo() {
return this.$store.getters.windowFoo;
},
googleRecaptcha() {
return this.$store.getters.googleRecaptcha;
}
},
methods: {
async barThenFooThenBaz(foo) {
await this.$store.dispatch({
type: "barThenFooThenBaz",
foo: foo
});
// ... do something dependent on windowFoo being set
}
}
//....
Although the other answers here are totally acceptable, I've had issues using the Vue instance with Vue.prototype in main.js as our project has gotten larger, so I hope this helps!
Provide/Inject works nicely. Here's an example with Vue 3:
main.js
const app = createApp(App)
app.provide('recaptcha_key', window.google_recaptcha_public_key)
app.mount('#app')
MyComponent.vue
<script setup>
const { inject } from 'vue'
const recaptchaKey = inject('recaptcha_key')
</script>