uniapp project actual news app

typora-copy-images-to: images
typora-root-url: ./

Project practice news

Alibaba cloud service space name: moocnews200909

Chapter 5 set sail, victory is waving to you (homepage function module)

Initialization item. 5-1 mp4

Initialize cloud database

Use db_init.json initializes the project database

Mode of use

  • Right click in the cloudfuctions directory to create db_init.json,
  • Write the json content in dB_ init. Right click on json to initialize the database.

Reference style

{
    "collection_test": { // Set (table name)
        "data": [ // data
           {
                "_id": "da51bd8c5e37ac14099ea43a2505a1a5",
               "name": "tom"
           }
        ],
        "index": [{ // Indexes
            "IndexName": "index_a", // Index name
            "MgoKeySchema": { // Index rule
                "MgoIndexKeys": [{
                    "Name": "index", // Index field
                    "Direction": "1" // Index direction, 1: ASC ascending, - 1: DESC descending, 2dsphere: geographic location
                }],
                "MgoIsUnique": false // Is the index unique
            }
        }]
    }
}

Make tabbar

Create 3 page files

Configure pages JSON (the tab content editor at the bottom will automatically prompt)

{
	"pages": [ //The first item in the pages array represents the application startup page. Refer to: https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/tabbar/index/index",
			"style": {
				"navigationStyle": "custom",
				"navigationBarTextStyle": "white",
				"navigationBarTitleText": "uni-app"
			}
		}, {
			"path": "pages/tabbar/follow/follow",
			"style": {}
		}, {
			"path": "pages/tabbar/my/my",
			"style": {}
		}, {
			"path": "pages/home-search/home-search",
			"style": {
				"navigationStyle": "custom"
			}
		}, {
			"path": "pages/home-label/home-label",
			"style": {
				"navigationBarTitleText": "Label management"
			}
		}, {
			"path": "pages/home-detail/home-detail",
			"style": {}
		}
	    ,{
            "path" : "pages/detail-comments/detail-comments",
            "style" : {}
        }
    ],
	"globalStyle": {
		"navigationBarTextStyle": "black",
		"navigationBarTitleText": "uni-app",
		"navigationBarBackgroundColor": "#F8F8F8",
		"backgroundColor": "#F8F8F8"
	},
	"tabBar": {
		"color": "#666",
		"selectedColor": "#f07373",
		"backgroundColor": "#fff",
		"list": [{
			"pagePath": "pages/tabbar/index/index",
			"iconPath": "static/home.png",
			"selectedIconPath": "static/home-active.png",
			"text": "home page"
		}, {
			"pagePath": "pages/tabbar/follow/follow",
			"iconPath": "static/follow.png",
			"selectedIconPath": "static/follow-active.png",
			"text": "follow"
		}, {
			"pagePath": "pages/tabbar/my/my",
			"iconPath": "static/my.png",
			"selectedIconPath": "static/my-active.png",
			"text": "my"
		}]
	}
}

5-2 customize the navigation bar mp4

Home page results:

Part 3:

  • navigation bar
  • tab
  • Card list

Make search box

1. Remove the default navigation bar for customization

"style": {
    "navigationStyle": "custom",/* Customize navigation bar */
    "navigationBarTextStyle": "white",/* Navigation bar foreground color */
    "navigationBarTitleText": "uni-app"/* Navigation bar text message */
}

2. Customize the navigation bar through custom components

​ Create component navbar vue

​ Reference registration in the page

​ Page access method: http://localhost:8080/#/pages/tabbar/index/index

​ Method of introducing components into easyCom

When the directory is consistent with the component name, you don't need to import it. You can use the component directly (you don't need to import it)

​ Use this method for local introduction

​ Enter in the page:

	<!-- Customize navigation bar -->
	<navbar></navbar>

Navigation bar implementation

Add public variables for styles

/* Color variable */
@mk-base-color : #f07373;

navbar.vue

<template>
    <view class="navbar">
            <view class="navbar-fixed">
                <view class="navbar-content">
                    <view class="navbar-search">
                        <!-- Non search page display -->
                        <view class="navbar-search_icon">
                            <uni-icons type="search" size="16" color="#999"></uni-icons>
                        </view>
                        <view class="navbar-serach">
                            <!-- Search page display  -->
                            <input class="navbar-search_text" type="text" v-model="val" placeholder="Please enter the content you want to search"  />
                        </view>
                    </view>
                </view>
            </view>
    </view>
</template>

<script>
    export default {
        name: 'navbar',
        data() {
            return {
                val: ''
            };
        }
    }
</script>

<style lang="less">
    @import '../../common/css/icons.css';
    @import './../../uni.less';

    .navbar {
        .navbar-fixed {
            position: fixed;
            top: 0;
            left: 0;
            z-index: 99;
            width: 100%;
            background-color: @mk-base-color;
            
            .navbar-content {
                display: flex;
                justify-content: center;
                align-items: center;
                padding: 0 15px;
                height: 45px;
                box-sizing: border-box;
                .navbar-search {
                    display: flex;
                    align-items: center;
                    padding: 0 10px;
                    width: 100%;
                    height: 30px;
                    border-radius: 30px;
                    background-color: #fff;

                    .navbar-search_icon {
                        // width: 10px;
                        // height: 10px;
                        margin-right: 10px;
                    }

                    .navbar-search_text {
                        width: 100%;
                        font-size: 14px;
                        color: #999;
                    }
                }

                &.search {
                    padding-left: 0;

                    .navbar-content__search-icons {
                        margin-left: 10px;
                        margin-right: 10px;
                    }

                    .navbar-search {
                        border-radius: 5px;
                    }
                }
            }

        }

    }
</style>

uni. As a public style color value, SCSS can be used directly in the component (I change it to less)

Operation results

5-3 navigation bar adaptation applet

There is no status bar in H5, and there is a status bar in the applet

The port needs to be opened when the wechat applet test runs

Error prompt, operation mode

1. Error reporting

1. The service port of the tool is closed.

To use the command line to call the tool, enter y below to confirm startup, or manually open the tool - > Settings - > security settings to open the service port.

2. Solve the problem that the project page of wechat applet opened by wechat developer tool cannot be displayed

1. Use the command line to install the dependent npm i

2. Enter the wechat developer tool, click the tool, select build npm, and refresh the page

2. Display problem: the status bar at the top of the applet is blocked, and the capsule on the right covers the search box

Treatment method:

1. Set the height of status bar, navigation bar and window width

        data() {
            return {
                statusBarHeight: 20,/* Status bar height */
                navBarHeight: 45,/* Navigation bar height */
                windowWidth: 375,/* Window width */
                /* Set the default height of the status bar */
                val: ''/* Value of the navigation bar search box */
            };
        },

2. Call the api according to the device and calculate the corresponding height and position

Conditional compilation using uniapp

#ifdef: if defined compiles only on a certain platform
#ifndef: if not defined is compiled in addition to the platform
#endif: end if end conditional compilation
%PLATFORM%     The platform that needs to be compiled, the above MP Is the meaning of each applet
        created() {
            // Get mobile system information
            const info = uni.getSystemInfoSync()
            // Set the height of the status bar (there is no status bar at the top of H5, and the applet needs to support the height of the status bar)
            this.statusBarHeight = info.statusBarHeight
            this.windowWidth = info.windowWidth
            // Except H5 app MP Alipay
            // #ifndef H5 || APP-PLUS || MP-ALIPAY
            // Get the location of the capsule
            const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
            console.log(menuButtonInfo);
            // (height of capsule bottom - height of status bar) + (height of capsule top - height of status bar) = height of navigation bar
            this.navBarHeight = (menuButtonInfo.bottom - info.statusBarHeight) + (menuButtonInfo.top - info.statusBarHeight)
            this.windowWidth = menuButtonInfo.left
            // #endif
        }

3. Assign a value to the corresponding dom element

<template>
    <view class="navbar">
        <view class="navbar-fixed">
            <!-- Status bar applet support height -->
            <view :style="{height:statusBarHeight+'px'}"></view>
            <view class="navbar-content" :style="{height:navBarHeight+'px',width:windowWidth+'px'}">
                <view class="navbar-search">
                    <view class="navbar-search_icon">
                        <uni-icons type="search" size="16" color="#999"></uni-icons>
                    </view>
                    <view class="navbar-serach">
                        <input class="navbar-search_text" type="text" v-model="val" placeholder="Please enter the content you want to search" />
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>

Change the color of the status bar from black to white: foreground color root directory: pages json

"navigationBarTextStyle": "white",/* Navigation bar foreground color */

Operation results

5-4 use font icons mp4

1. Use iconfont Ali Icon Library

1. Get Font Icon path in iconfont

2. Download the corresponding css file to common / css / icons css file

3. Introduce into css

    @import '../../common/css/icons.css';

4. Use in the page

<text class="iconfont icon-search"></text>

2. Use icon in plug-in Market

1. Installation of plug-ins

Website: 1 address

Display the uni icons folder under the components folder

2. Use of plug-ins

<view class="navbar-search_icon">
    <uni-icons type="search" size="16" color="#999"></uni-icons>
</view>

website: https://ext.dcloud.net.cn/plugin?id=28

Mode of use

Reference components in script (existing projects don't need to be introduced, just install plug-ins)

import uniIcons from "@/components/uni-icons/uni-icons.vue"
export default {
    components: {uniIcons}
}

Using components in template

<uni-icons type="contact" size="30"></uni-icons>
Attribute description
Attribute name type Default value explain
size Number 24 Icon size
type String - Icon pattern, refer to example
color String - Icon color
Event description
Event name explain Return value
@click Click Icon to trigger the event -

5-5 tab display

1. Create tab component

2. Page horizontal scrolling component writing

<scroll-view class="tab-scroll" scroll-x="true" >
    <view class="tab-scroll__box">
        <view v-for="item in 10" class="tab-scroll__item">
            {{item}}content
        </view>
    </view>
</scroll-view>

3. Add placeholder support height to the top navigation bar component

Note: you need to add placeholder height, status bar height + navigation bar height (otherwise the following tab will collapse)

navbar.vue file

        <!-- Need to add placeholder height status bar height+Navigation bar height (otherwise below) tab Will collapse)-->
        <view :style="{height: statusBarHeight+navBarHeight+'px'}"></view>

Line display settings in style Tab scroll maximum width

        .tab-scroll {
            max-width: calc(100vw - 45px);
		}

tab.vue complete code

<template>
    <view class="tab">
        <scroll-view class="tab-scroll" scroll-x>
            <view class="tab-scroll__box">
                <view v-for="item in 10" class="tab-scroll__item">
                    {{item}}content
                </view>
            </view>
        </scroll-view>
        <view class="tab-icons" @click="open">
            <uni-icons type="gear" size="26" color="#666"></uni-icons>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {

            };
        }
    }
</script>

<style lang="less">
    @import '../../common/css/icons.css';
    @import './../../uni.less';

    .tab {
        display: flex;
        width: 100%;
        border-bottom: 1px #f5f5f5 solid;
        background-color: #fff;
        box-sizing: border-box;

        .tab-scroll {
            flex: 1;
            overflow: hidden;
            box-sizing: border-box;
            max-width: calc(100vw - 45px);
            
            .tab-scroll__box {
                display: flex;
                align-items: center;
                flex-wrap: nowrap;
                height: 45px;
                box-sizing: border-box;

                .tab-scroll__item {
                    flex-shrink: 0;
                    padding: 0 10px;
                    color: #333;
                    font-size: 14px;

                    &.active {
                        color: @mk-base-color;
                    }
                }
            }

            .tab-scroll__box {
                display: flex;
                align-items: center;
                flex-wrap: nowrap;
                height: 45px;
                box-sizing: border-box;

                .tab-scroll__item {
                    flex-shrink: 0;
                    padding: 0 10px;
                    color: #333;
                    font-size: 14px;
                }
            }
        }

        .tab-icons {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
            width: 45px;

            &::after {
                content: '';
                position: absolute;
                top: 12px;
                bottom: 12px;
                left: 0;
                width: 1px;
                background-color: #ddd;
            }
        }
    }
</style>

5-6 tab data initialization

All datasheet files are located in the folder of the project root directory

1. Create cloud function get_label

2. Create corresponding cloud database data table

Just import the files in the folder

3. Cloud function get_label write return classification data

