简体   繁体   中英

Using Vue to listen to DOM events outside of the app

I need to use Vue.js to progressively enhance an existing server-side rendered form. I need to alter the <select> 's <options> depending on the value of another field on the form.

As I see it, I cannot mount Vue on the parent <form> (or another parent element) as I lose all my server-side rendered content, which I need to maintain.

I have mounted on the <select> that I wish to make dynamic. This allows me to dynamically generate <option> s however I wish. However the other form input element (a sibling-ish of the mounted <select> ) is now outside of my Vue scope. How can my Vue app be alerted of changes to the dependent field so it can update my <option> s accordingly?

As I understand it, Vue has its own events system so I'm going to have to hook up a DOM event listener myself - which is completely fine. That's about as far as I've gotten.

Aside: I understand that given infinite time, money, and resources, I should follow the trend of having my entire user experience be an SPA which would solve this issue in a rocket-launcher-to-hammer-a-nail sort of way. However this is not an option. I must progressively enhance the SSR output.

You could still query the document for sibling element with document.querySelector() , and call addEventListener() from within a Vue instance:

 const ALL_DATA = [ {id: 1, value: 1, text: 'One'}, {id: 2, value: 2, text: 'Two'}, {id: 3, value: 3, text: 'Three'}, ]; new Vue({ el: '#app', data: () => ({ options: [ ...ALL_DATA, ] }), mounted() { document.querySelector('#option-type').addEventListener('change', e => { switch (e.target.value) { case 'even': this.options = ALL_DATA.filter(x => x.value % 2 === 0); break; case 'odd': default: this.options = ALL_DATA.filter(x => x.value % 2 !== 0); break; } }) } }); document.getElementById('myForm').addEventListener('submit', e => { e.stopPropagation(); e.preventDefault(); }); 
 <script src="https://unpkg.com/vue@2.5.17"></script> <form action="#" id="myForm"> <fieldset id="option-type"> <label>Even <input name="option-type" type="radio" value="even"> </label> <label>Odd <input name="option-type" type="radio" value="odd"> </label> </fieldset> <select name="option" id="app"> <option v-for="o in options" value="o.value" :key="o.id">{{o.text}}</option> </select> </form> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM