Good Day, I'm very new to Vue.js and want a navbar, which is transparent by default, but changes its background on scrolling. Unfortunately, it does not work. I tried few solutions, but none of this worked. So this JavaScript code is an example from Stack Overflow, which works in a Fiddle. If you need more information and/or code, please let me know.
Navigation.vue
<template>
<div id="navigation">
<nav class="nav-items">
<router-link class="item" to="/home">Home</router-link>
<router-link class="item" to="/about">About</router-link>
<router-link class="item" to="/japan">Japan</router-link>
</nav>
</div>
</template>
<script>
export default {
name: 'navigation'
}
import scroll from '../assets/js/scroll.js';
</script>
scroll.js
const navbar = document.querySelector('#navigation')
window.addEventListener('scroll', function(e) {
const lastPosition = window.scrollY
if (lastPosition > 50 ) {
navbar.classList.add('colored')
} else if (navbar.classList.contains('colored')) {
navbar.classList.remove('colored')
} else {
navbar.classList.remove('colored')
}
})
navigation.scss
FYI: I've removed unneccessary code here.
#navigation {
background: transparent;
.colored {
background: #fff;
transition: 0.3s;
}
}
2 Answers 2
Note: To view how to import custom code in a Vue component (general case), scroll down past the last <hr>.
Vue is a JavaScript framework and therefore you can insert vanilla code anywhere in it and it will run perfectly fine.
IMHO, you issue is not about importing vanilla code. It's about running it at the correct moment.
You have to run your code inside mounted() hook, because that's when #navigation exists in DOM:
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('navigation', {
template: '#navigationTemplate',
mounted() {
window.addEventListener('scroll',
() => document.querySelector('#navigation')
.classList.toggle('colored', window.scrollY > 50)
)
}
})
new Vue({
el: '#app'
});
#app {
min-height: 200vh;
background: url("https://picsum.photos/id/237/1024/540") no-repeat center center /cover;
}
#navigation {
background: transparent;
position: fixed;
top: 0;
padding: 1rem;
transition: 0.3s;
width: 100%;
box-sizing: border-box;
color: white;
}
#navigation.colored {
background: rgba(255, 255, 255, .85);
color: black;
}
body {
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script id="navigationTemplate" type="text/template">
<div id="navigation">
<nav class="nav-items">
<a class="item" to="/home">Home</a>
<a class="item" to="/about">About</a>
<a class="item" to="/japan">Japan</a>
</nav>
</div>
</script>
<div id="app">
<navigation />
</div>
- your
scroll.jscan safely be written as:
window.addEventListener('scroll',
() => document.querySelector('#navigation')
.classList.toggle('colored', window.scrollY > 50)
)
- Your SCSS seems incorrect:
#navigation {
.colored {
declaration
}
}
will apply declaration to any element with a class of .colored that's inside an element with the id of navigation. But your code toggles the class colored on #navigation. Therefore your SCSS should look like this:
#navigation {
&.colored {
declaration
}
}
Might not seem like much, but the & makes your code apply (or not).
- You probably want to apply
transitionto#navigation, as it should apply when it has thecoloredclass and when it doesn't. If you don't, the return transition (from.coloredto:not(.colored)) will not be animated.
For the record and to also answer your initial question, the proper way to import custom code into a Vue component is:
a) export your code as a function:
(in scroll.js)
export function menuScroll = function() {
/* your custom code here */
}
b) import it:
(in your component)
import { menuScroll } from 'path/to/scroll'
c) run it exactly where you need it:
(i.e: in mounted)
export default {
name: 'navigation',
mounted() {
menuScroll();
}
}
Obviously, you want to rename the function in accordance with its purpose/role and the project's naming conventions.
Last, but not least, if your function needs to take params, you might want to use it as a method:
export function someName = function(...args) {
/** do stuff with args **/
}
... and, in component:
import { someName } from 'path/to/it'
export default {
name: 'whatever',
methods: {
someName,
/* more methods... */
}
}
3 Comments
navigation.vue, don't import scroll.js. Instead, add a mounted() {} under name, inside export. Inside {} of mounted place the scroll.js code (or my replacement). In navigation.scss, add a & before .colored. And move the transition rule outside of &.colored (into #navigation). Unless I'm missing something, it should work as my example. If you need more help, try to replicate your issue in a codesandbox and I'll take a look. Make sure the issue is reproduced, please.scroll.js in its separate file, the proper way to do it is: wrap it inside export function menuScroll = function() { /* your old scroll.js code here */ } and import it as import { menuScroll } from 'path/to/scroll.js'. Note import must be placed before export!. And, the mounted hook should look like: mounted() { menuScroll() }. That's it.just like that
<template>
.... your HTML
</template>
<script>
export default {
data: () => ({
......data of your component
}),
mounted() {
let recaptchaScript = document.createElement('script')
recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
document.head.appendChild(recaptchaScript)
},
methods: {
......methods of your component
}
}
</script>
source : Link