'use strict';
// Get a reference to the database
const db = uniCloud.database()
exports.main = async (event, context) => {
	// Get the data of label table
	let label = await db.collection('label').get()

	//Return data to client
	return {
		code: 200,
		msg: 'Data request succeeded',
		data: label.data
	}
};

4. Method calling interface in the page

website: Client calls cloud function

getLabel() {
    // Client calls cloud function method
    const data = uniCloud.callFunction({
        name:"get_label",
        success(res){
            console.log(res)
        },
        fail(err){console.log(err)},
        complete(){}
    })
}

5. Component value transmission

index. Within Vue

<tab :list="tabList"></tab>
	export default {
		data() {
			return {
				tablist:[]
			}
		},
		methods: {
			
		},
        onLoad() {
            console.log('dasasdasd')
             this.getLabel();
             console.log(this.tablist)
        },
        methods: {
            getLabel() {
                const _this = this;
                // Client calls cloud function method
                const data = uniCloud.callFunction({
                    name:"get_label",
                    success(res){
                        _this.tablist = res.result.data;
                    },
                    fail(err){console.log(err)},
                    complete(){}
                })
            }
        }
	}

Supplement: client calls cloud function method 2

            getLabel() {
                const _this = this;
                // Client calls cloud function method
                const data = uniCloud.callFunction({
                    name:"get_label",
                }).then((res)=>{
                    console.log(res)
                    _this.tablist = res.result.data;
                }).catch((err)=>{
                    console.log(err)
                })
            }

Component internal writing

        <scroll-view class="tab-scroll" scroll-x>
            <view class="tab-scroll__box">
                <view v-for="(item, index) in list" :key="index" class="tab-scroll__item" >
                    {{item.name}}
                </view>
            </view>
        </scroll-view>
props: {
    list: {
        type: Array
    }
},

5-7 encapsulation data request

Purpose: only focus on the successful return, and handle the failed return uniformly

In common - API - index js

Encapsulated results

this.$api.get_label().then((res) => {
})

step

|-common
|	|-api	api Interface call
|	|-css	Public style
|-http.js	Encapsulate network requests

1.promise method encapsulates unicloud Callfunction cloud function request method

HTTP in the common directory js

const get_label = (data)=> {	
    return new Promise((reslove, reject) => {
		uniCloud.callFunction({
			name: url,
			data: dataObj
		}).then((res) => {
			if (res.result.code === 200) {
				// .then
				reslove(res.result)
			} else {
				// catch
				reject(res.result)
			}
		}).catch((err) => {
			reject(err)
		})
	})
}
export default {
    get_label
}

Create a list in the api directory JS (test method feasibility)

/* The list of all cloud function interfaces is written here */
export const get_list = (data)=>{
    return new Promise((reslove, reject) => {
        reslove({'data':'Request succeeded'})
	})
}

Bind to the main. Directory of the root directory JS

import api from './common/api'
Vue.prototype.$api = api /*Bind to vue instance*/

2. Test method rewriting

index. Call override in Vue

Test method get_list

                this.$api.get_list().then((res)=>{
                    console.log(res)
                })

this.$api.get_label({
    name:"get_label"
}).then((res) => {
    const {
        data
    } = res
    console.log('label ',data);
    this.tabList = data
    // 	console.log(this.tabList);
})

3. Create http JS as a method call (create an HTTP interface method)

Purpose: to propose Promise in return as a public part

export default function $http(options){
    const {url,data} = options;
    return new Promise((reslove, reject) => {
		uniCloud.callFunction({
			name: url,/* Cloud function name */
			data: data/* Transmitted data */
		}).then((res) => {

			if (res.result.code === 200) {
				// .then
				reslove(res.result)
			} else {
				// catch
				reject(res.result)
			}

		}).catch((err) => {
			reject(err)
		})
	})
}

4. Modify the original list js

Method: introduce http JS transforms the original return value method

import $http from './../http.js'
export const get_label = (data)=> {	
    return $http({
        url:'get_label',
        data
    })
}

/* The list of all cloud function interfaces is written here */
export const get_list = (data)=>{
    return new Promise((reslove, reject) => {
        reslove({'data':'Request succeeded'})
	})
}

5. Encapsulate cloud function requests uniformly and call them uniformly in the list

Later, if there are multiple cloud functions, you only need to write multiple method functions repeatedly

import $http from './../http.js'
export const get_label = (data)=> {	
    return $http({
        url:'get_label',
        data
    })
}


6. Because there are multiple cloud functions, you need to export and reference in batch, and you need to rewrite the index JS file

Originally, only one cloud function could be exported (now you need to import and export all functions regardless of the name)

//Original===============
// import {get_label,get_list} from './list.js'

// export default{
//     get_label,
//     get_list
// }
//Modified================
// Batch export file
const requireApi = require.context(
	// Relative path of api directory
	'.',
	// Query subdirectories
	false,
	// A suffix of the query file
	/.js$/
)

let module = {}
requireApi.keys().forEach((key,index)=>{
    //Because index is the output directory, it needs to be excluded
	if(key === './index.js') return
	console.log(key);
    //Object merging
	Object.assign(module,requireApi(key))
})
console.log(module)
export default module

Get the format to be exported

final result

7. Create a list in the api JS

http.js

export default function $http(options) {
	const {
		url,
		data
	} = options
	const dataObj = {
		user_id: '5e76254858d922004d6c9cdc',
		...data
	}
	return new Promise((reslove, reject) => {
		uniCloud.callFunction({
			name: url,
			data: dataObj
		}).then((res) => {

			if (res.result.code === 200) {
				// .then
				reslove(res.result)
			} else {
				// catch
				reject(res.result)
			}

		}).catch((err) => {
			reject(err)
		})
	})
}

list.js

import $http from '../http.js'

export const get_label = (data) => {
	return $http({
		url: 'get_label',
		data
	})
}

export const get_list = (data) => {
	return $http({
		url: 'get_list',
		data
	})
}

export const update_like = (data) => {
	return $http({
		url: 'update_like',
		data
	})
}
export const get_search = (data) => {
	return $http({
		url: 'get_search',
		data
	})
}

export const update_label = (data) => {
	return $http({
		url: 'update_label',
		data
	})
}

export const get_detail = (data) => {
	return $http({
		url: "get_detail",
		data
	})
}

