I’m trying to use vue-cli for app, but i wonder can i use component without using App.vue ?
Here component is shown in html but when i click the button, the testFunction in component is not called but in html the button "click here" is showing
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
</head>
<body>
<h1>hi</h1>
<div id="app">
<MyComponent #my-event="testFunction"></MyComponent>
</div>
<!-- built files will be auto injected -->
</body>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.11" defer></script>
<script src="main.js" defer></script>
</html>
MyComponent.vue
<div class="child" #click="$emit('my-event')">
click here
</div>
</template>
<script>
export default {
name: 'MyComponent',
props: {
}
}
</script>
main.js
import Vue from 'vue/dist/vue.js'
import MyComponent from './components/MyComponent'
Vue.config.productionTip = false
Vue.component('MyComponent',MyComponent);
new Vue({
el: '#app',
beforeCreate() {
console.log('Vue instance beforeCreate!');
},
created() {
console.log('Vue instance created!');
},
mounted() {
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(json => this.todos=json);
},
components: {
MyComponent
},
data: {
todos:null,
data:null
},
methods: {
testFunction:function(){
console.log("clicked");
}
},
render:h => h(MyComponent),
}).$mount('#app')
My Question:
here testFunction in MyComponent is not called . but i see MyComponent is $emit
and i dont use App.vue
is there way to register component, without render:h => h(myComponent)? and without $mount("#app")?
3.there is [Vue warn]: Cannot find element: #app error in console
No, that is not possible with the default configuration of vue-cli. If you want to import the component globally or only into a specific module then that is entirely possible, but what you are asking isn't possible. If you'd like to read more about local and global imports then read here.
There is a potential workaround though. You could create a second div to mount the application into, and then use the MyComponent component as the Base component for that mounting div. However, you will NOT be able to share data directly between the two Vue applications, and this behavior was used to be reserved for Modal insertion; however, nowadays the correct way to do this would be by via teleporting elements. You can read more about teleporting elements here
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import MyComponent from './components/MyComponent.vue';
createApp(App).mount('#app');
createApp(MyComponent).mount('#app2');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<div id="app2"></div>
<!-- built files will be auto injected -->
</body>
</html>
Related
I'm learning React. I added them to my website with html script tag:
My index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MyWebsitewithReact</title>
<link rel="stylesheet" href="css/main.css">
<meta name="theme-color" content="#2e2e2e">
</head>
<body>
<div class="navbar">
Home
Plugins
</div>
<div id="root"></div>
<script src="https://unpkg.com/react#18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>
My index.js:
'use strict';
function LikeButton() {
const [liked, setLiked] = React.useState(false);
if (liked) {
return 'You liked this!';
}
return React.createElement(
'button',
{
onClick: () => setLiked(true),
},
'Like'
);
}
const rootNode = document.getElementById('root');
const root = ReactDOM.createRoot(rootNode);
root.render(React.createElement(LikeButton));
This is the error I get :
Error: Minified React error #299; visit https://reactjs.org/docs/error-decoder.html?invariant=299 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
I have tried to visit and the error is:
createRoot(...): Target container is not a DOM element
I checked the documentation and everything seems fine
EDIT:
first in your file index.js you need to add in first line:
import React from 'react';
import ReactDOM from 'react-dom/client';
because without imported these library you can't use elements of React and ReactDOOM.
and in your index.html you need to replace this:
<script src="js/index.js"></script>
to this:
<script src="js/index.js" type="text/babel" data-type="module"></script>
I wish I solved your problem.
I'm trying to get this header component to be recognised and it just isnt. I've tried messing setting eslint to strict, and messing with my syntax to no avail. I don't get it, this should be so simple. ANy help would be appreciated.
App.vue
<template>
<div class="container">
<header />
</div>
</template>
<script>
import header from './components/header'
export default {
name: 'App',
components: {
header,
}
}
</script>
<style>
</style>
main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app">
</div>
<!-- built files will be auto injected -->
</body>
</html>
header.vue
<template>
<header>
<h1>Component header</h1>
</header>
</template>
<script>
export default {
name: 'header',
};
</script>
<style>
header {
display: flex;
}
</style>
Any help would be awesome. Thankyou.
The main.jsneeds to be imported into the index.html:
<body>
<div id="app"></div>
<script type="module" src="/src/js/main.js"></script>
</body>
(using the correct path)
It is better to rename your header component to another word, because <header> is used as a standard tag name in html
I am using local vue.js These are my files.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="res/vue.js"></script>
<script src="res/vue-router.js"></script>
<title>Vue</title>
</head>
<body>
<div id="app" ></div>
<script type="module" src="App.js"></script>
</body>
</html>
App.js
import Vue from './res/vue.js'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div>
{{foo}}
</div>
</template>
<script>
export default {
name: 'App',
data: function(){
return{
foo:'Hello vue'
}
}
}
</script>
<style>
</style>
But my index.html shows nothing
You mount your vue instance at the div node which id is "app", but i can't find the "#app" node, so you can resolve that by insert the "#app" node .
index.html:
<body>
<div id="app"></div>
<script type="module" src="App.js"></script>
</body>
Like the Steven suggested you have to compile vue components.
If you dont want to do it that way, below is the the easiet way.
Vue.createApp({
data() {
return {
foo: 'Hello vue',
};
},
}).mount('#app');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://unpkg.com/vue#next"></script>
<!-- <script src="res/vue-router.js"></script> -->
<title>Vue</title>
</head>
<body>
<div id="app">{{foo}}</div>
<script type="module" src="App.js"></script>
</body>
</html>
You probably need to build it with vue-cli to create a SPA(Single page Application) for your android application
Hi is your import correct? from node_modules it should be import Vue from 'vue' and not import Vue from './res/vue.js' try it
I'm new to vue and have been trying to include a google sign in button into my webpage. However, there is an error that states that "gapi is undefined" in my mounted(). How do i fix this? I've also tried initializing gapi but I don't know where to put that.
<template>
<div id = "signin"><div class="g-signin2">Sign in with LFA Email</div></div>
</div>
</template>
<script src="https://apis.google.com/js/platform.js" async defer></script>
<script>
import UserDataService from "../services/UserDataService";
export default {
data(){
return {
emailAddress:"",
signedIn:false
};
},
methods:{
onSignIn(user){
const profile = user.getBasicProfile()
this.emailAddress =profile.getEmail()
console.log(this.emailAddress)
if(this.emailAddress.indexOf("#students.org")>-1){
UserDataService.create(this.emailAddress)
this.signedIn = true
}
else{
alert("Please sign in with an LFA Email Account")
var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('User signed out.');
});
this.signedIn=false
}
}
},
mounted() {
gapi.signin2.render('signin', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': this.onSuccess,
})
}
}
</script>
<style>
#import '../../public/stylesheet.css';
</style>
You can't put this tag <script src="https://apis.google.com/js/platform.js"></script> in Single File Component.
Put this tag in your public/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>t-vue</title>
</head>
<body>
<noscript>
<strong>We're sorry but t-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src="https://apis.google.com/js/platform.js"></script>
<!-- built files will be auto injected -->
</body>
</html>
Besides that, you need also to remove the attributes async and defer. Because when you call the gapi variable in mounted the script didn't download yet.
The correct script is: <script src="https://apis.google.com/js/platform.js"></script>
PS: I create a minimal example that works for me, try this in your computer:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<button #click="test">Click Here</button>
</div>
<script src="https://apis.google.com/js/platform.js"></script>
<script>
let app = new Vue({
el: '#app',
methods: {
test() {
console.log('method', gapi);
},
},
mounted() {
console.log('mounted', gapi);
},
});
</script>
</body>
</html>
Not sure if you still need help with this, but I had to explicitly assign the gapi variable I see in all these examples to window.gapi by doing this at the beginning of the Mounted() method:
let gapi = window.gapi
Trying to use only Single File Components with Laravel. The components are mounted but events do not fire. Inside ExampleComponent I have a button #click="test" that does not fire.
It worked previously when I directly used the ExampleComponent within the blade template but after incorporating an App.vue component the events stopped.
Blade Template
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet" type="text/css">
<!-- Styles -->
<style>
</style>
</head>
<body>
<div id="app">
</div>
<script src="{{ mix('/js/app.js') }}""></script>
<script src="/js/app.js"></script>
</body>
app.js
require('./bootstrap');
window.Vue = require('vue');
import Vue from 'vue'
import Buefy from 'buefy'
import 'buefy/dist/buefy.css'
import App from './components/App.vue'
Vue.use(Buefy)
Vue.component('navbar', require('./components/Navbar.vue'));
new Vue({
el: '#app',
template: '<App/>',
components: { App }
});
App.vue
<template>
<div id="app">
<ExampleComponent/>
</div>
</template>
<script>
import ExampleComponent from './ExampleComponent.vue'
export default {
components: {
ExampleComponent
}
}
</script>
ExampleComponent.vue
<template>
<div style="background-color: #f7faff">
<navbar></navbar>
<button #click="test">Submit</button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
test() {
console.log("TEST")
}
},
mounted() {
console.log("Component mounted.");
}
};
</script>
Your Blade Template seems to have conflicting Javascript files that are loaded.
<script src="{{ mix('/js/app.js') }}""></script>
Should be the only script you are loading. That way, Laravel Mix can always compile the latest changes to your app.js file. See if that helps, because your .vue and .js files look wired up correctly.
I experienced a similar problem, only to find that I had made an unnecessary import in the app.js