SoFunction
Updated on 2025-04-05

Solve the problem of scrolling penetration of Mint-ui framework Popup and Datetime Picker components

The Mint-ui component library is used in mobile development, and there are two components, Popup component and Datetime Picker, which have scrollability penetration problems. The latest version of the official document does not solve this problem.

Restore the phenomenon

Official address

Scan the code on your mobile phone to view demos, and view example demonstrations of the two components Popup components and Datetime.

Cause of the problem

HTML5 touch event touchmove event: triggers continuously when the finger slides on the screen

So when the popup layer of the component Popup component and the Datetime Picker is activated, the continuous sliding up and down while the content is selected by the bounce layer will trigger the event

Solution

Block the touchmove event of the body after the pop-up layer appears, and remove the block event after the bullet layer disappears

Solution to using mint-ui component library

Popup Components

// Official example

<mt-popup
 v-model="popupVisible"
 position="bottom">
 ...
</mt-popup>

// Solution: by listening to the popupVisible variable, the touchMove event of the bode node appears after the popup window appears, and the touchMove event of the body node is restored after the popup window disappears.

const handler = function(e) {
  ();
}

// In the vue instancewatch: {
  popupVisible: function (val) {
   if(val) {
     ('body')[0].addEventListener('touchmove', , { passive: false });
   } else {
     ('body')[0].addEventListener('touchmove', , { passive: false });
   }
  }
}

Datetime Picker

// Official example

<mt-datetime-picker
  ref="picker"
  type="time"
  v-model="pickerValue">
</mt-datetime-picker>

// Solution: This component is quite a pitfall. Since Datetime Picker does not provide popup display and hidden binding variables, we do not use the method of solving popup to solve the problem. We can only solve the problem by opening the event, confirming the event, canceling the event, and clicking the masked popup window to disappear. The official attribute method only supports confirming events and opening events. There is no callback function for canceling the event plain text, and it does not support clicking on the masked pop-up window to disappear, so it is very tricky.

<mt-datetime-picker
  ref="picker"
  type="time"
  v-model="pickerValue"
  @confirm="confirm">
</mt-datetime-picker>

const handler = function(e) {
  ();
}

// In the vue instance

methods: {
  openPicker() { // Open the event    ('body')[0].addEventListener('touchmove', , { passive: false });
    this.$();
  },
  confirm() { // Confirm the event    ('body')[0].addEventListener('touchmove', , { passive: false });
  }
}

At this time, there is also a cancel callback and a masked click event. Then look at the source code, the mint-ui source code supports cancel callback events. In addition, the surprise is that after version 2.0, the visible-change event and closeOnClickModal attribute (portal) were added to the Datetime picker component, but the official documentation still did not update these attributes. The above problem is solved very well now.

Moreover, with the visible-change event, you can solve it without following the above idea. The component source code is as follows:

props: {
  ...,
  closeOnClickModal: {
    type: Boolean,
    default: true
  }
},
watch: {
  ...,
 visible(val) {
  this.$emit('visible-change', val);
 }
},
...
<span class="mint-datetime-action mint-datetime-cancel" @click="visible = false;$emit('cancel')">{{ cancelText }}</span>

Directly a visible-change method to solve it

&lt;mt-datetime-picker
  ref="picker"
  type="time"
  v-model="pickerValue"
  @confirm="confirm"
  @visible-change=""handleValueChange&gt;
&lt;/mt-datetime-picker&gt;

const handler = function(e) {
  ();
}

// In the vue instancemethods: {
  handleValueChange: function (val) {
   if(val) {
     ('body')[0].addEventListener('touchmove', , { passive: false });
   } else {
     ('body')[0].addEventListener('touchmove', , { passive: false });
   }
  }
}

The above method can solve the pitfalls encountered by the project, but each page uses the component Popup component and the Datetime Picker, which requires adding this code. When there are multiple Popup components on the page, you need to listen to multiple variables.

Better solution (The above method also has similar solutions online, and I have added the visible-change solution myself)

It is too troublesome to solve the problem in the project as above, so I thought of a solution that is better experienced. Because the appearance and disappearance of the bullet layer will trigger component updates, I thought of registering a command v-roll globally and using the command componentUpdated hook to implement this function. The code is as follows

// Global registration instructionconst handler = (e) =&gt; {
 ();
};
('roll', {
 componentUpdated(el, binding) {
  if () {
   ('body')[0].addEventListener('touchmove', handler, { passive: false });
  } else {
   ('body')[0].removeEventListener('touchmove', handler, { passive: false });
  }
 }
});

This simplifies a lot of code, and other developers only need to add a v-roll instruction to the corresponding component when using it.

// How to handle popup component&lt;mt-popup
 v-model="popupVisible"
 v-roll:visible=popupVisible&gt;
 ...
&lt;/mt-popup&gt;