export const update_comment = (data) => {
	return $http({
		url: "update_comment",
		data
	})
}
export const get_comments = (data) => {
	return $http({
		url: 'get_comments',
		data
	})
}

export const update_author = (data) =>{
	return $http({
		url: 'update_author',
		data
	})
}

export const update_thumbsup =  (data) =>{
	return $http({
		url: 'update_thumbsup',
		data
	}) 
}

index.js

// Batch export file
const requireApi = require.context(
	// Relative path of api directory
	'.',
	// Query subdirectories
	false,
	// A suffix of the query file
	/.js$/
)

let module = {}
requireApi.keys().forEach((key,index)=>{
	if(key === './index.js') return
	console.log(key);
	Object.assign(module,requireApi(key))
})

export default module

Method call

				this.$api.get_label({
                        name:"get_label"
                    }).then((res) => {
					const {
						data
					} = res
					console.log('label ',data);
					data.unshift({
						name:'whole'
					})
					this.tabList = data
					// 	console.log(this.tabList);
				})

5-8 tab toggle highlight

​ Steps:

1. Bind click event registration

tab.vue

<scroll-view class="tab-scroll" scroll-x>
    <view class="tab-scroll__box">
        <view v-for="(item, index) in list" :key="index" class="tab-scroll__item" 
              @click="clickTab(item, index)">{{item.name}}</view>
    </view>
</scroll-view>

Event binding:

clickTab(item, index) {
    console.log(item,index);
    this.activeIndex = index
    this.$emit('tab', {
        data: item,
        index: index
    })
},

2. Obtain the name value and index value of the clicked object

Declare by dynamically binding classes

<view class="tab-scroll__box">
<view v-for="(item, index) in list" :key="index" class="tab-scroll__item" :class="{active:activeIndex === index}"
@click="clickTab(item, index)">{{item.name}}</view>
</view>
.tab-scroll__item {
    flex-shrink: 0;
    padding: 0 10px;
    color: #333;
    font-size: 14px;

    &.active {
        color: $mk-base-color;
    }
}

3. Pass the event to the parent page

			clickTab(item, index) {
				console.log(item,index);
				this.activeIndex = index
				this.$emit('tab', {
					data: item,/* Click content */
					index: index/* Index of clicks */
				})
			},

4. Accept events in the tab component on the home page

@tab="tab"

<tab :list="tabList" :tabIndex="tabIndex"  @tab="tab"></tab>

Registration event:

		tab({data,index}){
			console.log(data,index);
			this.activeIndex = index
		},

List item component

<template>
	<list-scroll class="list-scroll" @loadmore="loadmore">
		<list-card mode="base" :item="item" v-for="item in list" :key="item._id"></list-card>
		<uni-load-more v-if="list.length === 0 || list.length > 7" iconType="snow" :status="load.loading"></uni-load-more>
	</list-scroll>
</template>

<script>
	export default {
		props: {
			list: {
				type: Array,
				default () {
					return []
				}
			},
			load: {
				type: Object,
				default () {
					return {
						loading: "loading"
					}
				}
			}
		},
		methods: {
			loadmore() {
				this.$emit('loadmore')
			}
		}
	}
</script>

<style>
	.list-scroll {
		height: 100%;
	}
</style>

5-9 basic card view implementation

1. Fix the top tab bar at the top without sliding with the page

Processing method: place the scrolling content area in the scroll View tab

	<view class="home">
		<navbar></navbar>
        <tab :list="tabList" @tab="tab"></tab>
        <view class="scroll">
            <scroll-view scroll-y="true" class="list-scroll" >
                <view>
                    <view v-for="item in 100">
                        {{item}}Content of
                    </view>
                </view>
            </scroll-view>
        </view>

	</view>

Through flex vertical layout, the remaining content is highly supported on the screen

	page {
		height: 100%;
		display: flex;
	}
	.home  {
		display: flex;
		flex-direction: column;
		flex: 1;
		overflow: hidden;
            
        .scroll{
            flex: 1;
            overflow: hidden;
            box-sizing: border-box;
            .list-scroll{
                height: 100%;
                display: flex;
                flex-direction: column;
            }
        }
		.home-list {
			flex:1;
			box-sizing: border-box;
		}
	}

2. Place the content in the list scroll component

​ Create a list scroll component

​ Function: as a component of rolling area

<template>
	<view class="scroll">
		<scroll-view scroll-y="true" class="list-scroll" >
		    <view>
                <slot></slot>
		    </view>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		methods: {
			
		}
	}
</script>

<style  lang="less">
	.scroll {
		flex: 1;
		overflow: hidden;
		box-sizing: border-box;
		.list-scroll {
			height: 100%;
			display: flex;
			flex-direction: column;
		}
	}
</style>

3. Create component list card circular list

<template>
	<view class="home">
		<navbar></navbar>
        <tab :list="tabList" @tab="tab"></tab>
        <list-scroll>
            <list-card v-for="(item,i) in 10"></list-card>
        </list-scroll>
	</view>
</template>

4. Build card component list card basic card

Basic component construction

<template>
	<view>
        <!-- Basic card-->
		<view class="listcard">
            <view class="listcard-image">
                <!-- aspectFill Represents fully filled picture content-->
                <image src="../../static/logo.png" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>Article title</text>
                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">Article description</view>
                    </view>
                    <view class="listcard-content__des-browse">Page views</view>
                </view>
            </view>
        </view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
			};
		}
	}
</script>

5-10 more card view implementations

1. Add multi map mode and large map mode to list card

<template>
	<view>
        <!-- Basic card-->
		<view class="listcard">
            <view class="listcard-image">
                <!-- aspectFill Represents fully filled picture content-->
                <image src="../../static/logo.png" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>Article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title article title</text>
                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">Article description</view>
                    </view>
                    <view class="listcard-content__des-browse">Page views</view>
                </view>
            </view>
        </view>
        		<!-- Multi graph mode -->
        		<view  class="listcard mode-column">
        			<view class="listcard-content">
        				<view class="listcard-content__title">
        					<text>Article title</text>
        				</view>
        				<view class="listcard-image">
                            <view v-for="item in 3" :key="index" class="listcard-image__item">
                                <image src="../../static/logo.png" mode="aspectFill"></image>
                            </view>
        					
        				</view>
        				<view class="listcard-content__des">
        					<view class="listcard-content__des-label">
        						<view class="listcard-content__des-label-item">Article description</view>
        					</view>
        					<view class="listcard-content__des-browse">browse</view>
        				</view>
        			</view>
        		</view>
        		<!-- Large picture mode -->
        		<view  class="listcard mode-image">
        			<view class="listcard-image">
        				<image src="../../static/logo.png" mode="aspectFill"></image>
        			</view>
        			<view class="listcard-content">
        				<view class="listcard-content__title">
        					<text>Article title</text>
        				</view>
        
        				<view class="listcard-content__des">
        					<view class="listcard-content__des-label">
        						<view class="listcard-content__des-label-item">Article description</view>
        					</view>
        					<view class="listcard-content__des-browse">browse</view>
        				</view>
        			</view>
        		</view>
	</view>
