I. Preparation:
Create a new vue-app:
1 2 | vue create authen-with-vue-router |
Basic Config:
- Babel.
- Esint.
Oke. Run the web:
1 2 | yarn serve |
II. Idea:
Basically, I will write a dropdown-menu
, quite similar to that of bootstrap (because I do not focus on the UI, so I only fully function it, you have time to try to improve):
Check Document Dropdown Menu of Bootstrap Here!
The problem here is, I do not use a third external Library.
Okey, make some noises!
II. Perform:
1. Directory tree:
Because only create DropdownMenu
component as List-Item
, my directory structure will basically look like Vue CLI, so I’ll show the changed part:
1 2 3 4 5 6 | - src/ |---components |---DropdownMenu |--- index.vue |--- Item.vue |
2. UI:
I will do the CSS quickly, you can use the built-in CSS of Bootstrap
loaded if you do not want to do the UI .
File app.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <span class="token selector">#app </span> <span class="token punctuation">{</span> <span class="token property">font-family</span> <span class="token punctuation">:</span> Avenir, Helvetica, Arial, sans-serif <span class="token punctuation">;</span> <span class="token property">-webkit-font-smoothing</span> <span class="token punctuation">:</span> antialiased <span class="token punctuation">;</span> <span class="token property">-moz-osx-font-smoothing</span> <span class="token punctuation">:</span> grayscale <span class="token punctuation">;</span> <span class="token property">text-align</span> <span class="token punctuation">:</span> center <span class="token punctuation">;</span> <span class="token property">color</span> <span class="token punctuation">:</span> #2c3e50 <span class="token punctuation">;</span> <span class="token property">padding</span> <span class="token punctuation">:</span> 20px <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">#nav </span> <span class="token punctuation">{</span> <span class="token property">padding</span> <span class="token punctuation">:</span> 30px <span class="token punctuation">;</span> <span class="token selector">a </span> <span class="token punctuation">{</span> <span class="token property">font-weight</span> <span class="token punctuation">:</span> bold <span class="token punctuation">;</span> <span class="token property">color</span> <span class="token punctuation">:</span> #2c3e50 <span class="token punctuation">;</span> <span class="token selector"><span class="token parent important">&</span> .router-link-exact-active </span> <span class="token punctuation">{</span> <span class="token property">color</span> <span class="token punctuation">:</span> #42b983 <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token selector">* </span> <span class="token punctuation">{</span> <span class="token property">box-sizing</span> <span class="token punctuation">:</span> border-box <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector">a </span> <span class="token punctuation">{</span> <span class="token selector"><span class="token parent important">&</span> :visited </span> <span class="token punctuation">{</span> <span class="token property">color</span> <span class="token punctuation">:</span> #2c3e50 <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token selector">.spacing </span> <span class="token punctuation">{</span> <span class="token property">padding</span> <span class="token punctuation">:</span> 100px 0 <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
File DropdownMenu/index.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token selector">button </span> <span class="token punctuation">{</span> <span class="token property">position</span> <span class="token punctuation">:</span> relative <span class="token punctuation">;</span> <span class="token property">padding</span> <span class="token punctuation">:</span> 10px 20px <span class="token punctuation">;</span> <span class="token property">background-color</span> <span class="token punctuation">:</span> white <span class="token punctuation">;</span> <span class="token property">border</span> <span class="token punctuation">:</span> 1px solid black <span class="token punctuation">;</span> <span class="token property">cursor</span> <span class="token punctuation">:</span> pointer <span class="token punctuation">;</span> <span class="token property">transition</span> <span class="token punctuation">:</span> 0.3s <span class="token punctuation">;</span> <span class="token selector"><span class="token parent important">&</span> :focus </span> <span class="token punctuation">{</span> <span class="token property">outline</span> <span class="token punctuation">:</span> 0px <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector"><span class="token parent important">&</span> :hover </span> <span class="token punctuation">{</span> <span class="token property">background</span> <span class="token punctuation">:</span> #000 <span class="token punctuation">;</span> <span class="token property">color</span> <span class="token punctuation">:</span> white <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token selector"><span class="token parent important">&</span> .isActive </span> <span class="token punctuation">{</span> <span class="token property">background</span> <span class="token punctuation">:</span> #000 <span class="token punctuation">;</span> <span class="token property">color</span> <span class="token punctuation">:</span> white <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token selector">.dropdown </span> <span class="token punctuation">{</span> <span class="token property">position</span> <span class="token punctuation">:</span> relative <span class="token punctuation">;</span> <span class="token property">width</span> <span class="token punctuation">:</span> fit-content <span class="token punctuation">;</span> <span class="token selector"><span class="token parent important">&</span> -list </span> <span class="token punctuation">{</span> <span class="token property">background</span> <span class="token punctuation">:</span> white <span class="token punctuation">;</span> <span class="token property">margin-top</span> <span class="token punctuation">:</span> 5px <span class="token punctuation">;</span> <span class="token property">position</span> <span class="token punctuation">:</span> absolute <span class="token punctuation">;</span> <span class="token property">z-index</span> <span class="token punctuation">:</span> 10 <span class="token punctuation">;</span> <span class="token property">width</span> <span class="token punctuation">:</span> 100% <span class="token punctuation">;</span> <span class="token property">border</span> <span class="token punctuation">:</span> 1px solid black <span class="token punctuation">;</span> <span class="token property">border-radius</span> <span class="token punctuation">:</span> 4px <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
File DropdownMenu/Item.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token selector">.item </span> <span class="token punctuation">{</span> <span class="token property">display</span> <span class="token punctuation">:</span> block <span class="token punctuation">;</span> <span class="token property">width</span> <span class="token punctuation">:</span> 100% <span class="token punctuation">;</span> <span class="token property">padding</span> <span class="token punctuation">:</span> 5px 10px <span class="token punctuation">;</span> <span class="token property">transition</span> <span class="token punctuation">:</span> 0.3s <span class="token punctuation">;</span> <span class="token property">position</span> <span class="token punctuation">:</span> relative <span class="token punctuation">;</span> <span class="token selector"><span class="token parent important">&</span> :hover </span> <span class="token punctuation">{</span> <span class="token property">background</span> <span class="token punctuation">:</span> black <span class="token punctuation">;</span> <span class="token property">color</span> <span class="token punctuation">:</span> white <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
3. Logic code:
At DropdownMenu/index.vue
I will have the props
:
- Use an passed
id
to support the DOM and distinguish betweenmulti dropdown-menu
. - There are
prop
arrays
for passingitem
to thedropdown-menu
.
File Home.vue
:
1 2 3 4 5 6 7 8 9 10 | <span class="token operator"><</span> template <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"home"</span> <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"spacing"</span> <span class="token operator">></span> <span class="token operator"><</span> DropdownMenu id <span class="token operator">=</span> <span class="token string">"dropdownmenu1"</span> <span class="token punctuation">:</span> arrays <span class="token operator">=</span> <span class="token string">"arrays"</span> <span class="token operator">></span> DropdownMenu <span class="token number">1</span> <span class="token operator"><</span> <span class="token operator">/</span> DropdownMenu <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> template <span class="token operator">></span> |
Inside DropdownMenu/index.vue
:
- There
isOpen
variable is theDropdown-menu
open switch (true
is open,false
is closed). Item.vue
toItem.vue
1function
:closeDropdown
performs ourDropdown-menu
closure from theItem
inside.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <span class="token operator"><</span> template <span class="token operator">></span> <span class="token operator"><</span> div <span class="token punctuation">:</span> id <span class="token operator">=</span> <span class="token string">"id"</span> <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"dropdown"</span> <span class="token operator">></span> <span class="token operator"><</span> button @click <span class="token operator">=</span> <span class="token string">"isOpen = !isOpen"</span> <span class="token punctuation">:</span> <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"{ isActive: isOpen }"</span> <span class="token operator">></span> <span class="token operator"><</span> slot <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> button <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"dropdown-list"</span> v <span class="token operator">-</span> <span class="token keyword">if</span> <span class="token operator">=</span> <span class="token string">"isOpen"</span> <span class="token operator">></span> <span class="token operator"><</span> Item v <span class="token operator">-</span> <span class="token keyword">for</span> <span class="token operator">=</span> <span class="token string">"(item, index) in arrays"</span> <span class="token punctuation">:</span> key <span class="token operator">=</span> <span class="token string">"index"</span> <span class="token punctuation">:</span> item <span class="token operator">=</span> <span class="token string">"item"</span> <span class="token punctuation">:</span> closeDropdown <span class="token operator">=</span> <span class="token string">"callToClose"</span> <span class="token operator">></span> <span class="token punctuation">{</span> <span class="token punctuation">{</span> item <span class="token punctuation">.</span> text <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span> <span class="token operator">/</span> Item <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> template <span class="token operator">></span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'DropdownMenu'</span> <span class="token punctuation">,</span> components <span class="token punctuation">:</span> <span class="token punctuation">{</span> Item <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token function">data</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> isOpen <span class="token punctuation">:</span> <span class="token boolean">false</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> props <span class="token punctuation">:</span> <span class="token punctuation">{</span> arrays <span class="token punctuation">:</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> Array <span class="token punctuation">,</span> <span class="token keyword">default</span> <span class="token punctuation">:</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> id <span class="token punctuation">:</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> String <span class="token punctuation">,</span> required <span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token function">callToClose</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> isOpen <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token operator"><</span> <span class="token operator">/</span> script <span class="token operator">></span> |
File DropdownMenu/Item.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token operator"><</span> template <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"item"</span> @click <span class="token operator">=</span> <span class="token string">"doFunc"</span> <span class="token operator">></span> <span class="token operator"><</span> slot <span class="token operator">/</span> <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> template <span class="token operator">></span> <span class="token operator"><</span> script <span class="token operator">></span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span> name <span class="token punctuation">:</span> <span class="token string">'Item'</span> <span class="token punctuation">,</span> props <span class="token punctuation">:</span> <span class="token punctuation">{</span> item <span class="token punctuation">:</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> Object <span class="token punctuation">,</span> required <span class="token punctuation">:</span> <span class="token boolean">true</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> closeDropdown <span class="token punctuation">:</span> <span class="token punctuation">{</span> type <span class="token punctuation">:</span> Function <span class="token punctuation">,</span> <span class="token keyword">default</span> <span class="token punctuation">:</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token function">doFunc</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> console <span class="token punctuation">.</span> <span class="token function">log</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> item <span class="token punctuation">.</span> link <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">closeDropdown</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> <span class="token operator"><</span> <span class="token operator">/</span> script <span class="token operator">></span> |
In theory, click
button
will open and close our DropdownMenu
, in addition, click
each Item
will also close Dropdown
. If I want to perform a certain job in Item
, I pass the function
to the item
in the arrays
and use the methods
in Item.vue
to recall that job.
In addition, DropdownMenu
must be closed when we click outside of it. At this time, I use window.addEventListener('click', ...)
to detect each click and check if I am clicking on DropdownMenu
or not?
For now, I will use the hook
:
created
toaddEventListener
.beforeDestroy
toremoveEventListener
.
File DropdownMenu/index.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <span class="token function">created</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> window <span class="token punctuation">.</span> <span class="token function">addEventListener</span> <span class="token punctuation">(</span> <span class="token string">'click'</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> checkClickOn <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token function">beforeDestroy</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> window <span class="token punctuation">.</span> <span class="token function">removeEventListener</span> <span class="token punctuation">(</span> <span class="token string">'click'</span> <span class="token punctuation">,</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> checkClickOn <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> methods <span class="token punctuation">:</span> <span class="token punctuation">{</span> <span class="token function">checkClickOn</span> <span class="token punctuation">(</span> event <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> <span class="token operator">!</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> id <span class="token punctuation">)</span> <span class="token punctuation">.</span> <span class="token function">contains</span> <span class="token punctuation">(</span> event <span class="token punctuation">.</span> target <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">this</span> <span class="token punctuation">.</span> isOpen <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> |
The code document.getElementById('your-id).contains(event.target)
will return true
if we click on an HTML object that is a child of your-id
(prop) that we passed above.
Now, I will create one more DropdownMenu
next to check the case of multi dropdown-menu
:
File Home.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <span class="token operator"><</span> template <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"home"</span> <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"spacing"</span> <span class="token operator">></span> <span class="token operator"><</span> DropdownMenu id <span class="token operator">=</span> <span class="token string">"dropdownmenu1"</span> <span class="token punctuation">:</span> arrays <span class="token operator">=</span> <span class="token string">"arrays"</span> <span class="token operator">></span> DropdownMenu <span class="token number">1</span> <span class="token operator"><</span> <span class="token operator">/</span> DropdownMenu <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> div <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token string">"spacing"</span> <span class="token operator">></span> <span class="token operator"><</span> DropdownMenu id <span class="token operator">=</span> <span class="token string">"dropdownmenu2"</span> <span class="token punctuation">:</span> arrays <span class="token operator">=</span> <span class="token string">"arrays"</span> <span class="token operator">></span> DropdownMenu <span class="token number">2</span> <span class="token operator"><</span> <span class="token operator">/</span> DropdownMenu <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> div <span class="token operator">></span> <span class="token operator"><</span> <span class="token operator">/</span> template <span class="token operator">></span> |
It worked, perfectly!
I would like to share my repos, everyone please clone and comment for me.
Link github: Here!
Thank you, Mr. Trần Đại Sơn for giving me an opinion on the eventListener
section. Thanks for everyone who has read your article.