2

I have some problem with the matchMedia function that I wrote inside my computed property in Vue. The problem is when I load/refresh page, the function does not work. It only back to work after I resize the screen in Responsive Design Mode at the browser.

Here the code of my app.js

     computed: {
        widthChange() {
            if (matchMedia) {
                    var mqT = window.matchMedia(" (max-width: 850px) and (min-width: 600px) ")

                    function changeWidthT(mqT) {
                    const sectionRight = document.querySelector(".section-right")
                    if (mqT.matches) {
                        sectionRight.classList.remove("col-7")
                    }
                    else {
                        sectionRight.classList.add("col-7")
                    }
                }

                mqT.addListener(changeWidthT)
            }
        }
    },

and I call the computed property inside the parent of the page

<div class="frontpage-parent" :class="widthChange">...
</div>
  • How is matchmedia defined? If it comes from another script, there are quite a chances it is not defined at the time Vue compute the value for the first time. Since Vue caches the results of `computed` properties, it will not be revaluated until one of the observables changes. – BroiSatse Oct 30 '19 at 13:52
  • Actually after reading a bit more of what you did here - this code should not live in the computed properties at all. You don't even return anything! – BroiSatse Oct 30 '19 at 13:56
  • Oh, this is standard window element. Neat, good to know! – BroiSatse Oct 30 '19 at 14:00
  • I placed the function in the component with Vue.extend. I tried to use methods property but still gave me the same result – αякjυηισя K Oct 30 '19 at 14:08

4 Answers4

1

You are misusing computed properties here. They are supposed to be getters, meaning they are only to return ready to sue values. You're actually attaching event listeners there.

Instead, you need to use data attribute and initialize your listeners within mounted hook:

export default {
  name: 'Blah',
  data () {
    const tabletViewQuery = matchMedia('...')
    return {
      tabletViewQuery: tabletViewQuery.
      tabletView: tableViewQuery.matches,
    }  
  },
  mounted () {
     this.tabletViewQuery.addListener(() => {
       this.tabletView = tableViewQuery.matches
     }
  }
}

and use it in a table:

<div class="section-right" :class="{ 'col-7': tabletView }">

However, probably much cleaner solution would be to use vue-match-media plugin.

BroiSatse
  • 44,031
  • 8
  • 61
  • 86
0

Have you tried calling widthChange() in the mounted hook so that it runs on load?

Edit Try placing const tst = this.widthChange; in the mousnted hook

Tsepo Nkalai
  • 1,492
  • 11
  • 18
0

matchMedia in Vue with reactiveness

The aforementioned answers did not work for me. Improved BroiSatse's answer by replacing the deprecated addListener with change event as mentioned on https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList

Vue Options API with Typescript example:

data(): { mediaQuery: MediaQueryList; isTablet: boolean; } {
    const mediaQuery = window.matchMedia('(max-width: 1024px)');

    return {
        mediaQuery,
        isTablet: mediaQuery.matches
    };
},
mounted(): void {
    this.mediaQuery.addEventListener('change', () => {
        this.isTablet = this.mediaQuery.matches;
    });
}
Datsos
  • 528
  • 1
  • 8
  • 13
-1

A year later, but with a small tweak I made it work in Vuejs for a mobile/desktop purposes:

computed: {
...
...
      widthChange() {
        if (matchMedia) {
          const matchMediaQuery = window.matchMedia(" (max-width: 1024px) ")
          const changeWidthT = (matchMediaQuery) => {
            this.isMobileExperience = matchMediaQuery.matches ? true : false;
          }
          mqT.addListener(changeWidthT)
        }
      }
    },
    mounted() { 
      const awakeResizeListener = this.widthChange;
    },
...
...

With a v-if and v-else evaluating a isMobileExperience data option you are good to go with the resizing.

Hope this can help anyone

Crisarji
  • 1
  • 1