为啥在 Vue 中使用模态时我的 v-if 不触发?
Posted
技术标签:
【中文标题】为啥在 Vue 中使用模态时我的 v-if 不触发?【英文标题】:Why does my v-if not fire when using modals with Vue?为什么在 Vue 中使用模态时我的 v-if 不触发? 【发布时间】:2019-10-07 03:34:17 【问题描述】:我正在使用 v-if 来控制我的 Vue 应用程序中页面的显示。 'page' 数据属性跟踪当前页面并通过按钮单击进行更新。在我引入模态之前,这非常有效,因为现在当我打开一个模态并导航回几个页面(使用我的应用程序的导航按钮)时,尽管属性已正确更新,但页面仍无法显示。
这是一个简化的示例 - 导航到页面 B 然后 C 然后显示模式 2。取消模式 2,然后导航到页面 B 并且没有任何显示(尽管标题指示页面属性是 B)。
https://jsfiddle.net/fLmq0dxn/1/
我已经在引导模式和本机 js 模式中尝试过这种方法,但会出现同样的问题。控制台中没有报告错误。我认为这可能是错误嵌套的 div,但我已经检查了这些并通过了验证器。
我意识到我的导航方法是原始的,并且模态可能应该是组件,但我是 Vue 的新手,据我了解,我的方法“应该”工作。谁能解释为什么不喜欢?
html:
<div id="app">
<p>(app.page = page)</p>
<br/>
<div class="page" id="A" v-if="page=='A'">
Page A
<br/>
<button v-on:click="pager('B')">To B</button>
</div>
<div class="page" id="B" v-if="page=='B'">
Page B
<br/>
<button v-on:click="pager('C')">To C</button>
<button v-on:click="modalOpen('mod1')">Modal</button>
</div>
<!-- ************ Modal 1 ************************************ -->
<div id="mod1" class="mod">
<div class="mod-content">
<span class="mod-close" v-on:click="modalClose">×</span>
<h1>Modal 1</h1>
<button v-on:click="modalClose" class="btn btn-secondary">Cancel</button>
</div>
</div>
<div class="page" id="C" v-if="page=='C'">
Page C
<br/>
<button v-on:click="pager('B')">To B</button>
<button v-on:click="modalOpen('mod2')">Modal</button>
</div>
<!-- ************ Modal 2 ************************************ -->
<div id="mod2" class="mod">
<div class="mod-content">
<span class="mod-close" v-on:click="modalClose">×</span>
<h1>Modal 2</h1>
<button v-on:click="modalClose" class="btn btn-secondary">Cancel</button>
</div>
</div>
</div>
CSS:
/* The Modal (background) */
.mod
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
/* Modal Content/Box */
.mod-content
background-color: #fefefe;
margin: 20% auto;
padding: 20px;
border: 1px solid #888;
border-radius:8px;
width: 90%;
max-width:800px;
/* The Close Button */
.mod-close
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
.mod-close:hover,
.mod-close:focus
color: black;
text-decoration: none;
cursor: pointer;
new Vue(
el: "#app",
data:
page: "A"
,
methods:
pager: function(target)
this.page=target;
,
modalOpen: function(modID)
$('#'+ modID).css('display','block');
,
modalClose: function()
$('.mod').css('display','none');
)
【问题讨论】:
使用#id模型关闭$('#'+modeid).css('display','none')
感谢@Alaa - 修复了这个非常简单的示例,但不适用于我的实际应用程序。为什么我不能使用他们的类关闭模式? $('.mod').css('display','none');
【参考方案1】:
不幸的是,将 Vue 与 jQuery 结合是有风险的。
在您的特定情况下,似乎当您尝试关闭模式时,jQuery 会查找所有具有“mod”类的元素,但是在隐藏它们时,选择会被 Vue 篡改,最终会隐藏不正确的元素(在您的情况下,您的页面 B) 的内容。 Vue 的设计初衷不是让另一个库摆弄 DOM。
您可以仅使用 Vue“轻松”实现您的目标。由于您通过更改样式来管理模态框,因此您可以使用 Vue class and/or style binding 做类似的事情。
例如您可以拥有一个覆盖您的display: none
的类,并且您可以根据数据有条件地应用该类,这与您对页面所做的非常相似。您甚至可以使用 v-if
管理您的模式,就像您对页面所做的一样。
条件类示例:https://jsfiddle.net/jfx8mbya/
由 v-if 管理的模态示例:
new Vue(
el: "#app",
data:
page: "A",
modal: null
,
methods:
pager: function(target)
this.page = target;
,
modalOpen: function(modID)
this.modal = modID;
,
modalClose: function()
this.modal = null;
)
/* The Modal (background) */
.mod
/*display: none;*/
/* Hidden by default */
position: fixed;
/* Stay in place */
z-index: 1;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
overflow: auto;
/* Enable scroll if needed */
background-color: rgb(0, 0, 0);
/* Fallback color */
background-color: rgba(0, 0, 0, 0.4);
/* Black w/ opacity */
/* Modal Content/Box */
.mod-content
background-color: #fefefe;
margin: 20% auto;
padding: 20px;
border: 1px solid #888;
border-radius: 8px;
width: 90%;
max-width: 800px;
/* The Close Button */
.mod-close
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
.mod-close:hover,
.mod-close:focus
color: black;
text-decoration: none;
cursor: pointer;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>(app.page = page)</p>
<br/>
<div class="page" id="A" v-if="page=='A'">
Page A
<br/>
<button v-on:click="pager('B')">To B</button>
</div>
<div class="page" id="B" v-if="page=='B'">
Page B
<br/>
<button v-on:click="pager('C')">To C</button>
<button v-on:click="modalOpen('mod1')">Modal</button>
</div>
<!-- ************ Modal 1 ************************************ -->
<div id="mod1" class="mod" v-if="modal === 'mod1'">
<div class="mod-content">
<span class="mod-close" v-on:click="modalClose">×</span>
<h1>Modal 1</h1>
<button v-on:click="modalClose" class="btn btn-secondary">Cancel</button>
</div>
</div>
<div class="page" id="C" v-if="page=='C'">
Page C
<br/>
<button v-on:click="pager('B')">To B</button>
<button v-on:click="modalOpen('mod2')">Modal</button>
</div>
<!-- ************ Modal 2 ************************************ -->
<div id="mod2" class="mod" v-if="modal === 'mod2'">
<div class="mod-content">
<span class="mod-close" v-on:click="modalClose">×</span>
<h1>Modal 2</h1>
<button v-on:click="modalClose" class="btn btn-secondary">Cancel</button>
</div>
</div>
</div>
【讨论】:
同意。优秀的答案.. 并详细说明(更多的长期解决方案).. 如果您想在 Vue 应用程序中呈现浏览页面的外观 - 最好使用Vue Router,imo。这正是它所做的——隐藏/显示 DOM 的不同部分,特别是看起来好像你正在浏览页面......在 Vue 中抛弃 jQuery 式的思维)——你可以将每个模式放在自己的“页面”中,等等。Basic Vue Router demo以上是关于为啥在 Vue 中使用模态时我的 v-if 不触发?的主要内容,如果未能解决你的问题,请参考以下文章