</template>

2. List card add props to render different views

Add the parameters accepted by the parent-child props,

Basic card: v-if="item.mode === 'base'"

Multi graph mode: v-if="item.mode === 'column'"

Large image mode: v-if="item.mode === 'image'"

The default is mode=base

<template>
    <view>
        <!-- Basic card-->
        <view v-if="mode==='base'" class="listcard">
            <view class="listcard-image">
                <!-- aspectFill Represents fully filled picture content-->
                <image src="../../static/logo.png" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>Article title article</text>
                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">Article description</view>
                    </view>
                    <view class="listcard-content__des-browse">Page views</view>
                </view>
            </view>
        </view>
        <!-- Multi graph mode -->
        <view v-if="mode==='column'" class="listcard mode-column">
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>Article title</text>
                </view>
                <view class="listcard-image">
                    <view v-for="item in 3" :key="index" class="listcard-image__item">
                        <image src="../../static/logo.png" mode="aspectFill"></image>
                    </view>

                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">Article description</view>
                    </view>
                    <view class="listcard-content__des-browse">browse</view>
                </view>
            </view>
        </view>
        <!-- Large picture mode -->
        <view v-if="mode==='image'" class="listcard mode-image">
            <view class="listcard-image">
                <image src="../../static/logo.png" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>Article title</text>
                </view>

                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">Article description</view>
                    </view>
                    <view class="listcard-content__des-browse">browse</view>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            mode: {
                type: String,
                default: 'base'
            }
        },
        data() {
            return {};
        }
    }
</script>

index.vue calls the corresponding component content

<template>
	<view class="home">
		<navbar></navbar>
        <tab :list="tabList" @tab="tab"></tab>
        <list-scroll>
            <list-card mode="base"></list-card>
            <list-card mode="column"></list-card>
            <list-card mode="image"></list-card>
        </list-scroll>
	</view>
</template>

5-11 realize content switching

1.list component fabrication

Function: used to place the swiper left and right sliding list

list.vue

<template>
		<swiper class="home-swiper">
            <swiper-item class="swiper-item">
                <list-scroll class='list-scroll'>
                    <list-card mode="base"></list-card>
                    <list-card mode="column"></list-card>
                    <list-card mode="image"></list-card>
                </list-scroll>
            </swiper-item>
            <swiper-item class="swiper-item">
                <list-scroll class='list-scroll'>
                    <list-card mode="base"></list-card>
                    <list-card mode="column"></list-card>
                    <list-card mode="image"></list-card>
                </list-scroll>
            </swiper-item>
        </swiper>
</template>

index.vue annotates the original content

	<view class="home">
		<navbar></navbar>
        <tab :list="tabList" @tab="tab"></tab>
<!--       <list-scroll>
            <list-card mode="base"></list-card>
            <list-card mode="column"></list-card>
            <list-card mode="image"></list-card>
        </list-scroll> -->
       <view class="home-list">
            <list></list>
        </view>
	</view>

Slide left and right

2. Make component list item

Create a new list item component in the list component, and bring out the content area list scroll for nesting

list-item.vue

<template>
    <list-scroll class='list-scroll'>
        <list-card mode="base"></list-card>
        <list-card mode="column"></list-card>
        <list-card mode="image"></list-card>
    </list-scroll>
</template>
<script>
</script>
<style lang="less">
    .list-scroll{
        height:100%
    }
</style>

Since the list item does not meet the corresponding specifications, it needs to be introduced separately

list.vue

<template>
		<swiper class="home-swiper">
            <swiper-item class="swiper-item">
                <list-item></list-item>
            </swiper-item>
            <swiper-item class="swiper-item">
                <list-item></list-item>
            </swiper-item>
            <swiper-item class="swiper-item">
                <list-item></list-item>
            </swiper-item>
        </swiper>
</template>
<script>
    /* Manual registration is required because it does not comply with the specification*/
    import listitem from './list-item.vue'
	export default {
        components:{'list-item':listitem}
	}
</script>

result:

3. Pass in the tab in the list to highlight

Start with index In Vue, pass in tablist, and then loop the list tab

index.vue

   <view class="home-list">
        <list :tab = "tabList"></list>
    </view>

list.vue

<template>
		<swiper class="home-swiper">
            <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item">
                <list-item></list-item>
            </swiper-item>
        </swiper>
</template>
<script>
    /* Manual registration is required because it does not comply with the specification*/
    import listitem from './list-item.vue'
	export default {
        components:{'list-item':listitem},
        props:{
            tab:Array,
            default(){
                return [];
            }
        }
	}
</script>

Result: the number of lists corresponds to the number of tabs one by one

5-12 tab and content linkage

1.swiper monitors left and right scrolling and change event monitoring sliding

<template>
		<swiper class="home-swiper" @change="change">
            <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item">
                <list-item></list-item>
            </swiper-item>
        </swiper>
</template>
<script>
    /* Manual registration is required because it does not comply with the specification*/
    import listitem from './list-item.vue'
	export default {
        components:{'list-item':listitem},
        props:{
            tab:Array,
            default(){
                return [];
            }
        },
        methods:{
            change(e){
                console.log(e)
            }
        }
	}
</script>

The current value returned by the method is the current item

activeIndex can control which item is currently returned

Method: pass the current value to activeIndex to realize highlight switching linkage

list.vue

            change(e){
                /* Get current attribute*/
                const {current} = e.detail
                console.log(e)
                /* Pass the current value to the top component of tab to realize highlight switching linkage*/
                this.$emit('change',current)
            }

index.vue