// mt-datetime-picker component processing method&lt;mt-datetime-picker 
 ref="datePicker" 
 v-model="date"
 @visible-change="handleVisibleChange"
 v-roll:visible=pVisible
 ...&gt;
&lt;/mt-datetime-picker&gt;
...
data: {
  pVisible: false 
},
methods: {
  handleVisibleChange (isVisible) {
     = isVisible;
  }
}

Then I encountered a pitfall. When there are multiple components, Popup components and Datetime Picker usage instructions on the same view page, the instructions will be triggered collectively. Therefore, it will overwrite each other, such as opening the A bullet layer to block the touchMove event on the page, but another popuu component also triggers the hook function and unblocks the touchMove event, resulting in no effect.

componentUpdated: Called after the VNode and its child VNode of the component where the directive is located. // My current understanding here is that the view interface node is updated due to the appearance and disappearance of the bullet layer, so the hook bound to the v-roll instruction of other nodes is also triggered

Solution:For multiple components using multiple components in a view, pass the array type to the instruction

// Global registration instructionconst handler = (e) =&gt; {
 ();
};
('roll', {
 componentUpdated(el, binding) {
  if ( instanceof Array) {
   const visible = (e =&gt; e); // When one of the variables in the control layer of the view is true, the touchmove event can be blocked   if (visible) {
    ('body')[0].addEventListener('touchmove', handler, { passive: false });
   } else {
    ('body')[0].removeEventListener('touchmove', handler, { passive: false });
   }
  } else if (typeof  === 'boolean') {
   if () {
    ('body')[0].addEventListener('touchmove', handler, { passive: false });
   } else {
    ('body')[0].removeEventListener('touchmove', handler, { passive: false });
   }
  }
 }
});

// How to handle popup component&lt;mt-popup
 v-model="popupVisible"
 v-roll:visible=[popupVisible, pVisible]&gt;
 ...
&lt;/mt-popup&gt;

// mt-datetime-picker component processing method&lt;mt-datetime-picker 
 ref="datePicker" 
 v-model="date"
 @visible-change="handleVisibleChange"
 v-roll:visible=[popupVisible, pVisible]
 ...&gt;
&lt;/mt-datetime-picker&gt;
...
data: {
  pVisible: false 
},
methods: {
  handleVisibleChange (isVisible) {
     = isVisible;
  }
}

At present, mint-ui has not fixed this problem, so we will use the above solution to solve it. I planned to change the source code at the beginning, but it was not realistic, because I might need to update the mint-ui version in the future. You can also help check whether there are any pitfalls in the above solution.

Supplementary knowledge:There will be scrolling penetration problems on ios when using mint-ui's date plugin in Vue

Problem: When selecting a date to slide up and down on iOS, the entire page will scroll accordingly, and Android is normal

The solution is to prohibit the default scrolling mechanism of the page when the date pop-up layer appears, and to unblock the default scrolling mechanism of the page when the date pop-up layer disappears.

1. Call the date component

 &lt;div class="datePicker" style="z-index: 9999"&gt;
   &lt;mt-datetime-picker
    type="date"
    ref="picker"
    v-model="nowTime"
    year-format="{value} Year"
    month-format="{value} moon"
    date-format="{value} day"
    @confirm="handleConfirm"
    :startDate="startDate"
    :endDate="endDate"
   &gt;
   &lt;/mt-datetime-picker&gt;
  &lt;/div&gt;

2. Set up the listening function

data () {
    return {
     birthday:"", //Date of Birth     startDate: new Date('1952'),
     endDate:new Date(),
     nowTime:'1992-09-15',
    
     /*---------------------------*/
     handler:function(e){();}
    }
   },
   methods:{
    /*Solve the problem of mutual influence of iPhone page hierarchy*/
    closeTouch:function(){
     ("body")[0].addEventListener('touchmove',
      ,{passive:false});//Block default events     ("closeTouch haved happened.");
    },
    openTouch:function(){
     ("body")[0].removeEventListener('touchmove',
      ,{passive:false});//Open the default event     ("openTouch haved happened.");
    },
 }

Then listen, call the corresponding method when the pop-up window disappears

// Listen to propertieswatch:{
  signReasonVisible:function(newvs,oldvs){// There is no callback function when picker is closed, so listen to this property instead    if(newvs){
      ();
    }else{
      ();
    }
  }
},

The following is the processing of datetime-picker: (openPicker1 is the event that triggers the open selector, handleConfirm (data) is the callback function after the date is selected)

 openPicker () {
      this.$();
      ();//Close the default event 
     },
     handleConfirm (data) {
      let date = moment(data).format('YYYY-MM-DD')
       = date;
      ();//Open the default event 
     },

Then this problem was solved!

The above article solves the problem of scrolling penetration of the Mint-ui framework Popup and Datetime Picker components is all the content I share with you. I hope you can give you a reference and I hope you can support me more.