I made a Vue3 project using the Vue CLI, and have a parent component('ReactionTimer') and a child component('Block') in the same folder('./components/').
I tried importing 'Block' into 'ReactionTimer', but got the following error:
[Vue warn]: Failed to resolve component: Block
at ReactionTimer
ReactionTimer.vue
<template>
<h1>Reaction Timer</h1>
<button #click="startTimer" :disabled="isTimerOn">Play</button>
<Block v-if="isTimerOn" :delay="delay" />
</template>
<script>
import Block from '../components/Block'
export default {
name: 'ReactionTimer',
components: {},
data() {
return {
isTimerOn: false,
delay: null
}
},
methods: {
startTimer() {
this.delay = 2000 + Math.random() * 5000;
this.isTimerOn = true
//console.log(this.delay)
}
}
}
</script>
Block.vue
<template>
<div class="block">
click me
</div>
</template>
<script>
export default {
props: 'delay'
}
</script>
<style>
.block {
width: 400px;
border-radius: 20px;
background: green;
color: aliceblue;
text-align: center;
padding: 100px 0;
margin: 40px auto;
}
</style>
I tried every combination of
import Block from '../components/Block'
import Block from '../components/Block.vue'
import Block from './Block'
import Block from './Block.vue'
You should add it to components option :
...
<script>
import Block from '../components/Block.vue'
export default {
name: 'ReactionTimer',
components: {Block },
...
Related
I added a new route, and added an animation in transition to the new route.
I added the following code which pushes the new route (/first) when a button is clicked:
/* From the Template */
<router-view #clickedNext1="onClickTransition" v-slot="{ Component }">
<transition name="route1" mode="out-in">
<component :is="Component"></component>
</transition>
</router-view>
/* From the Script */
methods: {
onClickTransition() {
this.$router.push("/first");
},
Now the problem is that when I click the button and invoke the "onClickTransition" method, the router seems to be pushed just fine, but the page is empty. The components are rendered only when I manually refresh the page by pressing ctrl+R.
I believe the problem perhaps comes from insertion of the animation, but if I refresh the page manually, the animation works just fine. So I have no idea what the problem is. I will be very grateful for help.
Here is the rest of the code for app.vue:
<template>
<router-view #clickedNext1="onClickTransition" v-slot="{ Component }">
<transition :key="$route.fullPath" name="route1" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</template>
<script>
export default {
name: "App",
components: {},
data() {
return {};
},
methods: {
onClickTransition() {
this.$router.push("/first");
},
leave(event) {
event.preventDefault();
event.returnValue = "";
},
},
mounted() {
window.addEventListener("beforeunload", this.leave);
},
beforeUnmount() {
window.removeEventListener("beforeunload", this.leave);
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #fff;
background-color: #151515;
position: relative;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
margin: 0px;
}
/* route transition */
.route1-enter-from {
opacity: 0;
}
.route1-enter-active {
transition: all 3s ease-in;
}
.route1-leave-to {
opacity: 0;
}
.route1-leave-active {
transition: all 3s ease-in;
}
</style>
code section from index.js:
import { createRouter, createWebHistory } from "vue-router";
import MainPage from "../views/MainPage.vue";
import FirstScene from "../views/FirstScene.vue";
const routes = [
{
path: "/",
name: "main",
component: MainPage,
},
{
path: "/first",
name: "first",
component: FirstScene,
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;
The "onClickTransition" method comes from the "PreStartPage.vue" component, which is the child component of "MainPage.vue" which is the main route.
Once the "Next" button is clicked in the "PreStartPage.vue", it sends an event to the "MainPage.vue" with this.$emit."MainPage.vue" then receives the event with a method named "onClickNext1", which sends out a signal to "App.vue" with another this.$emit. That is where the "#clickedNext1" that is shown in the App.vue comes from.
Here is the code from "PreStartPage.vue":
<script>
export default {
name: "PreStartPage",
methods: {
onClickNext() {
this.$emit("clickedNext");
},
},
};
</script>
Here is the code from "MainPage.vue":
<script>
import PreStartPage from "../components/PreStartPage.vue";
export default {
name: "MainPage",
components: { PreStartPage },
data() {
return { showMain: true, showPre: false };
},
methods: {
toggleMain() {
this.showMain = !this.showMain;
this.showPre = !this.showPre;
},
onClickNext1() {
this.$emit("clickedNext1");
},
},
};
</script>
Try modifying your code like this:
/* From the Template */
<router-view #clickedNext1="onClickTransition" v-slot="{ Component }">
<transition :key="$route.fullPath" name="route1" mode="out-in">
<component :is="Component"></component>
</transition>
</router-view>
The "key" property set to $route.fullPath should ensure that the transition is done correctly whenever the route is changed.
EDIT
To solve this, you can add a ":enter-active-class" and ":leave-active-class" property to the transition component, which allows you to specify the class that should be applied to the element during the transition.
In your App.vue component, you can update the transition component like this:
<transition :key="$route.fullPath" name="route1" mode="out-in" :enter-active-class="'route1-enter-active'" :leave-active-class="'route1-leave-active'">
<component :is="Component" />
</transition>
This will ensure that the correct classes are applied to the element during the transition, and that the components are fully rendered before the animation starts.
For more info i should you to visit the official wiki: https://vuejs.org/guide/built-ins/transition.html#css-based-transitions
You can try using
created() {
this.$watch(() => this.$route.params, () => {
// WATCH FOR ROUTE CHANGES
},
}
I'm following a Vue 2 tutorial but got stuck by this error. I've checked multiple questions before posting this one because I'm still unsure of what did I do wrong. Any input will be appreciated!
App.vue code:
<template>
<div id="app">
<!-- <img alt="Vue logo" src="./assets/logo.png"> -->
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/> -->
<TodoApp />
</div>
</template>
<script>
// import HelloWorld from './components/HelloWorld.vue'
import TodoApp from './components/TodoApp.vue';
export default {
name: 'App',
components: {
// HelloWorld,
TodoApp
}
}
</script>
body {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
line-height: 1.6;
background: #e8f7f0;
}
.container {
max-width: 1100px;
margin: auto;
overflow: auto;
padding: 0 2rem;
}
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
Store (index.js) code:
import Vuex from 'vuex';
import Vue from 'vue';
import TodoModule from './modules/TodoModule.js';
// Load vuex
Vue.use(Vuex);
// Create store
export default new Vuex.Store({
modules: {
TodoModule
}
});
Main.js code:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
TodoApp.vue code:
<template>
<div>
<h3>Vuex Todo App</h3>
<div class="todos">
<div class="todo" v-for="todo in allTodos" :key="todo.id">
{{ todo.title }}
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: "TodoApp",
computed: mapGetters(['allTodos'])
};
</script>
<style>
</style>
TodoModule.js code:
// import axios from "axios";
const state = {
todos: [
{
id: 1,
title: "first todo"
},
{
id: 2,
title: "second todo"
},
{
id: 3,
title: "third todo"
}
]
};
const getters = {
allTodos: state => state.todos
};
const actions = {};
const mutations = {};
export default {
state,
getters,
actions,
mutations
}
No Error on Compiler:
Error on Browser Console:
=== UPDATE ===
I still haven't fix this issue and I have tried restarting the localhost server, even my own laptop to check if it'll fix it.. no luck there.
From what I've read from answers, is it possible that this error happen because of my vue installation? Or perhaps I forgot to install something else when starting the development?
=== UPDATE 2 ===
Found the culprit, apparently my vue and vuex npm package either got corrupted or has a conflict, changing the version of vue to 2.7.8 and vuex to 3.0.1 then rerun npm i (after deleting the node_modules and package-lock.json) has fixed the issue!
Thanks for all the help!
I got the same problem while using Vue 2.
npm uninstall vuex
then
npm i vuex#3.0.1
npm install vuex by default npm installs version 4 which is not supported by Vue 2
https://github.com/vuejs/vuex/releases
Your code seems ok.
I could reproduce with no erros using TodoModule below.
const TodoModule = {
state: {
todos: [{ title: "1" }, { title: "2" }, { title: "3" }, { title: "4" }]
},
getters: {
allTodos: (state) => state.todos
}
};
export default TodoModule;
If error continues, you could check the naming on your files.
The store index.js as you said should be named as store.js.
Or perhaps restart server.
I think I might have actually done the same youtube tutorial on vuex state management but I didn't use the mapGetter helper function, instead, I used the vanilla functions of vuex for getting and setting global variables.
main.js
store: new vuex.Store({
state: {
user: {}
},
mutations: {
setUser(state, payload){
state.user = payload;
}
},
getters: {
getUser: state => state.user,
}})
any-component.js
this.user = this.$store.getters.getUser; //get
this.$store.commit("setUser", this.user); //set
I think you should change getter inTo
export default {
name: "TodoApp",
computed: mapGetters(['allTodos'])
};
===>
export default {
name: "TodoApp",
computed: {
...mapGetters(['allTodos'])
}
};
I installed phylotreejs using the following command:
npm install --save phylotree
When I try to import this into a page like this:
import * as d3 from 'd3';
import phylotree from 'phylotree/build/phylotree';
I get the following error:
Cannot read property 'phylotree' of undefined
It would be really helpful if I can understand what's going on here.
I read and tried the following things by reading nuxt documentation [https://nuxtjs.org/faq/]
import phylotree from '~/node_modules/phylotree/build/phylotree.js'
export default {
head () {
return {
script: [
{ src: '~/node_modules/phylotree/build/phylotree.js' }
],
}
},
}
but nothing seems to work
Following is the Vue page, I'm trying to create:
<template>
<div>
<section class="section">
<div class="container">
<div id="phylotree"></div>
</div>
</section>
</div>
</template>
<script>
import * as d3 from 'd3';
import phylotree from 'phylotree';
import _ from 'lodash';
export default {
data:() => ({
example_tree : "(((EELA:0.150276,CONGERA:0.213019):0.230956,(EELB:0.263487,CONGERB:0.202633):0.246917):0.094785,((CAVEFISH:0.451027,(GOLDFISH:0.340495,ZEBRAFISH:0.390163):0.220565):0.067778,((((((NSAM:0.008113,NARG:0.014065):0.052991,SPUN:0.061003,(SMIC:0.027806,SDIA:0.015298,SXAN:0.046873):0.046977):0.009822,(NAUR:0.081298,(SSPI:0.023876,STIE:0.013652):0.058179):0.091775):0.073346,(MVIO:0.012271,MBER:0.039798):0.178835):0.147992,((BFNKILLIFISH:0.317455,(ONIL:0.029217,XCAU:0.084388):0.201166):0.055908,THORNYHEAD:0.252481):0.061905):0.157214,LAMPFISH:0.717196,((SCABBARDA:0.189684,SCABBARDB:0.362015):0.282263,((VIPERFISH:0.318217,BLACKDRAGON:0.109912):0.123642,LOOSEJAW:0.397100):0.287152):0.140663):0.206729):0.222485,(COELACANTH:0.558103,((CLAWEDFROG:0.441842,SALAMANDER:0.299607):0.135307,((CHAMELEON:0.771665,((PIGEON:0.150909,CHICKEN:0.172733):0.082163,ZEBRAFINCH:0.099172):0.272338):0.014055,((BOVINE:0.167569,DOLPHIN:0.157450):0.104783,ELEPHANT:0.166557):0.367205):0.050892):0.114731):0.295021)",
}),
mounted (){
// const phylotree = require('phylotree');
var tree = d3.layout.phylotree()
.svg(d3.select("#phylotree"));
tree(example_tree).layout();
}
};
</script>
<style scoped>
#spaced {
letter-spacing: 3px;
}
.section {
padding: 1.5rem 1.5rem;
}
</style>
I was able to figure out what was going on. The d3 version for phylotree.js is v3 while I was using v5. But even then it didn't work. So, I tried it in a simple html file and found out the requirements as in this page Link.
Then tried the following script, it worked. But is there a better way to do this. Can anyone help me figure this out!
<template>
<section class="section">
<div class="container">
<svg id="tree_display" />
</div>
</section>
</template>
<script>
export default {
head () {
return {
script: [
{ src: 'https://d3js.org/d3.v3.min.js' },
{ src: 'https://veg.github.io/phylotree.js/phylotree.js' },
{ src: 'https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js' },
],
}
},
mounted (){
var example_tree = "(((EELA:0.150276,CONGERA:0.213019):0.230956,(EELB:0.263487,CONGERB:0.202633):0.246917):0.094785,((CAVEFISH:0.451027,(GOLDFISH:0.340495,ZEBRAFISH:0.390163):0.220565):0.067778,((((((NSAM:0.008113,NARG:0.014065):0.052991,SPUN:0.061003,(SMIC:0.027806,SDIA:0.015298,SXAN:0.046873):0.046977):0.009822,(NAUR:0.081298,(SSPI:0.023876,STIE:0.013652):0.058179):0.091775):0.073346,(MVIO:0.012271,MBER:0.039798):0.178835):0.147992,((BFNKILLIFISH:0.317455,(ONIL:0.029217,XCAU:0.084388):0.201166):0.055908,THORNYHEAD:0.252481):0.061905):0.157214,LAMPFISH:0.717196,((SCABBARDA:0.189684,SCABBARDB:0.362015):0.282263,((VIPERFISH:0.318217,BLACKDRAGON:0.109912):0.123642,LOOSEJAW:0.397100):0.287152):0.140663):0.206729):0.222485,(COELACANTH:0.558103,((CLAWEDFROG:0.441842,SALAMANDER:0.299607):0.135307,((CHAMELEON:0.771665,((PIGEON:0.150909,CHICKEN:0.172733):0.082163,ZEBRAFINCH:0.099172):0.272338):0.014055,((BOVINE:0.167569,DOLPHIN:0.157450):0.104783,ELEPHANT:0.166557):0.367205):0.050892):0.114731):0.295021)";
var tree = d3.layout.phylotree()
.svg(d3.select("#tree_display"));
tree(example_tree).layout();
}
};
</script>
<style scoped>
#spaced {
letter-spacing: 3px;
}
.section {
padding: 1.5rem 1.5rem;
}
</style>
Component
<template lang="html">
<div class="chat-log">
<chat-message v-for="message in messages" :message="message"></chat-message>
</div>
</template>
<script>
export default {
props: ["messages"]
}
</script>
<style lang="css">
.chat-log .chat-message:nth-child(even) {
background-color: #ccc;
}
.chat-log {
overflow-y: auto;
max-height: 400px;
}
</style>
When I change the above script code to below. I get errors..
<script>
export default {
props: ["messages"]
},
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
</script>
Error Details
Unexpected token, expected ;
Issue comes only when adding the created method, Am I missing anything?
The created lifecyle method goes within the body of the Vue component itself, not outside. I mean:
export default {
props: ["messages"],
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
}
Vue.js Lifecycle
Your created(){} method should be encapsulated within your export default {} block.
In other words, change your code this:
export default {
props: ["messages"],
created() {
$(".chat-log").scrollTop($(".chat-log").prop('scrollHeight'));
}
},
I'm working with Vuex and in one of my components, I try to pass an iterable element as function parameter in buttons v-for loop. My problem is that instead of getting the element I want, I get an empty object...
I would also like to know if I'm passing the parameter to the store actions the right way?
Code goes as follow:
//Side_bar.vue
<template>
<div id="sideBar">
<ul>
<li v-for='l in links'>
<button v-on:click='d(l.title)'>{{l.title}}</button>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'sideBar',
data () {
return {
links: [
{'title':'asset', 'valuesss':'ASSET'},
{'title':'task', 'valuesss':'TASK'},
{'title':'user', 'valuesss':'USER'}
]
}
},
computed:{
d(v){
console.log(v)
// update active table
this.$store.dispatch('updateActiveTable',v)
}
}
}
</script>
<style>
li {
list-style-type: none;
padding-bottom: 5px;
}
</style>
store file looks like this
//store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
activeTable: 'assets' // def view
};
const mutations = {
setActiveTable(context,v){
context.activeTable = v
}
};
const getters={
getActiveTable(context){
//return active table
return context.activeTable
}
};
const actions={
updateActiveTable(context,v){
console.log(context)
context.commit('setActiveTable',v)
}
}
export default new Vuex.Store({
state,
mutations,
getters,
actions
})
App.vue looks like that
<template>
<div id="app">
<sideBar></sideBar>
<tableComponent></tableComponent>
</div>
</template>
<script>
import sideBar from './components/Side_bar'
import tableComponent from './components/Table_component'
export default {
name: 'app',
components:{
sideBar,
tableComponent
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
small {
display: block;
font-style: italic;
}
</style>
The code defines d as a computed property.
It should be a method.
methods:{
d(v){
console.log(v)
// update active table
this.$store.dispatch('updateActiveTable',v)
}
}