2. Add a change event to listen for changes and pass the value to the tab component to realize highlight switching

<list :tab = "tabList" @change="change"></list>
            /* Receive events from subcomponents*/
            change(current){
                /* Current value of current*/
                   console.log(current)
                   /* Then pass the value to the tab component at the top of the table*/
                   this.tabIndex =current;
            },

The parameter passed is accepted at the tab component reference

<tab :list="tabList" @tab="tab" :tabIndex="tabIndex"></tab>

3. Monitor the change of the value transmitted in props through watch to realize the switching effect

tab.vue component

The original tab component is highlighted through activeIndex control

Accept the value of tabIndex through props

        props: {
            list: {
                type: Array
            },
            /* Toggle highlighted items*/
            tabIndex:{
                  type:Number,
                  default:0
            }
        },

watch monitors props changes

        watch:{
            tabIndex(newVal,oldVal){
                this.activeIndex = newVal
            }
        },

4. When clicking tab, the list at the bottom also switches

Click this after the tab$ Emit passes the value to index, and then passes the value from index to list

The tab$emit method was written before tab

tab.vue

            clickTab(item,index) {
                this.activeIndex = index;
                this.$emit('tab',{
                    data:item,/* Transmitted data */
                    index:index/* Index value passed */
                })
            }

index.vue

In index Declare variable data first in Vue activeIndex:0

The parameters received in tab are passed to activeIndex

            /* Receive component pass value*/
            tab({data,index}){
              console.log(data)   
              console.log(index)   
              this.activeIndex =index;
            }

props component value passing activeIndex

 <list :tab = "tabList" :activeIndex="activeIndex" @change="change"></list>

The current attribute of the swiper is the number of items to jump to

list.vue

proprs receiving parameters

            /* Toggle highlighted items*/
            activeIndex:{
                  type:Number,
                  default:0
            }

The parameter is assigned to the wiper component: current="activeIndex"

	<swiper class="home-swiper" :current="activeIndex"  @change="change">
        <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item">
            <list-item></list-item>
        </swiper-item>
    </swiper>

5-13 content card data initialization

Create cloud function git_list get list information

git_list

'use strict';
// Get a reference to the database
const db = uniCloud.database()
exports.main = async (event, context) => {
    const list = await db.collection('aritcle').get()
    // Return data to client
    return list
};

Filter out the content of the returned result and use the method (field)

Final optimization results

'use strict';
// Get a reference to the database
const db = uniCloud.database()
exports.main = async (event, context) => {
    const list = await db.collection('article')
    .field({
        /* true Indicates that only this field is returned, and false indicates no return*/
        content:false
    })
    .get()
    // Return data to client
    return{
        code:200,
        msg:"Data request succeeded",
        data:list.data
    }
};

Add return in the interface's common/api/list

/* The list of all cloud function interfaces is written here */
export const get_list = (data)=>{

    return $http({
        url:'get_list',
        data
    })
}

In components / list / list Vue calls the corresponding cloud function to obtain data

            /* Pass the required parameters to the cloud classification function*/
            getList(name){
                this.$api.getList().then((res)=>{
                    console.log(res);
                    const {data} = res;
                    this.list = data;
                })
            }

Call list

onload cannot be used in components, only created can be used

        created(){
            /* Initialization call*/
            this.getList()
        },

Complete list vue

<template>
		<swiper class="home-swiper" :current="activeIndex"  @change="change">
            <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item">
                <list-item :list="list"></list-item>
            </swiper-item>
        </swiper>
</template>
<script>
    /* Manual registration is required because it does not comply with the specification*/
    import listitem from './list-item.vue'
	export default {
        components:{'list-item':listitem},
        data:function(){
            return {
                list:[]
            }
        },
        props:{
            tab:Array,
                
            default(){
                return [];
            },
            /* Toggle highlighted items*/
            activeIndex:{
                  type:Number,
                  default:0
            }
        },
        /* onload On the page, the created component*/
            
        created(){
            /* Initialization call*/
            this.getList()
        },
        methods:{
            change(e){
                /* Get current attribute*/
                const {current} = e.detail
                /* Get the corresponding classification name*/
                // console.log(this.tab[current].name)
                /* For each change, the obtained value is passed to getList to realize data change*/
                // this.getList(this.tab[current].name)
                /* Pass the current value to the top component of tab to realize highlight switching linkage*/
                this.$emit('change',current)

            },
            /* To obtain the corresponding information, you need to pass the classification parameters to the cloud function*/
            getList(){
                this.$api.get_list().then((res)=>{
                    console.log(res);
                    const {data} = res;
                    this.list = data;
                })
            }
        }
	}
</script>

<style lang="less">
.home-swiper{
    height: 100%;
    .swiper-item{
        height:100%;
        overflow:hidden;

    }
}
</style>

List item under list In Vue,

First modify the list item Vue realizes circular traversal of content and passes the value: item=item to list card

<template>
    <list-scroll class='list-scroll'>
        <list-card mode="base" :item=item v-for="item in list" :key="item._id">
        </list-card>
    </list-scroll>
</template>

<script>
    export default{
        props:{
            list:{
                type:Array,
                default(){
                    return []
                }
            }
        }
    }
</script>

<style lang="less">
    
    .list-scroll{
        height:100%
    }
</style>

Modify the corresponding list card content, display different content information, and accept the content of item

Accept the object item in props and return an empty object by default

        props: {
            item:{
                type:Object,
                default(){
                    return {}
                }
            }
        },

The original mode can be clear, including the mode in the item

Modify the judgment of the above template as item Mode = = = 'template type'

Modify and fill the corresponding field content

Note: in the multi graph mode, it is necessary to add judgment whether it is less than 3 before rendering V-IF = "index < 3"

list-card.vue complete code

