簡體   English   中英

如果元素單擊vue組件,如何添加活動類?

[英]How can I add class active if the element click on the vue component?

我的Vue組件是這樣的:

 Vue.component('list-category', { template: "#lc", props: ['data', 'category', 'search'], data() { return { open: false, categoryId: this.category } }, mounted() { let isDataOpen = (d) => d.id === this.categoryId || d.children && d.children.some(isDataOpen); this.open = isDataOpen(this.data); }, computed: { icon() { return { 'fa-plus': !this.open, 'fa-minus': this.open, } }, isFolder() { return this.data.children && this.data.children.length }, isShow() { return this.open ? 'show' : 'hide' } }, methods: { toggle() { this.open = !this.open }, filterByCategory(id) { this.categoryId = id } } }) new Vue({ el: '#app', data() { return { categories: [{ id: 1, name: 'England', children: [{ id: 3, name: 'Chelsea', children: [{ id: 7, name: 'Hazard' }, { id: 8, name: 'Morata' } ] }, { id: 4, name: 'Manchester United', children: [{ id: 9, name: 'Pogba' }, { id: 10, name: 'Lukaku' } ] } ] }, { id: 2, name: 'Spain', children: [{ id: 5, name: 'Real Madrid', children: [{ id: 11, name: 'Ronaldo' }, { id: 12, name: 'Bale' } ] }, { id: 6, name: 'Barcelona', children: [{ id: 13, name: 'Messi' }, { id: 14, name: 'Suarez' } ] }, ] } ], category: 7 } } }) 
 .active { background: yellow; } .pd-search-filter > .panel-body ul.filter-category { padding-left: 0; list-style: none; margin: 0 -15px 0; } .pd-search-filter > .panel-body ul.filter-category > li a { display: block; padding: 10px 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pd-search-filter > .panel-body ul.filter-category > li a:last-child { padding-left: 45px; } .pd-search-filter > .panel-body ul.filter-category > li a:focus, .pd-search-filter > .panel-body ul.filter-category > li a:hover { background-color: #eeeeee; text-decoration: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul { padding-left: 0; list-style: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul > li > a { padding-left: 30px; } .show { display: block !important; } .hide { display: none !important; } 
 <script src="https://unpkg.com/vue"></script> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <div id="app"> <div class="panel panel-default pd-search-filter"> <div class="panel-heading"> <h3 class="panel-title"><i class="fa fa-circle-o"></i> By Category</h3> </div> <div class="panel-body"> <ul class="filter-category" v-for="list in categories"> <list-category :data="list" :category="category"></list-category> </ul> </div> </div> </div> <template id="lc"> <li> <!--parent--> <a v-if="isFolder" href="javascript:" @click="toggle"> <span class="fa fa-fw" :class="icon"></span> {{data.name}} </a> <!--if not folding, we do not need an binding event--> <a v-else href="javascript:" :title="data.name" :class="{active: data.id === categoryId}" @click="filterByCategory(data.id)"><span class="fa fa-fw fa-circle-o"></span> {{data.name}}</a> <!--children--> <ul v-if="isFolder" :class="isShow"> <list-category v-for="(data, index) in data.children" :key="index" :data="data" :search="search" :category="categoryId"></list-category> </ul> </li> </template> 

似乎您需要查看演示和完整代碼

就像這樣: http : //jsfiddle.net/vxLhbo5m/861/

從演示中可以看到類別危險活動。 如果我單擊morata類別,則該類別無效。 我已經編寫了代碼

我怎么解決這個問題?

================================================== =========================

您將必須將類別計算器移至觀察程序(而不是mount() ),並發出/監聽從子級到父級的某些事件,以更新類別並折疊未選擇的子樹。

在此更新了JSFiddle

變化:

  • 模板:

    • 家長:

      • 從:

         <div id="app"> ... <list-category :data="list" :category="category"></list-category> 
      • 添加偵聽category事件並更新父級的category屬性:

         <div id="app"> ... <list-category :data="list" :category="category" @category="category = $event"></list-category> 
    • 兒童:

      • 從:

         <template id="lc"> ... <list-category v-for="(data, index) in data.children" :key="index" :data="data" :search="search" :category="categoryId"></list-category> 
      • category事件並將其發出給父對象:

         <template id="lc"> ... <list-category v-for="(data, index) in data.children" :key="index" :data="data" :search="search" :category="categoryId" @category="$emit('category', $event)"></list-category> 
  • JavaScript(全部包含在子代碼中):

    • filterByCategory更改為發出事件,而不是更改屬性:

      • 從:

         filterByCategory(id) { this.categoryId = id } 
      • 至:

         filterByCategory(id) { this.$emit('category', id); } 
    • 卸下已mounted掛鈎並添加觀察者:

      • 卸下已安裝:

         mounted() { let isDataOpen = (d) => d.id === this.categoryId || d.children && d.children.some(isDataOpen); this.open = isDataOpen(this.data); }, 
      • 添加觀察者以在父category發生更改時接聽:

         watch: { category: { handler() { this.categoryId = this.category let isDataOpen = (d) => d.id === this.categoryId || d.children && d.children.some(isDataOpen); this.open = isDataOpen(this.data); }, immediate: true } } 

演示:

 Vue.component('list-category', { template: "#lc", props: ['data', 'category', 'search'], data() { return { open: false, categoryId: this.category } }, computed: { icon() { return { 'fa-plus': !this.open, 'fa-minus': this.open, } }, isFolder() { return this.data.children && this.data.children.length }, isShow() { return this.open ? 'show' : 'hide' } }, methods: { toggle() { this.open = !this.open }, filterByCategory(id) { this.$emit('category', id); } }, watch: { category: { handler() { this.categoryId = this.category let isDataOpen = (d) => d.id === this.categoryId || d.children && d.children.some(isDataOpen); this.open = isDataOpen(this.data); }, immediate: true } } }) new Vue({ el: '#app', data() { return { categories: [{ id: 1, name: 'England', children: [{ id: 3, name: 'Chelsea', children: [{ id: 7, name: 'Hazard' }, { id: 8, name: 'Morata' } ] }, { id: 4, name: 'Manchester United', children: [{ id: 9, name: 'Pogba' }, { id: 10, name: 'Lukaku' } ] } ] }, { id: 2, name: 'Spain', children: [{ id: 5, name: 'Real Madrid', children: [{ id: 11, name: 'Ronaldo' }, { id: 12, name: 'Bale' } ] }, { id: 6, name: 'Barcelona', children: [{ id: 13, name: 'Messi' }, { id: 14, name: 'Suarez' } ] }, ] } ], category: 7 } } }) 
 .active { background: yellow; } .pd-search-filter > .panel-body ul.filter-category { padding-left: 0; list-style: none; margin: 0 -15px 0; } .pd-search-filter > .panel-body ul.filter-category > li a { display: block; padding: 10px 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pd-search-filter > .panel-body ul.filter-category > li a:last-child { padding-left: 45px; } .pd-search-filter > .panel-body ul.filter-category > li a:focus, .pd-search-filter > .panel-body ul.filter-category > li a:hover { background-color: #eeeeee; text-decoration: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul { padding-left: 0; list-style: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul > li > a { padding-left: 30px; } .show { display: block !important; } .hide { display: none !important; } 
 <script src="https://unpkg.com/vue"></script> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <div id="app"> <div class="panel panel-default pd-search-filter"> <div class="panel-heading"> <h3 class="panel-title"><i class="fa fa-circle-o"></i> By Category</h3> </div> <div class="panel-body"> <ul class="filter-category" v-for="list in categories"> <list-category :data="list" :category="category" @category="category = $event"></list-category> </ul> </div> </div> </div> <template id="lc"> <li> <!--parent--> <a v-if="isFolder" href="javascript:" @click="toggle"> <span class="fa fa-fw" :class="icon"></span> {{data.name}} </a> <!--if not folding, we do not need an binding event--> <a v-else href="javascript:" :title="data.name" :class="{active: data.id === categoryId}" @click="filterByCategory(data.id)"><span class="fa fa-fw fa-circle-o"></span> {{data.name}}</a> <!--children--> <ul v-if="isFolder" :class="isShow"> <list-category v-for="(data, index) in data.children" :key="index" :data="data" :search="search" :category="categoryId" @category="$emit('category', $event)"></list-category> </ul> </li> </template> 

您無法通過子組件控制父元素的數據。 為了更改父級的數據,您需要將更改發送給父級,而不是更改父級的數據。

請找到以下內容以了解如何使用this.$emit 我知道我必須更改json數據以避免對同一模板進行遞歸調用,但是現在您對如何更改父數據元素有了一個了解。

 Vue.component('list-category', { template: "#lc", props: ['data', 'category', 'search'], data() { return { open: false, categoryId: this.category } }, mounted() { let isDataOpen = (d) => d.id === this.categoryId || d.children && d.children.some(isDataOpen); this.open = isDataOpen(this.data); }, computed: { icon() { return { 'fa-plus': !this.open, 'fa-minus': this.open, } }, isFolder() { return this.data.children && this.data.children.length }, isShow() { return this.open ? 'show' : 'hide' } }, methods: { toggle() { this.open = !this.open }, filterByCategory: function(id){ this.$emit('update-active-category', id); console.log('Emitting: ' + id); } } }) new Vue({ el: '#app', data() { return { categories: [{ id: 1, name: 'England', children: [{ id: 3, name: 'Chelsea', children: [{ id: 7, name: 'Hazard' }, { id: 8, name: 'Morata' } ] }, { id: 4, name: 'Manchester United', children: [{ id: 9, name: 'Pogba' }, { id: 10, name: 'Lukaku' } ] } ] }, { id: 2, name: 'Spain', children: [{ id: 5, name: 'Real Madrid', children: [{ id: 11, name: 'Ronaldo' }, { id: 12, name: 'Bale' } ] }, { id: 6, name: 'Barcelona', children: [{ id: 13, name: 'Messi' }, { id: 14, name: 'Suarez' } ] }, ] } ], category: 7 } }, methods: { updateActiveCategory: function(id) { this.category = id; } } }) 
 .active { background: yellow !important; } .pd-search-filter > .panel-body ul.filter-category { padding-left: 0; list-style: none; margin: 0 -15px 0; } .pd-search-filter > .panel-body ul.filter-category > li a { display: block; padding: 10px 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .pd-search-filter > .panel-body ul.filter-category > li a:last-child { padding-left: 45px; } .pd-search-filter > .panel-body ul.filter-category > li a:focus, .pd-search-filter > .panel-body ul.filter-category > li a:hover { background-color: #eeeeee; text-decoration: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul { padding-left: 0; list-style: none; } .pd-search-filter > .panel-body ul.filter-category > li a + ul > li > a { padding-left: 30px; } .show { display: block !important; } .hide { display: none !important; } 
 <script src="https://unpkg.com/vue"></script> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> <div id="app"> <div class="panel panel-default pd-search-filter"> <div class="panel-heading"> <h3 class="panel-title"><i class="fa fa-circle-o"></i> By Category</h3> </div> <div class="panel-body"> <ul class="filter-category" v-for="list in categories"> <list-category :data="list" :category="category" @update-active-category="updateActiveCategory"> </list-category> </ul> </div> </div> </div> <template id="lc"> <li> <!--parent--> <a v-if="isFolder" href="javascript:" @click="toggle"> <span class="fa fa-fw" :class="icon"></span> {{data.name}} </a> <!--if not folding, we do not need an binding event--> <a v-else href="javascript:" :title="data.name" :class="{active: data.id === category}" @click="filterByCategory(data.id)" @update-active-category="filterByCategory"><span class="fa fa-fw fa-circle-o"></span> {{data.name}}</a> <!--children--> <ul v-if="isFolder" :class="isShow"> <list-category v-for="(data, index) in data.children" :key="index" :data="data" :search="search" :category="category" @update-active-category="filterByCategory"></list-category> </ul> </li> </template> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM