I am not a web developer and this is the first time I play with a web framework – so please go easy on me. The framework I’m trying to learn is vue.js. Version 3.
What I try to achieve:
- 4 app instances. (nav, defaultApp, bootstrapApp, vueApp).
- Depending on the navbar item I select, one of the 3 other apps should show. The others shall hide.
I looked at various places on the internet about how to do it and added console.log() output, which convinces me, that the calls actually happen as I think they should.
I am aware, that there are alternatives, but the v-show approach seems most readable to me.
What is not working:
- The 3 apps are visible all the time and never get hidden.
It is probably a very silly mistake on my part. Who can spot it?
<!DOCTYPE html>
<html>
<head>
<title>Learning web framworks</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65"
crossorigin="anonymous"/>
<!-- TODO: Make sure to use the production build (*.prod.js) when deploying for production.<!-->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<nav id="navbar" class="navbar navbar-dark navbar-expand-lg bg-dark">
<div class="container-fluid">
<a @click.prevent="showDefault" class="navbar-brand" href="#">Navbar</a>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a @click.prevent="showBootstrap" class="nav-link" href="#">Bootstrap</a>
</li>
<li class="nav-item">
<a @click.prevent="showVue" class="nav-link" href="#">Vue.js</a>
</li>
</ul>
</div>
</nav>
<div v-show="isShow" id="default-content">
<p>default content</p>
</div>
<div v-show="isShow" id="bootstrap-content">
<p>bootstrap content</p>
</div>
<div v-show="isShow"
id="vue-content">
<p>vue content</p>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4"
crossorigin="anonymous"></script>
<script>
const { createApp } = Vue
let defaultApp = createApp({
data() {
return {
isShow: true,
}
},
watch: {
isShow(val,oldVal) {
console.log(`defaultApp.isShow( ${oldVal} -> ${val} )`);
}
}
}).mount("#default-content");
let bootstrapApp = createApp({
data() {
return {
isShow: false,
}
},
watch: {
isShow(val,oldVal) {
console.log(`bootstrapApp.isShow( ${oldVal} -> ${val} )`);
}
}
}).mount("#bootstrap-content");
let vueApp = createApp({
data() {
return {
isShow: false,
}
},
watch: {
isShow(val,oldVal) {
console.log(`vueApp.isShow( ${oldVal} -> ${val} )`);
}
}
}).mount("#vue-content");
let nav = createApp({
data() {
return {
// pages: [
// { title: "Navbar", url: "#default-content" },
// { title: "Bootstrap", url: "#bootstrap-content" },
// { title: "Vue.js", url: "#vue-content" },
// ],
};
},
methods: {
showDefault: function() {
console.log("showDefault()");
defaultApp.$data.isShow = true;
bootstrapApp.$data.isShow = false;
vueApp.$data.isShow = false;
},
showBootstrap: function() {
console.log("showBootstrap()");
defaultApp.$data.isShow = false;
bootstrapApp.$data.isShow = true;
vueApp.$data.isShow = false;
},
showVue: function () {
console.log("showVue()");
defaultApp.$data.isShow = false;
bootstrapApp.$data.isShow = false;
vueApp.$data.isShow = true;
}
}
}).mount('#navbar');
</script>
</body>
</html>
>Solution :
Don’t use v-show on the root element of the apps – probably treat the root element as not being part of the "vue" App at all, it’s just a container for the App
Instead, use it on the content
In your example, just the <p> but you may want to wrap actual content in a div or appropriate
const { createApp } = Vue;
let defaultApp = createApp({
data() {
return {
isShow: true,
};
},
watch: {
isShow(val, oldVal) {
console.log(`defaultApp.isShow( ${oldVal} -> ${val} )`);
},
},
}).mount("#default-content");
let bootstrapApp = createApp({
data() {
return {
isShow: false,
};
},
watch: {
isShow(val, oldVal) {
console.log(`bootstrapApp.isShow( ${oldVal} -> ${val} )`);
},
},
}).mount("#bootstrap-content");
let vueApp = createApp({
data() {
return {
isShow: false,
};
},
watch: {
isShow(val, oldVal) {
console.log(`vueApp.isShow( ${oldVal} -> ${val} )`);
},
},
}).mount("#vue-content");
let nav = createApp({
data() {
return {
};
},
methods: {
showDefault: function () {
console.log("showDefault()");
defaultApp.$data.isShow = true;
bootstrapApp.$data.isShow = false;
vueApp.$data.isShow = false;
},
showBootstrap: function () {
console.log("showBootstrap()");
defaultApp.$data.isShow = false;
bootstrapApp.$data.isShow = true;
vueApp.$data.isShow = false;
},
showVue: function () {
console.log("showVue()");
defaultApp.$data.isShow = false;
bootstrapApp.$data.isShow = false;
vueApp.$data.isShow = true;
},
},
}).mount("#navbar");
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" />
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<nav id="navbar" class="navbar navbar-dark navbar-expand-lg bg-dark">
<div class="container-fluid">
<a @click.prevent="showDefault" class="navbar-brand" href="#">Navbar</a>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a @click.prevent="showBootstrap" class="nav-link" href="#">Bootstrap</a>
</li>
<li class="nav-item">
<a @click.prevent="showVue" class="nav-link" href="#">Vue.js</a>
</li>
</ul>
</div>
</nav>
<div id="default-content">
<p v-show="isShow">default content</p>
</div>
<div id="bootstrap-content">
<p v-show="isShow">bootstrap content</p>
</div>
<div id="vue-content">
<p v-show="isShow">vue content</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>