<template>
    <view>
        <!-- Basic card-->
        <view v-if="item.mode==='base'" class="listcard">
            <view class="listcard-image">
                <!-- aspectFill Represents fully filled picture content-->
                <image :src="item.cover[0]" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>{{item.title}}</text>
                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">{{item.classify}}</view>
                    </view>
                    <view class="listcard-content__des-browse">{{item.browse_count}}browse</view>
                </view>
            </view>
        </view>
        <!-- Multi graph mode -->
        <view v-if="item.mode==='column'" class="listcard mode-column">
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>{{item.title}}</text>
                </view>
                <view class="listcard-image">
                    <view v-if="index < 3" v-for="(item,index) in item.cover" :key="index" class="listcard-image__item">
                        <image :src="item" mode="aspectFill"></image>
                    </view>

                </view>
                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">{{item.classify}}</view>
                    </view>
                    <view class="listcard-content__des-browse">{{item.browse_count}}browse</view>
                </view>
            </view>
        </view>
        <!-- Large picture mode -->
        <view v-if="item.mode==='image'" class="listcard mode-image">
            <view class="listcard-image">
                <image :src="item.cover[0]" mode="aspectFill"></image>
            </view>
            <view class="listcard-content">
                <view class="listcard-content__title">
                    <text>{{item.title}}</text>
                </view>

                <view class="listcard-content__des">
                    <view class="listcard-content__des-label">
                        <view class="listcard-content__des-label-item">{{item.classify}}</view>
                    </view>
                    <view class="listcard-content__des-browse">{{item.browse_count}}browse</view>
                </view>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            mode: {
                type: String,
                default: 'base'
            },
            item:{
                type:Object,
                default(){
                    return {}
                }
            }
        },
        data() {
            return {};
        }
    }
</script>

<style lang="less">
    @import './../../uni.less';

    .listcard {
        display: flex;
        padding: 10px;
        margin: 10px;
        border-radius: 5px;
        box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.1);
        box-sizing: border-box;

        .listcard-image {
            flex-shrink: 0;
            width: 60px;
            height: 60px;
            border-radius: 5px;
            overflow: hidden;

            image {
                width: 100%;
                height: 100%;
            }
        }

        .listcard-content {
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding-left: 10px;
            width: 100%;

            .listcard-content__title {
                position: relative;
                padding-right: 30px;
                font-size: 14px;
                color: #333;
                font-weight: 400;
                line-height: 1.2;

                text {
                    overflow: hidden;
                    text-overflow: ellipsis;
                    display: -webkit-box;
                    -webkit-line-clamp: 2;
                    -webkit-box-orient: vertical;
                }

            }

            .listcard-content__des {
                display: flex;
                justify-content: space-between;
                font-size: 12px;

                .listcard-content__des-label {
                    display: flex;

                    .listcard-content__des-label-item {
                        padding: 0 5px;
                        margin-right: 5px;
                        border-radius: 15px;
                        color: @mk-base-color;
                        border: 1px @mk-base-color solid;
                    }
                }

                .listcard-content__des-browse {
                    color: #999;
                    line-height: 1.5;
                }
            }
        }

        &.mode-column {
            .listcard-content {
                width: 100%;
                padding-left: 0;
            }

            .listcard-image {
                display: flex;
                margin-top: 10px;
                width: 100%;
                height: 70px;

                .listcard-image__item {
                    margin-left: 10px;
                    width: 100%;
                    border-radius: 5px;
                    overflow: hidden;

                    &:first-child {
                        margin-left: 0;
                    }

                    image {
                        width: 100%;
                        height: 100%;
                    }
                }
            }

            .listcard-content__des {
                margin-top: 10px;
            }
        }

        &.mode-image {
            flex-direction: column;

            .listcard-image {
                width: 100%;
                height: 100px;
            }

            .listcard-content {
                padding-left: 0;
                margin-top: 10px;

                .listcard-content__des {
                    display: flex;
                    align-items: center;
                    margin-top: 10px;
                }
            }
        }
    }
</style>

5-14 switch tab lazy loading data

Use the interface gitlist to get the real data and render the page

1. Determine the different labels of different contents displayed on the page (make classification)

In components / list / list Get the corresponding classification in Vue

Obtain the corresponding subscript value in the change event, and obtain the corresponding classification according to the subscript value

            change(e){
                /* Get current attribute*/
                const {current} = e.detail
                console.log(this.tab[current])
                /* Pass the current value to the top component of tab to realize highlight switching linkage*/
                this.$emit('change',current)
            }

Use this tab[current]. Name can get the corresponding name value,

2. Pass the corresponding name value to the cloud function to obtain the corresponding classification information

​ Create the method getList in the list and pass the parameter name

            /* To obtain the corresponding information, you need to pass the classification parameters to the cloud function*/
            getList(name){
                this.$api.getList({name}).then((res)=>{
                    console.log(res);
                    const {data} = res;
                    this.list = data;
                })
            }

Call in created when the page is initialized and loaded, and call when the onchange event is switched

        created(){
            /* Initialization call*/
            this.getList('Back end development')
        },
            change(e){
                /* Get current attribute*/
                const {current} = e.detail
                /* Get the corresponding classification name*/
                console.log(this.tab[current].name)
                /* For each change, the obtained value is passed to getList to realize data change*/
                this.getList(this.tab[current].name)
                /* Pass the current value to the top component of tab to realize highlight switching linkage*/
                this.$emit('change',current)

            },

The cloud function obtains event data and performs filtering and aggregation operations

Use aggregation to filter data

Cloud function get_list/index.js

'use strict';
// Get a reference to the database
const db = uniCloud.database()
exports.main = async (event, context) => {
    /* Receive classification to filter data*/
    const {name} = event;
    let matchObj = {}
	if (name !== 'whole') {
		matchObj = {
			classify: name/* The filter field passes the qualified documents to the next pipeline */
		}
	}
    // Aggregation: more refined processing of data summation, grouping and specifying those fields
    const list = await db.collection('article')
    .aggregate()/* Gets the collection of aggregation operations */
    .match(matchObj)/* The filter field passes the qualified documents to the next pipeline */
    .project({
        /* false Indicates no return*/
        content:false
    })
    .end()/* Initiate actual aggregation operation */
    // Return data to client
    return{
        code:200,
        msg:"Data request succeeded",
        data:list.data
    }
};

As the new content will flash when rendered, the caching function is added

Add the cached subscript current in the getList

Add data value listCatchData = {};

        data:function(){
            return {
                list:[],
                /* The state in which the content flashes when processing switching (set cache state)*/
                listCatchData = {};
            }
        },
            /* To obtain the corresponding information, you need to pass the classification parameters to the cloud function*/
            getList(current){
                this.$api.get_list({
                    name:this.tab[current].name
                }).then((res)=>{
                    console.log(res);
                    const {data} = res;
                    this.list = data;
                    /* Assign current to cache*/
                    this.listCatchData[current] = data
                })
            }

