Home > Blockchain >  Vue 3 component not rendering but show up on the elements tree
Vue 3 component not rendering but show up on the elements tree

Time:01-05

I'm new to vue and I was trying to change one of my components in to the new syntax to learn vue 3. The component was working just fine before the change so I must be missing something.

this is the mother component:

<template>
  <div >
    <div>
      <div >
        <h1 >@{{ user.username }}</h1>
        <div v-if="user.isAdmin" >Admin</div>
        <div >
          <string><b>Followers: </b></string> {{ followers }}
        </div>
      </div>
      <NewTwoot @create-twoot="createNewTwoot" />
    </div>
    <div >
      <TwootItem
        v-for="twoot in user.twoots"
        :username="user.username"
        :key="twoot.id"
        :twoot="twoot"
        @favorit="toggleFavorite(id)"
      />
    </div>
  </div>
</template>

<script>
import TwootItem from "./TwootItem.vue";

export default {
  name: "UserProfile",
  components: {
    TwootItem,
  },
  data() {
    return {
      followers: 0,
      user: {
        id: 1,
        username: "GabrielBG",
        firstName: "Gabriel",
        lastName: "Gutierrez",
        email: "[email protected]",
        isAdmin: true,
        twoots: [
          {
            id: 2,
            content: "This is my second twoot",
          },
          {
            id: 3,
            content: "This is my third twoot",
          },
          {
            id: 1,
            content: "This is my first twoot",
          },
        ],
      },
    };
  },
  watch: {
    followers(newFollowerCount, oldFollowerCount) {
      if (oldFollowerCount > newFollowerCount) {
        console.log("You lost a follower!");
      } else {
        console.log("You gained a follower!");
      }
    },
  },
  computed: {
    fullName() {
      return this.user.firstName   " "   this.user.lastName;
    },
  },
  methods: {
    followUser() {
      this.followers  ;
    },
    toggleFavorite(id) {
      console.log("Toggling favorite for twoot with id: "   id);
    },
    createNewTwoot(newTwootContent) {
      this.user.twoots.unshift({
        id: this.user.twoots.length   1,
        content: newTwootContent,
      });
    },
  },
  mounted() {
    this.followUser();
  },
};
</script>

And this is the component that was refactored but now it does not render:

<template>
  <form  @submit.prevent="createNewTwoot">
    <lable for="new-twoot"
      ><strong>New Twoot</strong> ({{ newTwootCharCount }}/180)
    </lable>
    <textarea id="new-twoot" rows="5" v-model="state.newTwootContent" />
    <div >
      <lable for="twoot-type">
        <strong>Twoot Type</strong>
      </lable>
      <select id="twoot-type" v-model="state.selectedTwootType">
        <option
          :value="option.value"
          v-for="(option, index) in state.twootTypes"
          :key="index"
        >
          {{ option.name }}
        </option>
      </select>
    </div>
    <button
      type="submit"
      :disabled="
        newTwootContent.length === 0 ||
        newTwootContent.length > 180 ||
        newTwootType == 'draft'
      "
    >
      Twoot
    </button>
  </form>
</template>

<script>
import { reactive, computed } from "vue";
export default {
  name: "NewTwoot",
  setup(_props, ctx) {
    const state = reactive({
      newTwootContent: "",
      selectedTwootType: "instant",
      twootTypes: [
        { value: "draft", name: "Draft" },
        { value: "instant", name: "Instant Twoot" },
      ],
    });

    const newTwootCharCount = computed(() => state.newTwootContent.length);

    function createNewTwoot() {
      ctx.emit("create-twoot", state.newTwootContent);
      state.newTwootContent = "";
    }

    return {
      state,
      newTwootCharCount,
      createNewTwoot,
    };
  },
};
</script>

I can see it on the elements tree but it show up as <newtwoot></newtwoot> as if it was empty.

CodePudding user response:

I see two errors:

  1. you only import TwootItem in the parent but not NewTwoot. This explains why it is not rendered properly.
  2. You don't define the emit in the child component, look at my answer here: vue 3 emit warning " Extraneous non-emits event listeners"

So importing the missing component import NewTwoot from "./NewTwoot.vue"; and adding it to the components should do the trick:

components: {
    NewTwoot,
    TwootItem,
}
  •  Tags:  
  • Related