如何通过方法解决 vue-transitions 是否被触发的问题
How to solve an issue with vue-transitions being triggered or not through methods
我正在研究 vue-cli
的研究项目,尽管这是一个简单的项目,但我正在尝试应用我一直在学习的一些东西。
我有一个 header 和两个 routes
:
- 投资组合
- 股票
一旦进入这两个 routes
中的任何一个,我都设置了一个简单的 fade
动画 routes
。
这里有两个问题,我认为两者是相关的。我将按照下面列出的 posting code
块后进入它。
我将 post 我的代码如下:
Header.vue(这是我的header)
<template>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<router-link to="/" class="navbar-brand"><a>Stock Trade</a></router-link>
<div class="d-inline" @click="toPortfolio">
<ul class="navbar-nav mr-auto">
<router-link :to="{ name: 'portfolio'}"
tag="li" class="nav-item nav-link"><a
class="text-decoration-none">Portfolio</a></router-link>
</ul>
</div>
<div class="collapse navbar-collapse" @click="toStocks">
<ul class="navbar-nav mr-auto">
<router-link :to="{name: 'stocks'}"
tag="li" class="nav-item nav-link">
<a class="text-decoration-none">Stocks</a>
</router-link>
</ul>
</div>
<div class="collapse navbar-collapse end-day">
<div class="navbar-nav ml-auto">
<li class="nav-item nav-link">End Day</li>
</div>
</div>
<div class="d-inline" @click="isDropping = !isDropping">
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle"
href="#"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
Save & Load <span class="dropdown-toggle-no-caret"></span>
</a>
<!-- I must understand why it does not work below-->
<div class="dropdown-menu"
:class="{show: isDropping}"
aria-labelledby="navbarDropdown">
<a class="dropdown-item " href="#">Save Data</a>
<a class="dropdown-item" href="#">Load Data</a>
</div>
</li>
</ul>
</div>
<div>
<!-- Got to add a Getter here instead so "DRY" does not happen with the "EUR" assignment-->
<strong class="navbar-text" style="color: dimgray">Funds: {{$store.state.funds}}</strong>
</div>
</nav>
</template>
<script>
import {mapActions} from 'vuex'
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js'
export default {
data() {
return {
isDropping: false
}
},
methods: {
...mapActions({
toPortfolio: types.COMMIT_TO_PORTFOLIO,
toStocks: types.COMMIT_TO_STOCKS
})
}
}
</script>
<style scoped>
a {
color: dimgray;
}
a:hover{
color: black !important;
}
.end-day {
cursor: pointer;
}
</style>
Stocks.vue(这是显示股票的地方)
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showStocks: types.GET_STOCKS
})
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc;
}
.stock-title {
background-color: lightskyblue;
color: royalblue;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
margin: 0;
padding: 10px -1px 10px 10px;
}
p {
align-self: flex-end;
}
.stock-content {
display: flex;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: royalblue;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
</style>
Portfolio.vue
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showPortfolio: types.GET_PORTFOLIO
})
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc
}
.stock-title {
background-color: #ffbf00;
color: indianred;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
vertical-align: baseline;
margin: 0;
padding: 10px -1px 10px 10px;
}
.stock-content {
display: flex;
}
p {
align-self: flex-end;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: indianred;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import 'bootstrap/dist/css/bootstrap.css'
import BootstrapVue from 'bootstrap-vue'
import {store} from "./store/store";
import {routes} from "./routes";
Vue.use(BootstrapVue);
Vue.use(VueRouter);
export const router = new VueRouter({
routes,
mode: 'history',
scrollBehavior(to, from, savedPosition) {
if(savedPosition) {
return savedPosition
}
if (to.hash) {
return {selector: to.hash}
}
return {x: 0, y: 0};
}
});
new Vue({
el: '#app',
store,
router,
render: h => h(App)
});
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import altAnims from "@/store/modules/altAnims";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
sharesValue: {
BMW: 1,
Apple: 0,
FaceBook: 0,
Google: 0
},
user:{
funds: 1000,
shares: {
BMW: 0,
Apple: 0,
FaceBook: 0,
Google: 0
}
}
},
modules: {
altAnims
}
});
types.js
// Getters
export const GET_PORTFOLIO = 'portfolio/shared';
export const GET_STOCKS = 'stocks/shared';
//Mutations
export const MUTATE_PORTFOLIO = 'shared/SET_PORTFOLIO';
export const MUTATE_STOCKS = 'shared/SET_STOCKS';
//Actions
export const COMMIT_TO_PORTFOLIO = 'shared/ALTERNATE_PORTFOLIO';
export const COMMIT_TO_STOCKS = 'shared/ALTERNATE_STOCKS';
altAnims.js(这个动画我就是在这里胡闹的)
import * as types from '../types';
const state = {
showStock: false,
showPortfolio: false
};
const getters = {
[types.GET_PORTFOLIO]: state => {
return state.showPortfolio
},
[types.GET_STOCKS]: state => {
return state.showStock
}
};
const mutations = {
[types.MUTATE_PORTFOLIO]: state => {
state.showPortfolio = true;
state.showStock = false
},
[types.MUTATE_STOCKS]: state => {
state.showStock = true;
state.showPortfolio = false
}
};
const actions = {
[types.COMMIT_TO_PORTFOLIO]: ({commit}) => {
commit(types.MUTATE_PORTFOLIO);
},
[types.COMMIT_TO_STOCKS]: ({commit}) => {
commit(types.MUTATE_STOCKS);
}
};
export default {
state,
getters,
mutations,
actions
}
第一期
我尝试做的第一件事是创建简单的 fade
动画,你们可以在 Stocks.vue
和 Portfolio.vue
文件上看到,应该由 @click
事件发生在 Headers.vue
.
嗯,第一个问题是,由于某种原因,当我重新加载页面并触发 @click
event
第一次 进入任何Profile.vue
或 Stocks.vue
都不会出现 animation
。但是在彼此之间切换后它开始工作。
我不明白为什么它在第一次点击时不起作用,因为您可以在 altAnims.js
上看到这两个项目的 state
最初设置为 false
。
const state = {
showStock: false,
showPortfolio: false
};
然后一旦提交 mutating
的 action
和 state
,正如您在 altAnims.js
的进展中看到的那样,反转他们的 Boolean
语句,第一次点击 v-if
应该读取 getter
和 state
从 false
到 true
,你可以看到 @click
事件做了什么在 Header.vue
第二期
尽管我一开始并没有解决这个问题,但我还是尝试继续前进。
这就是我尝试做的@Portfolio.vue
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="revealBMW">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealApple">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealFaceBook">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealGoogle">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showPortfolio: types.GET_PORTFOLIO
})
},
methods: {
revealBMW(){
if(this.$store.state.sharesValue.BMW > 0) {
return this.showPortfolio
}
},
revealApple(){
if(this.$store.state.sharesValue.Apple > 0) {
return this.showPortfolio }
},
revealFaceBook(){
if(this.$store.state.sharesValue.FaceBook > 0) {
return this.showPortfolio }
},
revealGoogle(){
if(this.$store.state.sharesValue.Google > 0) {
return this.showPortfolio }
}
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc
}
.stock-title {
background-color: #ffbf00;
color: indianred;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
vertical-align: baseline;
margin: 0;
padding: 10px -1px 10px 10px;
}
.stock-content {
display: flex;
}
p {
align-self: flex-end;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: indianred;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
</style>
我已经添加了一些methods
,所以每次我进入这条路线时,我只会显示在altAnims.js
的状态下共享数量大于0的容器。为了测试这一点,我硬编码了 BMW: 1
,最终结果是 animation
停止工作,BMW 股票 container
也没有响应我的 methods
。
我不确定这是否是一个好的做法,也许将这些方法放在 computed
中,或者我缺少的完全不同的东西。
很抱歉提出这么长的问题,充满了代码块。我试图尽可能详细。
我想就两个问题
寻求帮助
P.S - 我刚刚想到的一个想法是,在这种情况下,是否可以对每个要加载的 container
使用 templates
。我没有试过,但是可以吗?
提前干杯和感谢!
要写的东西太多了,Codereview 会是更好的地方,但是....
Here 你可以找到我对这个问题的看法。要寻找的东西:
- 使用
<route-view>
的过渡,不使用 vuex 和其他复杂的东西 - 使用 appear
进行调整,因此它在初始渲染和 mode="out-in"
上进行过渡(只需尝试将其删除以查看效果)
- 更好的存储状态 - 不要使用公司名称作为对象键,并非每个公司名称都是有效的 JS 标识符
- 重写了
Portfolio
和 Stocks
组件以使用 v-for
呈现来自商店的数组数据
使用 Vue 路由器的转换
<transition name="fade" mode="out-in" appear>
<router-view :key="$route.fullPath"/>
</transition>
我正在研究 vue-cli
的研究项目,尽管这是一个简单的项目,但我正在尝试应用我一直在学习的一些东西。
我有一个 header 和两个 routes
:
- 投资组合
- 股票
一旦进入这两个 routes
中的任何一个,我都设置了一个简单的 fade
动画 routes
。
这里有两个问题,我认为两者是相关的。我将按照下面列出的 posting code
块后进入它。
我将 post 我的代码如下:
Header.vue(这是我的header)
<template>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<router-link to="/" class="navbar-brand"><a>Stock Trade</a></router-link>
<div class="d-inline" @click="toPortfolio">
<ul class="navbar-nav mr-auto">
<router-link :to="{ name: 'portfolio'}"
tag="li" class="nav-item nav-link"><a
class="text-decoration-none">Portfolio</a></router-link>
</ul>
</div>
<div class="collapse navbar-collapse" @click="toStocks">
<ul class="navbar-nav mr-auto">
<router-link :to="{name: 'stocks'}"
tag="li" class="nav-item nav-link">
<a class="text-decoration-none">Stocks</a>
</router-link>
</ul>
</div>
<div class="collapse navbar-collapse end-day">
<div class="navbar-nav ml-auto">
<li class="nav-item nav-link">End Day</li>
</div>
</div>
<div class="d-inline" @click="isDropping = !isDropping">
<ul class="navbar-nav ml-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle"
href="#"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
Save & Load <span class="dropdown-toggle-no-caret"></span>
</a>
<!-- I must understand why it does not work below-->
<div class="dropdown-menu"
:class="{show: isDropping}"
aria-labelledby="navbarDropdown">
<a class="dropdown-item " href="#">Save Data</a>
<a class="dropdown-item" href="#">Load Data</a>
</div>
</li>
</ul>
</div>
<div>
<!-- Got to add a Getter here instead so "DRY" does not happen with the "EUR" assignment-->
<strong class="navbar-text" style="color: dimgray">Funds: {{$store.state.funds}}</strong>
</div>
</nav>
</template>
<script>
import {mapActions} from 'vuex'
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js'
export default {
data() {
return {
isDropping: false
}
},
methods: {
...mapActions({
toPortfolio: types.COMMIT_TO_PORTFOLIO,
toStocks: types.COMMIT_TO_STOCKS
})
}
}
</script>
<style scoped>
a {
color: dimgray;
}
a:hover{
color: black !important;
}
.end-day {
cursor: pointer;
}
</style>
Stocks.vue(这是显示股票的地方)
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showStocks">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Buy</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showStocks: types.GET_STOCKS
})
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc;
}
.stock-title {
background-color: lightskyblue;
color: royalblue;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
margin: 0;
padding: 10px -1px 10px 10px;
}
p {
align-self: flex-end;
}
.stock-content {
display: flex;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: royalblue;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
</style>
Portfolio.vue
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="showPortfolio">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showPortfolio: types.GET_PORTFOLIO
})
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc
}
.stock-title {
background-color: #ffbf00;
color: indianred;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
vertical-align: baseline;
margin: 0;
padding: 10px -1px 10px 10px;
}
.stock-content {
display: flex;
}
p {
align-self: flex-end;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: indianred;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import 'bootstrap/dist/css/bootstrap.css'
import BootstrapVue from 'bootstrap-vue'
import {store} from "./store/store";
import {routes} from "./routes";
Vue.use(BootstrapVue);
Vue.use(VueRouter);
export const router = new VueRouter({
routes,
mode: 'history',
scrollBehavior(to, from, savedPosition) {
if(savedPosition) {
return savedPosition
}
if (to.hash) {
return {selector: to.hash}
}
return {x: 0, y: 0};
}
});
new Vue({
el: '#app',
store,
router,
render: h => h(App)
});
store.js
import Vue from 'vue'
import Vuex from 'vuex'
import altAnims from "@/store/modules/altAnims";
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
sharesValue: {
BMW: 1,
Apple: 0,
FaceBook: 0,
Google: 0
},
user:{
funds: 1000,
shares: {
BMW: 0,
Apple: 0,
FaceBook: 0,
Google: 0
}
}
},
modules: {
altAnims
}
});
types.js
// Getters
export const GET_PORTFOLIO = 'portfolio/shared';
export const GET_STOCKS = 'stocks/shared';
//Mutations
export const MUTATE_PORTFOLIO = 'shared/SET_PORTFOLIO';
export const MUTATE_STOCKS = 'shared/SET_STOCKS';
//Actions
export const COMMIT_TO_PORTFOLIO = 'shared/ALTERNATE_PORTFOLIO';
export const COMMIT_TO_STOCKS = 'shared/ALTERNATE_STOCKS';
altAnims.js(这个动画我就是在这里胡闹的)
import * as types from '../types';
const state = {
showStock: false,
showPortfolio: false
};
const getters = {
[types.GET_PORTFOLIO]: state => {
return state.showPortfolio
},
[types.GET_STOCKS]: state => {
return state.showStock
}
};
const mutations = {
[types.MUTATE_PORTFOLIO]: state => {
state.showPortfolio = true;
state.showStock = false
},
[types.MUTATE_STOCKS]: state => {
state.showStock = true;
state.showPortfolio = false
}
};
const actions = {
[types.COMMIT_TO_PORTFOLIO]: ({commit}) => {
commit(types.MUTATE_PORTFOLIO);
},
[types.COMMIT_TO_STOCKS]: ({commit}) => {
commit(types.MUTATE_STOCKS);
}
};
export default {
state,
getters,
mutations,
actions
}
第一期
我尝试做的第一件事是创建简单的 fade
动画,你们可以在 Stocks.vue
和 Portfolio.vue
文件上看到,应该由 @click
事件发生在 Headers.vue
.
嗯,第一个问题是,由于某种原因,当我重新加载页面并触发 @click
event
第一次 进入任何Profile.vue
或 Stocks.vue
都不会出现 animation
。但是在彼此之间切换后它开始工作。
我不明白为什么它在第一次点击时不起作用,因为您可以在 altAnims.js
上看到这两个项目的 state
最初设置为 false
。
const state = {
showStock: false,
showPortfolio: false
};
然后一旦提交 mutating
的 action
和 state
,正如您在 altAnims.js
的进展中看到的那样,反转他们的 Boolean
语句,第一次点击 v-if
应该读取 getter
和 state
从 false
到 true
,你可以看到 @click
事件做了什么在 Header.vue
第二期
尽管我一开始并没有解决这个问题,但我还是尝试继续前进。
这就是我尝试做的@Portfolio.vue
<template>
<div class="d-flex flex-wrap justify-content-sm-around">
<transition name="fade">
<div class="wrapper" v-if="revealBMW">
<div class="stock-title">
<h4 class="box-headers">BMW</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealApple">
<div class="stock-title">
<h4 class="box-headers">Apple</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealFaceBook">
<div class="stock-title">
<h4 class="box-headers">Facebook</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
<transition name="fade">
<div class="wrapper" v-if="revealGoogle">
<div class="stock-title">
<h4 class="box-headers">Google</h4>
<p class="box-headers" style="font-size: 13px">(Price: 20 EUR)</p>
</div>
<div class="stock-content">
<input type="text" class="mr-auto" placeholder="How many shares?">
<button>Sell</button>
</div>
</div>
</transition>
</div>
</template>
<script>
import {mapGetters} from 'vuex';
import * as types from '/Users/Dev/WebstormProjects/the-trader-app/src/store/types.js';
export default {
computed: {
...mapGetters({
showPortfolio: types.GET_PORTFOLIO
})
},
methods: {
revealBMW(){
if(this.$store.state.sharesValue.BMW > 0) {
return this.showPortfolio
}
},
revealApple(){
if(this.$store.state.sharesValue.Apple > 0) {
return this.showPortfolio }
},
revealFaceBook(){
if(this.$store.state.sharesValue.FaceBook > 0) {
return this.showPortfolio }
},
revealGoogle(){
if(this.$store.state.sharesValue.Google > 0) {
return this.showPortfolio }
}
}
}
</script>
<style scoped>
.wrapper {
border: solid lightgray 1px;
width: 500px;
margin-top: 20px;
border-radius: 5px;
box-shadow: 3px 3px 5px 6px #ccc
}
.stock-title {
background-color: #ffbf00;
color: indianred;
display: flex;
flex-wrap: wrap;
padding: 7px 0 0 20px;
}
.box-headers {
display: inline-block;
vertical-align: baseline;
margin: 0;
padding: 10px -1px 10px 10px;
}
.stock-content {
display: flex;
}
p {
align-self: flex-end;
}
input {
margin: 10px;
padding: 10px;
}
button {
background-color: indianred;
color: white;
padding: 0 20px;
border-radius: 5px;
justify-self: center;
margin: 10px;
}
::placeholder {
font-size: 15px;
}
.fade-enter {
opacity: 0;
}
.fade-enter-active {
transition: opacity 2s;
}
.fade-leave-active {
transition: opacity 2s;
opacity: 0;
}
</style>
我已经添加了一些methods
,所以每次我进入这条路线时,我只会显示在altAnims.js
的状态下共享数量大于0的容器。为了测试这一点,我硬编码了 BMW: 1
,最终结果是 animation
停止工作,BMW 股票 container
也没有响应我的 methods
。
我不确定这是否是一个好的做法,也许将这些方法放在 computed
中,或者我缺少的完全不同的东西。
很抱歉提出这么长的问题,充满了代码块。我试图尽可能详细。
我想就两个问题
寻求帮助P.S - 我刚刚想到的一个想法是,在这种情况下,是否可以对每个要加载的 container
使用 templates
。我没有试过,但是可以吗?
提前干杯和感谢!
要写的东西太多了,Codereview 会是更好的地方,但是....
Here 你可以找到我对这个问题的看法。要寻找的东西:
- 使用
<route-view>
的过渡,不使用 vuex 和其他复杂的东西 - 使用appear
进行调整,因此它在初始渲染和mode="out-in"
上进行过渡(只需尝试将其删除以查看效果) - 更好的存储状态 - 不要使用公司名称作为对象键,并非每个公司名称都是有效的 JS 标识符
- 重写了
Portfolio
和Stocks
组件以使用v-for
呈现来自商店的数组数据
使用 Vue 路由器的转换
<transition name="fade" mode="out-in" appear>
<router-view :key="$route.fullPath"/>
</transition>