Demand background

During long form verification, you need to prompt the corresponding problem and locate the specific position to improve user interaction experience.

Scroll view Navigation anchor point

1. Scroll view wraps the form

<template> <scroll-view :scroll-y="true" :scroll-into-view="navIndex"> <! </scroll-view> </template>Copy the code

2. Set anchor points

<template>
  <view id="nav1">Anchor point 1</view>
</template>
Copy the code

3. Locate the anchor

this.navIndex = "nav1";
Copy the code

There is a problem

After the first positioning, the anchor cannot be located by scrolling the scroll bar

Guess may be unable to locate the same anchor position, and try using Vue debugging render problem three sets:

  • key
  • nextTick
  • setTimeout

Solve the positioning problem, before positioning, the original anchor point is cleared, and then reset the anchor point

this.navIndex = null; this.$nextTick(() => { this.navIndex = 'nav1'; });
Copy the code

Problem analysis

Why resetting anchor points in $nextTick?

Scroll through the uni-app source code to find the Scrollview component:

# src/core/view/components/scroll-view/index.vue
Copy the code

Inside the component, the watch scrollIntoView data change is performed using the _scrollIntoViewChanged method

Vue updates data asynchronously. When data changes, VUE opens a queue and buffers all data changes that occur in the same event loop. If the same watcher is triggered more than once, it will only be pushed into the queue once.

Ios Compatibility Issues

Troubleshooting and verification problems:

When setting the scroll-y to allow vertical scrolling, the layout will be changed on ios models, and a new layout area will be formed. Position: Fixed is only relative to the scroll-view area

Set two divs to verify, div1 and div2 to fixed position, width 100vw

  • Div1,height: 44px, background blue

  • Div2, height: 100vh, background red

① Scroll view set height, div1 outside, div2 inside

<template> <view class="wrapper"> <! < p style="position: fixed; width: 100vw; height: 44px; z-index: 1; background: blue;" ></view> <scroll-view style="height: 500px" :scroll-y="true"> <! < p style="position: fixed; width: 100vw; height: 100vh; z-index: 1; background: red;" ></view> </scroll-view> </view> </template>Copy the code

② Scroll view variable height, div1 inside, div2 inside

<template> <view class="wrapper"> <! < p style="position: fixed; width: 100vw; height: 44px; z-index: 1; background: blue;" ></view> <scroll-view :scroll-y="true"> <! < p style="position: fixed; width: 100vw; height: 100vh; z-index: 1; background: red;" ></view> </scroll-view> </view> </template>Copy the code

③ Scroll view set height, div1, div2 inside. Div1 before dvi2

<template> <view class="wrapper"> <scroll-view style="height: 500px" :scroll-y="true"> <! < p style="position: fixed; width: 100vw; height: 44px; z-index: 1; background: blue;" ></view> <! < p style="position: fixed; width: 100vw; height: 100vh; z-index: 1; background: red;" ></view> </scroll-view> </view> </template>Copy the code

④ Scroll view height, div1, div2 are both inside. Div1 after dvi2

<template> <view class="wrapper"> <scroll-view style="height: 500px" :scroll-y="true"> <! < p style="position: fixed; width: 100vw; height: 100vh; z-index: 1; background: red;" ></view> <! < p style="position: fixed; width: 100vw; height: 44px; z-index: 1; background: blue;" ></view> </scroll-view> </view> </template>Copy the code

Conclusion: There is compatibility problem in Scrollview, which is not caused by layout code

Inaccurate anchor points

Element.getBoundingClientRect()

Element. GetBoundingClientRect () method returns the Element size and its position relative to the viewport.

Js onscroll, scrollTop, scrollHeight

  • Onscroll: Event triggered when the element’s scroll bar scrolls
  • ScrollTop: The height of the top hidden part inside the element’s scroll bar
  • ScrollHeight: The height of the content inside the element’s scroll bar

Anchor point calculation formula: y = elrect. top-mainrect. top + scrollTop

1. Set the height of layout elements

2. Layout setting the padding height

① Margin will lead to content collapse and inaccurate calculation of anchor points

② Layout wrap set padding

A better way

Uni-app Node information

// Link to the id location
// @param{\*}inside target element
// @param{_}outside Scroll elements
exportconstlinkToId = (inside, outside) = > {
  uni
    .createSelectorQuery()
    .select(`${inside}`)
    .boundingClientRect((data) = > {
      uni
        .createSelectorQuery()
        .select(`${outside}`)
        .boundingClientRect((res) = > {
          uni.pageScrollTo({
            duration: 99.// Transition time
            scrollTop: data.top - res.top,
          });
        })
        .exec();
    })
    .exec();
};
Copy the code

Advantages: Good compatibility, easy to use, Android, ios, H5 test without compatibility problems