Recently I was writing a page for an H5, and one of the components used pullToRefresh in ANTD-Mobile. Boy, the car flipped over!

Realize the function

PullToRefresh component is used for pull-up loading of data on the next page to realize continuous loading of data.

Rollover phenomenon

The pullToRefresh component in Chrome on the Web side can be used to load the data on the next page normally, and the H5 embedded in the APP can be accessed by the simulator without any problems. However, when you get to the real machine or open the connection of H5 directly on the real machine, the pullToRefresh will flip over and cannot be pulled up (the function that cannot trigger its pull up operation), which is outrageous!

Trying to reason

Through a variety of local information, finally found in the ANTD-mobile issues of the big guy’s explanation.

The problem is as follows: AntD-Mobile pullToRefresh component trigger pull-up source code is isEdge function in the following code

if (direction === UP) {
    return ele.scrollHeight - ele.scrollTop === ele.clientHeight; 
}
Copy the code

At first glance, there is no problem, but the height of ele on the mobile terminal is dynamically calculated by REM. The algorithm is:

let remHeight = 2.48 // The height of the element in rem
let __fontUnit = 43.3333 // The pixels represented by 1rem for mobile phones with different resolutions
someElementHeight = remHeight * __fontUnit
Copy the code

Because of the resolution of different mobile phones someElementHeight is the decimal A that may appear decimals, while ele.clientHeight obtained with JS code is always the integer B, Thus, there is an error between the real PX value of someElementHeight and the real value obtained through JS code on different models.

If A

conclusion

Because rem is used, the height (px) dynamically set to the element may be decimal, resulting in ele.scrollheight-ele.scrolltop! = el.clientheight, unable to trigger sliding threshold.

The solution

This paper only gives their own solution may not be the optimal solution, please use as appropriate!

Modify the source code

Ele.scrollheight-ele.scrolltop === ele.clientheight This statement determines the exception caused by the failure to trigger the pull-up refresh operation

So change the source code to

_this2.isEdge = function (ele, direction) {
            var container = _this2.props.getScrollContainer();
            if (container && container === document.body) {
                // In chrome61 `document.body.scrollTop` is invalid
                var scrollNode = document.scrollingElement ? document.scrollingElement : document.body;
                if (direction === UP) {
                    return scrollNode.scrollHeight - scrollNode.scrollTop <= window.innerHeight;
                }
                if (direction === DOWN) {
                    return scrollNode.scrollTop <= 0; }}if (direction === UP) {
                var __height = Math.abs(ele.scrollHeight - ele.scrollTop - ele.clientHeight)// Change the code
                return __height>=0 && __height<=1 // Change the code
                return ele.scrollHeight - ele.scrollTop === ele.clientHeight; // Source code
            }
            if (direction === DOWN) {
                return ele.scrollTop <= 0; }};Copy the code

Node_modules = antD-mobile = antD-mobile = antD-mobile = antD-mobile = antD-mobile = antD-mobile = antD-mobile

When I asked later, I realized that this is only source code, but the actual code path referenced in the project is in package.json in ANTD-mobile

"main": "lib/index.js"."module": "es/index.js".Copy the code

Whether it’s main or module or even browser we’ll talk about next time or we’ll look into it ourselves, but we’re using module which is es/index, so find out where the pullToRefresh component came from.

export { default as PullToRefresh } from './pull-to-refresh/index';
Copy the code

Go to the es/pull-to-refresh/index.js file

.import RPullToRefresh from 'rmc-pull-to-refresh'; .var PullToRefresh = function (_React$Component) {
    _inherits(PullToRefresh, _React$Component);

    function PullToRefresh() {... } _createClass(PullToRefresh, [{key: 'render'.value: function render() {...// I'm here
            return React.createElement(RPullToRefresh, _extends({}, this.props, { indicator: ind })); }}]);return PullToRefresh;
}(React.Component);

export default PullToRefresh;
Copy the code

RPullToRefresh (rC-pull-to-refresh) {rc-pull-to-refresh (rC-pull-to-refresh) {rc-pull-to-refresh (rC-pull-to-refresh); Then go to the actual referenced PullToRefresh. Js file, modify isEdge, restart the project, and finally fix the problem.

To solve the follow-up

However, only my local modification dependency will appear when the project is pulled by others, the installation dependency is not modified, so we need to solve the problem that everyone can automatically modify the file when the code is pulled.

This problem can be handled in several ways:

  • Encapsulate the component itself and reference it directly within the project
  • The Colone project re-released the NPM package, but it was a bit of a hassle.
  • .

The patch-package plug-in is introduced to patch dependencies

package.json

Add the following code to the package.json file

"scripts": {..."postinstall": "patch-package"
  },
Copy the code

Perform patch

NPX patch-package package-name (package name to be changed)Copy the code

It will automatically compare your local file with the clean NPM package to determine the difference between the two pieces of code and record the patch. Patches will be created in the project directory under which the patches will be found. You only need to upload the patch to the code repository, and then everyone who pulls the project installation dependency will automatically patch the dependency package and write your changes into the dependency package.

This is the whole rollover and all the repair process!