demand
In most emporium scenes, the page will have a category switch plus a list of items, and the page will look something like this
Every time I write a similar scenario, I have to write a lot of logic for the category item list, so I decided to separate this part into components to improve the development efficiency.
implementation
Style 1.
All TAB bar styles and item list styles provide slots for business customization
2. The variable
isTabFixed: falseTAB: 1,// Current TAB page: 1,// Current page: 1,//false// Is this the last pagefalse, / /} in the load, the items: [], / / commodity array tabMap: [], / / the TAB list array cache: {}, / / the cache listName:' '// tabName:' '// TAB list name apiName:' '// API method name queryName:' '// API request parameter nameCopy the code
3. Cache design
To reduce overhead, I cache the list of items that have been requested
_addCache(proList) {
cache[this.tab] = {
finished: this.listStatus.finished,
page: this.page,
list: proList,
};
},
Copy the code
4. Request data
_getList(type) {
let data = {};
data[this.queryName] = this.tab;
data.page = this.page;
this.$http[this.apiName](data) .then((res) => { this.listStatus.finished = ! res.has_more; // Update whether the state of the last page is this._handleData(res.items); / / handle to get the list of goods}). The catch ((err) = > {note (err. Message | |'Wrong');
});
},
_handleData(proList) {
if(this. items = proList) {this.items = proList; (this. items = proList; }else{// We need to concatenate the data this.items = this.items. Concat (proList); } this.$store.setData(this.listName, this.items); // Update the data to the parent component this._addCache(this.items); // add data to cache},Copy the code
5. The operating
The logical part is mainly divided into two parts: one is the list page turning, the other is TAB related
A list of pages
The logic of this part is relatively simple, mainly divided into two points
- Add page one
- The request data
_loadmore() {
this.page = this.page + 1;
this._getList();
},
Copy the code
There are a lot of things that need to be noted about the pull-up of the mobile list, such as how to avoid continuous requests, but since I’ve handed them over to another component that focuses on the list rendering, I don’t need to worry about them here.
TAB associated
The TAB to switch
There are two main points in tab-switching
- Toggle TAB pointing
- Toggles the direction of items
- The loaded list is fetched from the cache
- Request data that has not been loaded and then there are two points of experience
- The view should go back to the top
-
- The first page of the toggle list should be retrieved when switching
changeTab(id) {
this.tab = id;
this.$store.setData(this.tabName, this.tab); // synchronize the TAB pointer to the parent component this._scrollTotab (); // View back to topif (cache[this.tab]) {
const target = cache[this.tab];
this.listStatus.finished = target.finished;
this.page = target.page;
this.items = target.list;
this.$store.setData(this.listName, this.items); // Synchronize the item list to the parent component}else{ this.page = 1; this._getList(); }}, // View back to the top_scrollToTab() {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
let productsTop = this.$refs.products.$el.offsetTop; // The distance from the top of the listlet topHeight = this.$refs.tabNav.offsetHeight; // The height of the TAB columnif(scrollTop > productsTop) { window.scrollTo(0, productsTop - topHeight); }},Copy the code
Suck the top
You need to make some small changes to the TAB bar style when you hit the top, so you need a variable to know if you hit the top
handleNavFixed() {
this.stickyTop = this.$store.getData('stickyTop') | | 0; Onscroll = (e) => {let top = document.documentElement.scrollTop || document.body.scrollTop;
let tabHeight = this.$refs.tabNav.offsetTop - top - 1;
if(tabHeight <= this.stickyTop && ! This.istabfixed) {// to avoid double counting this.istabfixed =true;
}
if (tabHeight >= this.stickyTop && this.isTabFixed) {
this.isTabFixed = false; }}; },Copy the code
6. Component correlation
As a component, the difference is that it needs to be usable and universal. How the component can get the value of the parent component and send the updated value back to the parent component is a bottleneck in my development process. Finally, I used a set of component pass-through mechanism based on VUE. The implementation of this kind of traffic mechanism on the net is many, here is not detailed. The traffic mechanism has two main functions
- Components can call methods to each other
- Each component can get and update the parent component’s data
Since the TAB list is passed in as a slot, you don’t need to care about the initial data, just the update data.
For different pages, the name of the TAB list, the name of the TAB location, the name of the item list, the name of the interface, and the parameters of the request interface can all be different, so I’m going to pass these items in here as parameters to initialize the component
Init (data = {}) {this.listStatus.finished =! data.hasMore; this.tabName = data.tabName; this.listName = data.listName; this.apiName = data.apiName; this.queryName = data.queryName; this.handleNavFixed(); }, // call component this.$bus.emit('tab-list.init', {
tabName: 'tab',
listName: 'items',
apiName: 'homeList',
queryName: 'tab_id',
hasMore: this.hasMore,
});
Copy the code
The effect
This page toggles the list of items using this component