从 vue1 迁移到 vue2



我正在尝试将此示例下拉菜单从 vue1 迁移到 vue2。

http://vuejsexamples.com/vue-dropdown-menu/

我已将ready方法更改为mounted,删除了json过滤器并重写了 for 循环close,因为它在控制台中导致错误。

现在,当我运行它时没有任何错误,但是下拉菜单仍然无法正常工作 - 当我在菜单外单击时它不会关闭。 任何人都可以帮助迁移它吗?

new Vue({
el: '#menu',

mounted: function()
{
var self = this
window.addEventListener('click', function(e){
if (! e.target.parentNode.classList.contains('menu__link--toggle'))
{
self.close()
}
}, false)
},

data: {
dropDowns: {
ranking: { open: false}  
}
},

methods: {
toggle: function(dropdownName)
{
this.dropDowns[dropdownName].open = !this.dropDowns[dropdownName].open;
},

close: function()
{
for (var i = 0; i < this.dropDowns.length; i++) {
this.dropDowns[dd].open = false;
}
}
}

})
body {
margin: 2rem 0;
}
ul {
list-style: none;
}
.menu {
display: flex;
}
.menu__item {
position: relative;
padding-right: 3rem;
}
.menu__link {
text-transform: uppercase;
}
.menu__icon {
margin: 0 !important;
}
.open .dropdown-menu {
display: block;
}
.dropdown-menu {
font-size: 0.9rem;
position: absolute;
min-width: 130px;
top: 2.2rem;
display: none;
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.dropdown-menu__item:first-child .dropdown-menu__link {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.dropdown-menu__item:last-child .dropdown-menu__link {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.dropdown-menu__link {
display: block;
padding: 1rem;
color: blue;
background-color: #fafafa;
}
.dropdown-menu__link:hover {
color: green;
background-color: #ccc;
}
<script src="https://unpkg.com/vue@2.4.2/dist/vue.min.js"></script>
<div id="menu"class="row">  
<ul class="menu">
<li class="menu__item">
<a class="menu__link" href="#">Home</a>
</li>
<li class="menu__item menu__item--dropdown" v-on:click="toggle('ranking')" v-bind:class="{'open' : dropDowns.ranking.open}">
<a class="menu__link menu__link--toggle" href="#">
<span>Rangliste</span>
<i class="menu__icon fa fa-angle-down"></i>
</a>
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<a class="dropdown-menu__link" href="#">Aktuelle Runde</a>
</li>
<li class="dropdown-menu__item">
<a class="dropdown-menu__link" href="#">Siegerliste</a>
</li>
</ul>
</li>
<li class="menu__item">
<a class="menu__link" href="#">Belegungskalender</a>
</li>
</ul>

<pre>{{ dropDowns }}</pre>
</div>

为了解决这个问题,我必须进行两项更改:

首先是在事件侦听器中。当我测试它时,我得到了一个异常,因为e.target.parentNode.classList是未定义的(当元素没有类时(。错误是在尝试访问undefined的功能contains时。

所以我做了一个变量并检查了它的真实值。如果未定义,则它不包含所需的类,因此您可以关闭菜单。

下一个也是主要的问题是代码的这一部分:

for (var i = 0; i < this.dropDowns.length; i++) {

this.DropDownsObject,不是Array。对象没有长度,因此不能使用dropDowns.length

相反,您将提取对象键并循环它们,然后使用键名称访问值。

我使用Array.prototype.forEach而不是循环来获得更实用的方法,这是最终结果:

new Vue({
el: '#menu',
mounted: function() {
var self = this
window.addEventListener('click', function(e) {
var classList = e.target.parentNode.classList;
//Check if classList is a valid value. If classList is undefined, contains would throw an error.
if (!classList || !classList.contains('menu__link--toggle')) {
self.close()
}
}, false)
},
data: {
dropDowns: {
ranking: {
open: false
}
}
},
methods: {
toggle: function(dropdownName) {
this.dropDowns[dropdownName].open = !this.dropDowns[dropdownName].open;
},
close: function() {
var dropDowns = this.dropDowns;
Object.keys(dropDowns).forEach(function(key, index) {
dropDowns[key].open = false;
});
}
}
})
body {
margin: 2rem 0;
}
ul {
list-style: none;
}
.menu {
display: flex;
}
.menu__item {
position: relative;
padding-right: 3rem;
}
.menu__link {
text-transform: uppercase;
}
.menu__icon {
margin: 0 !important;
}
.open .dropdown-menu {
display: block;
}
.dropdown-menu {
font-size: 0.9rem;
position: absolute;
min-width: 130px;
top: 2.2rem;
display: none;
box-shadow: 0px 6px 12px rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.dropdown-menu__item:first-child .dropdown-menu__link {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.dropdown-menu__item:last-child .dropdown-menu__link {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
}
.dropdown-menu__link {
display: block;
padding: 1rem;
color: blue;
background-color: #fafafa;
}
.dropdown-menu__link:hover {
color: green;
background-color: #ccc;
}
<script src="https://unpkg.com/vue@2.4.2/dist/vue.min.js"></script>
<div id="menu" class="row">
<ul class="menu">
<li class="menu__item">
<a class="menu__link" href="#">Home</a>
</li>
<li class="menu__item menu__item--dropdown" v-on:click="toggle('ranking')" v-bind:class="{'open' : dropDowns.ranking.open}">
<a class="menu__link menu__link--toggle" href="#">
<span>Rangliste</span>
<i class="menu__icon fa fa-angle-down"></i>
</a>
<ul class="dropdown-menu">
<li class="dropdown-menu__item">
<a class="dropdown-menu__link" href="#">Aktuelle Runde</a>
</li>
<li class="dropdown-menu__item">
<a class="dropdown-menu__link" href="#">Siegerliste</a>
</li>
</ul>
</li>
<li class="menu__item">
<a class="menu__link" href="#">Belegungskalender</a>
</li>
</ul>
<pre>{{ dropDowns }}</pre>
</div>

我建议你把这个菜单变成一个组件。就像现在一样,这是不可重用的实例,您肯定需要在项目中的更多位置使用此下拉列表。

最新更新