Difference in behavior between inline templates and SFC templates

I am trying to use the vue-phone-number-input component in my f7-vue app. It works fine when using in f7 app that is inlined with templates and script all in the html file. And it also works fine in a regular Vue app without f7. But when I try to use this component in an f7-vue app built by webpack with SFC and es6 modules, then an infinite render loop error occurs:

vue.runtime.esm.js?2b0e:619 [Vue warn]: You may have an infinite update loop in a component render function.

found in

---> <CountrySelector> at CountrySelector.vue
       <VuePhoneNumberInput> at index.vue
         <F7PageContent>
           <F7Page>
             <PhonePage> at src/components/PhonePage.vue
               <F7View>
                 <F7App>
                   <App> at src/App.vue
                     <Root>

The inline and module-based apps seem to be basically the same, yet the component behaves differently. I distilled a repro as simply as I could. The source code is at: https://github.com/jacobg/f7-phone-input

Demos of the repro are here:

  1. webpack version with error - https://jacobg.github.io/f7-phone-input
  2. inline version that works fine - https://jacobg.github.io/f7-phone-input/inline.html

What could be the problem? Am I missing something?

Thanks.

In the webpack version, if the <phone-page /> component is declared directly in App.vue without making a route for it, then it works fine. The problem occurs when it’s a routable component. What would cause that issue?

It also works if I programatically create the VuePhoneNumberInput in the PhonePage’s pageAfterIn event handler:

    pageAfterIn () {
      const vuePhoneNumberInput = new VuePhoneNumberInputClass({
        parent: this,
        propsData: {
          value: this.phoneNumber
        }
      })
      vuePhoneNumberInput.$on('input', value => { this.phoneNumber = value })
      vuePhoneNumberInput.$mount()
      this.$el.querySelector('.container').appendChild(vuePhoneNumberInput.$el)
    }

Why is the component sensitive to being rendered when mounting vs pageAfterIn? There seems to be a similar issue here:

Another thought: This is the first time I’ve used a non-f7 input component in an f7 app. Is there a quirk to that? Do f7 components comply in some way to how f7 apps render, such that non f7 components (maybe input or other components with bindings) might have issues?

Ideally you should never use inline templates with Vue, especially on production. There shouldn’t be any behavior difference, but inline templates are limited.

I checked the repo and can say that issue somewhere is on plugin side, there is something wrong with it producing infinite loop.

I’m not using inline templates. It was just to try to debug the problem.

The infinite loop has something to do with focus and the use of the v-click-outside directive. What’s throwing me off is that it works fine in 3 scenarios, and breaks in 1 scenario. The 3 scenarios it works fine in are: (1) vue without f7; (2) f7-vue using inline templates; and (3) f7-vue and programatically adding the component in the mounted event of the parent.

That’s why I was just wondering if there’s any rendering or focusing magic you’re aware of in the f7 routed pages?

Well, there is no really any rendering magic, at least from what i see nothing should break the rendering logic.

There is still something wrong with plugin for sure, if i register it globally, issue will gone:

import VuePhoneNumberInput from 'vue-phone-number-input'
Vue.component('vue-phone-number-input', VuePhoneNumberInput)

Thanks @nolimits4web. I also tried global registration, and it works fine. It’s so strange. Why would it make a difference?

This better to ask to that plugin developer :slight_smile:

1 Like