The initialized call is filled with

It should be noted that when the content is not rendered, an error will be reported if getList is executed in created

            /* Initialization call*/
            this.getList(this.activeIndex);

Modify to call the method in created in watch

        /* Render only when the tab changes*/
        watch:{
            tab(newVal) {
                if (newVal.length === 0) return;
                  this.listCatchData = {};
                  this.getList(this.activeIndex);
            },
        },
        /* onload On the page, the created component*/
            
        created(){
            /* Initialization call*/
            /* tab There is no assignment*/
            
        },

Modify the rendered part of the template

<list-item :list="listCatchData[index]"></list-item>

The data request is successful, the page is not displayed, and the rendering update needs to be reprocessed and assigned

Use this$ Set to re render the page

Use when data changes

                  // Lazy loading renders data only when the data changes
                  this.$set(this.listCatchData, current, data);

Complete getList method

            /* To obtain the corresponding information, you need to pass the classification parameters to the cloud function*/
            getList(current){
                this.$api.get_list({
                    name:this.tab[current].name
                }).then((res)=>{
                    console.log(res);
                    const {data} = res;
                    console.log('Request data',data);
                    // this.list = data;
                    /* Assign current to cache*/
                    // this.listCatchData[current] = data
                  // Lazy loading renders data only when the data changes
                  this.$set(this.listCatchData, current, data);
                })
            }

list.vue complete code

<template>
		<swiper class="home-swiper" :current="activeIndex"  @change="change">
            <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item">
                <list-item :list="listCatchData[index]"></list-item>
            </swiper-item>
        </swiper>
</template>
<script>
    /* Manual registration is required because it does not comply with the specification*/
    import listitem from './list-item.vue'
	export default {
        components:{'list-item':listitem},
        data:function(){
            return {
                list:[],
                // The state in which the content flashes when processing switching (set cache state)
              // js limit listCatchData[index] = data 
              listCatchData: {},
            }
        },
        props:{
            tab:Array,
                
            default(){
                return [];
            },
            /* Toggle highlighted items*/
            activeIndex:{
                  type:Number,
                  default:0
            }
        },
        /* Render only when the tab changes*/
        watch:{
            tab(newVal) {
                if (newVal.length === 0) return;
                  this.listCatchData = {};
                  this.getList(this.activeIndex);
            },
        },
        /* onload On the page, the created component*/
            
        created(){
            /* Initialization call*/
            /* tab There is no assignment*/
            
        },
        methods:{
            change(e){
                /* Get current attribute*/
                const {current} = e.detail
                /* Get the corresponding classification name*/
                console.log(this.tab[current].name)
                /* For each change, the obtained value is passed to getList to realize data change*/
                this.getList(this.tab[current].name)
                /* Pass the current value to the top component of tab to realize highlight switching linkage*/
                this.$emit('change',current)

            },
            /* To obtain the corresponding information, you need to pass the classification parameters to the cloud function*/
            getList(current){
                this.$api.get_list({
                    name:this.tab[current].name
                }).then((res)=>{
                    console.log(res);
                    const {data} = res;
                    console.log('Request data',data);
                    // this.list = data;
                    /* Assign current to cache*/
                    // this.listCatchData[current] = data
                  // Lazy loading renders data only when the data changes
                  this.$set(this.listCatchData, current, data);
                })
            }
        }
	}
</script>

<style lang="less">
.home-swiper{
    height: 100%;
    .swiper-item{
        height:100%;
        overflow:hidden;

    }
}
</style>

5-15 - 1 pull up load more (up)

https://ext.dcloud.net.cn/plugin?id=29

Load more using component LoadMore

5-16 - 2 pull-up loading more (lower)

5-17 - 1 collection button implementation (Part 1)

5-18 - 2 collection button implementation (Part 2)

Chapter 6 whether things are fast or not depends not on the temporary effort, but on whether they can last (search page function module)

6-1 search page navigation bar modification (2) mp4

6-2 using vuex to manage history (2) mp4

6-3 - 1 implementation of search logic (Part I) (2) mp4

6-4 - 2 implementation of search logic (Part 2) (2) mp4

6-5 search history data persistence (2) mp4

Chapter 7 perseverance, gold and stone can be carved (tab function module)

7-1 label management page layout style mp4

7-2 tab data processing mp4

7-3 edit tab mp4

7-4 save tab data mp4

7-5 synchronize data using custom events mp4

Chapter 8 persistence is victory, and persistence will make achievements (function module on the details page)

8-1 details page display mp4

8-10 comment content realization (5) mp4

8-11 comment content realization (6) mp4

Author's attention (I) mp4

8-13 pay attention to the author (Part 2) mp4

8-14 collection and praise of articles (Part I) mp4

8-15 collection and praise of articles (Part 2) mp4

8-16 comment list (top) mp4

8-17 comment list (below) mp4

8-2 content preloading mp4

8-3 details page data initialization mp4

8-4 rich text rendering mp4

8-5 display of release window mp4

8-6 comment content realization (1) mp4

8-7 comment content realization (2) mp4

8-8 comment content realization (3) mp4

8-9 comment content realization (4) mp4

Chapter 9 focus page function module

9-1 focus page (navigation bar Implementation) mp4

9-2 collection article content realization mp4

9-3 collection is associated with the content of the home page mp4

9-4 focus on the realization of the author's page mp4

9-5 synchronize the author page data mp4

Chapter 10 function module of personal information page

10-1 implementation of personal center page mp4

10-2 personal center data processing) mp4

10-3 my article Implementation) mp4

10-4 problem feedback page (Implementation) mp4

10-5 feedback picture selection mp4

10-6 upload pictures mp4

Chapter 11 a little makes a lot and moves towards perfection (project optimization is compatible with the platform)

11-1 wechat applet optimization and compatibility mp4

11-2 Alipay applet optimization and compatibility mp4

11-3 other platform optimization and compatibility mp4

Chapter 12 final sprint, success is at hand (project release and packaging)

12-1 h5 end distribution and packaging mp4

12-2 release and upload of applet mp4

12-3 App side distribution and packaging mp4

Tags: uniapp

Posted by Ravi Kumar on Sun, 15 May 2022 19:22:39 +0300