kili
kili

Reputation: 33

How can i have component render without App.vue

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/[email protected]" 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:

  1. here testFunction in MyComponent is not called . but i see MyComponent is $emit and i dont use App.vue
  2. 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

Upvotes: 1

Views: 1981

Answers (2)

Suat Atan PhD
Suat Atan PhD

Reputation: 1382

It is possible the solution is to use App.vue with different options like this:

<template>
  <div class="container">

    <div >
      <div id="AdminTemplate" v-if="this.$route.meta.layout == 'AdminTemplate'">
        <router-view />
      </div>
    <div id="NormalTemplate" v-else>
        <router-view />
    </div>
  
  </div>

</template>
<script>
export default {
  data() {
    return {
      
    };
  },
};
</script>

And in the router

{
    path: "/admin",
    name: "AdminVue",
    component: AdminVue,
    meta: { layout: 'AdminTemplate' },
  }

Upvotes: 0

brff19
brff19

Reputation: 834

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>

Upvotes: 0

Related Questions