Notes on the actual combat of uniapp project

catalog

Project source address: https://github.com/whynot-todo/uniapp_demo.git

1 project construction

1.1 new project and operation

To build the project, Details click

  • The name we created here is uniapp_demo
  • Run. Here we can see the above details and click it. Pay attention to the path configuration during the initial run
  • When we run it, we close the interface like this

1.2 configure basic appearance according to project effect

  1. open pages.json Under global style, you can configure the global style by referring to the official website, Details click
"globalStyle": {
        "navigationBarTextStyle": "white",
        "navigationBarTitleText": "Shopping Mall",
        "navigationBarBackgroundColor": "##b50e03",
        "backgroundColor": "#F8F8F8"
}

This is what it looks like after configuration. Because the priority of local configuration is higher, the navigationBar displays the uniapp

2. Frame up

2.1 configure tabbar

1. Create a new page

According to the renderings, tabber is connected with four pages: homepage, consultation, shopping cart and membership. Our new four pages are

  1. pages/index/index
  2. pages/cart/cart
  3. pages/member/member
  4. pages/news/news

2. New page steps

  1. Right click under pages folder and select new page
  2. Then configure the page a little

    It should be noted that
  • Select a template. Here is less
  • Yes no pages.json We need all four of them
  1. Follow the above steps to create four new files

3. Configure tabber
About the configuration of tabbar, Details click

	"tabBar": {
		"selectedColor": "#b50e03",
		"color": "#ccc",
		"list": [{
				"text": "home page",
				"pagePath": "pages/index/index",
				"iconPath": "static/icon/home.png",
				"selectedIconPath": "static/icon/home-active.png"
			},
			{
				"text": "real-time info",
				"pagePath": "pages/news/news",
				"iconPath": "static/icon/news.png",
				"selectedIconPath": "static/icon/news-active.png"
			},
			{
				"text": "Shopping Cart",
				"pagePath": "pages/cart/cart",
				"iconPath": "static/icon/cart.png",
				"selectedIconPath": "static/icon/cart-active.png"
			},
			{
				"text": "member",
				"pagePath": "pages/member/member",
				"iconPath": "static/icon/member.png",
				"selectedIconPath": "static/icon/member-active.png"
			}
		]
	}

It should be noted that

  • The first element of the pages array represents the default page at startup
  • Path writing

When we have configured the above, the following effect will appear, indicating that the configuration is successful

3 get data from the background

3.1 package request component

  1. Let's create a new utils folder in the root directory and create a new one api.js File, write the following code
const BASE_URL = 'http://localhost:8082'
export const myRequest = (options)=>{
	return new Promise((resolve,reject)=>{
		uni.request({
			url:BASE_URL+options.url,
			method: options.method || 'GET',
			data: options.data || {},
			success: (res)=>{
				if(res.data.status !== 0) {
					return uni.showToast({
						title: 'Failed to get data'
					})
				}
				resolve(res)
			},
			fail: (err)=>{
				uni.showToast({
					title: 'Request interface failed'
				})
				reject(err)
			}
		})
	})
}

Note the following

  • We want to return a promise object
  • The parameter received by the function is a configuration object, which should include three required data in the interface document
{
url,//The requested path,
method,//Request method
data//Parameters required for request
}
  • Handling of success and failure uni.showToast Details click
  • BASE_ The URL is the background interface, uni.request Details click For H5, cross domain processing is required, Details click , we mainly write small programs here, so we won't deal with them.
  1. Add request method to global
    open mian.js =>Introduce component = > Add method to primitive
import {myRequest} from 'utils/api.js'
Vue.prototype.$myRequest = myRequest

3.2 build background application

  1. Download phpStudy and open it. The version used here is 8.1.0.1
  2. Start MYSQL service
  3. Click open, click SQL_Front
  4. Click to open
  5. Right click localhost, select new, select database
  6. Enter the database name (the same as our local sql file), and click OK
  7. Right click our new database, click input, click sql file,
  8. Import the local file, note that the character set is utf-8
  9. After importing, we can close the current page, but we cannot exit phpStudy
  10. Open the server folder and run the command node app.js , running the background project.

4 home page

4.1 configure basic data of home page

navigationBarTitleText

{
	"path": "pages/index/index",
	"style": {
		"navigationBarTitleText": "Homepage of shopping mall"
	}
}

After configuration

4.2 rotation chart

Get the data of the carousel

  • Interface documentation
  • Define methods according to interface documents
data() {
	return {
		swipers: []
},
methods: {
	async getSwipers () {
		const res = await this.$myRequest({
			url: '/api/getlunbo'
		})
		this.swipers = res.data.message
	},
}
  • Call in lifecycle function
onLoad() {
	this.getSwipers()
	/* console.log(this.swipers) No data available */
},
  • Some small partners may print directly in the onLoad function this.swipers Note that you cannot get the corresponding data because it is an asynchronous function

Display the acquired data into the web page

<swiper indicator-dots circular autoplay indicator-color='rgba(249,180,141,.7)'>
	<swiper-item v-for="item in swipers" :key="item.id">
		<image :src="item.img"></image>
	</swiper-item>
</swiper>
  • We also need to give swiper a width and height
swiper{
	width: 750rpx;
	height: 380rpx;
	image{
		height: 100%;
		width: 100%;
	}
}

explain

  • Indicator dots is the indicator dot
  • circular sliding
  • autoplay auto rotation
  • Indicator color origin background color

4.3 navigation in the page

1. Static navigation

  1. Open material / font_nav put the font icon we downloaded into the static/fonts folder. We only need five of them
    • iconfont.woff
    • iconfont.woff2
    • iconfont.ttf
    • svg
    • eot


2. Open material / font_ In nav iconfont.css Files, copying code, putting App.vue Under the file, note that the path to modify the reference starts with ~ @, and the write path cannot be followed by @. When we use it, we can class = "iconcont icon name"

    @font-face {font-family: "iconfont";
      src: url('~@/static/fonts/iconfont.eot?t=1576335469449'); /* IE9 */
      src: url('~@/static/fonts/iconfont.eot?t=1576335469449#iefix') format('embedded-opentype'), /* IE6-IE8 */
      url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAVMAAsAAAAAChwAAAT/AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDKAqHQIYhATYCJAMUCwwABCAFhG0HUBurCFGUTk6f7EeBu6eIlFFajBY208XLlGHx/6/hiYfvx76d+2xFJLlUn75pp4tCoyQ8NgiJUJjuJfzNpSrpXIDoeDbs3GjyH7Lfv+zTy1mok+GyEhYAW8AKaPvz/6eeG1QvDUo6SQW8bE4KYTDSMRj1R/5x7/TP88Dmo7Jc/misYXOelwWYYEBjbGxrAQ7KEvQW8SwuJBO4nkCvRQ21q/PbB5hXQLdAvDU6gHmbRQnhhG598xlb1lEvsu70PvEBfFU/H/+hF1IkNYO+149nMRz+6v7/fwrv4JAqI6T5uXCbRMYWUIhnX8+tKT22ZUrvJ3PaCdCNryR+Sb2RfRPT+c9kbdF0s788siIRDWj6GXkWL/ySEsVkfsmyftoYKiIZsiQfJ+Y2ll7MgdgDiE/AMF+CumLWsCSpdFXpjsNkefoatW8WSY8xapRhreWm1a9vWvVEM6edaQdPapImTzTLLG4BwEBG/HJsK4bVEKkStJbxbUYy3othvO2ofJA7jBARcUZ4illDuEL29TB2C/3AGWj4WUfGYbG25LTICaEk1jWBR8KWC0bqQJ+EjJYmOnvisiHzqtifvZ08X7NYzBaJWAJBglDIRIi3Fd/C3cbZjqEKvkh9Qmx2SKCgMAhD15VHVkCQMCWOP72YnLB0euHUpROzJ/PEYiR6wxK8ShC+ZsryVibGlbIzorOjqRKnhwyOKTIlMRoPSLgMlYvInDIKdwsQ8K2YbO2PReRsyxzZvrK0dWxUYUrIE2sPj8+sHNw6tUVhj0AgslvelUfhDnNG4k0YwgedbyX/ovPRL8SnqwOt/atMII/RGGMacyXGJOaq+MtGYDFMOL1Hk8OSJdfqARNMZkPmnDVh5DP0bjDpx6XAB6RO0JkqM4F0fNSNZMKXB20QqI//n+swdzCvnv1/JszOzMEszPsskD8RZtrarNB14gGhubjWlduokVnWD9e9PyCQd1jtvPjStKTGs6VZFT/xjhhW0hpkG6PoC0wW8iGUrPK9prFY4AM+9GF8APhKfIvr5tct+IoAxU/eE3ILa4yrDxTgUfkrG0lPTtshU4pGtXT9UJqywWkDhzyi/5ka15D+WlPn1Gd+QYF7s0j3dXTuS0oStZLum6on86NOwIbPcydIP3+STiDFaYk1Z6WFLPt7b7M6EhMA+Gr+qtDilfia4mPFr0p8JZUS973QHulzYJxsPjJ6xdeW7Wd75WHHrZsGDXaUb1hacCuQVmrOkt1DjdgTxSeY3EcWDqCzRLxB9PmH2DNplYhzhCDbNLfzY7dKy1jb/dqNFfBTXbWg8vhWsH1JP9IN0VQmIcif4isHay1vtVDzNIiyxeirbpZ0JKEXg3QAAqN+8jFMLN9E6DZhQtJlAbJuS2ght6DqcwRNt1Potelicp8xbEqUHmz4IBCGfUIy6DtkwyZoIb+hmvQLzXAQoddNbM3ZZyWKFk+YAqEYwxGayJZKsMuiVnxH2ucBW+Uq94m4MkHstjrO5AWVxHkMqPq6J6JQsS3wnGxGeW7RsU0pklYi4rbbbeV3plZkC1h0iZGAIDEUGkFGxCopubpYdL3/DtG8XIBDSn4knxBWMbWjrpZODPRCU8YqWZfGlT6tRwjFOynMKqBz6iI5xizk/FulSES0JCkizrY2q6Tialrl64ppLD0VysKcNVLkKFGjae8S40w5K14OB+WS9lKjkR/YgsrZsRnZzAAA') format('woff2'),
      url('~@/static/fonts/iconfont.woff?t=1576335469449') format('woff'),
      url('~@/static/fonts/iconfont.ttf?t=1576335469449') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
      url('~@/static/fonts/iconfont.svg?t=1576335469449#iconfont') format('svg'); /* iOS 4.1- */
    }

    .iconfont {
      font-family: "iconfont" !important;
      font-size: 16px;
      font-style: normal;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
    }

    .icon-shipin:before {
      content: "\f0024";
    }

    .icon-tupian:before {
      content: "\e650";
    }

    .icon-guanyuwomen:before {
      content: "\e608";
    }

    .icon-ziyuan:before {
      content: "\e60d";
    }
  1. We are index.vue Write the following structure in
<view class="nav">
    <view class="item">
        <view class="iconfont icon-ziyuan"></view>
        <text>Supermarket Homepage</text>
    </view>
    <view class="item">
        <view class="iconfont icon-tupian"></view>
        <text>contact us</text>
    </view>
    <view class="item">
        <view class="iconfont icon-guanyuwomen"></view>
        <text>Community picture</text>
    </view>
    <view class="item">
        <view class="iconfont icon-shipin"></view>
        <text>Video Zone</text>
    </view>
</view>
  1. We are uni.scss A theme color is defined in. If less is used, we can create a new global file definition variable
/* Color variable */
$shop-color: #b50e03;
  1. stay index.vue Add CSS style, which uses flex and percentage layout and references global variables
.nav{
  display: flex;
  align-items: center;
  .item{
    width: 25%;
    text-align: center;
    view{
      background: $shop-color;
      line-height: 120rpx;
      width: 120rpx;
      height: 120rpx;
      border-radius: 90px;
      margin:10px auto;
    }
    text{
      font-size: 15px;
    }
  }
  .iconfont{
    font-size: 25px;
    color: #fff;
    height: 50px;
  }
  .icon-tupian{
    font-size: 20px;
  }
}

When we have finished configuring, the following screen will appear


Dynamic page navigation

We will create four new pages for the four navigation buttons, on which there are steps to configure the page to build the framework

  1. /pages/goods/goods
  2. /pages/pics/pics
  3. /pages/contact/contact
  4. /pages/videos/videos

We need to define Click to jump events for four icons. We need to use the uni.navigateTo(OBJECT) Details click

Optimize navigation structure

  1. Because one by one of the binding advantages is troublesome, let's optimize the structure of navigation index.vue In data() {}, add the following configuration data
navs: [
  {
    icons: "iconfont icon-ziyuan",
    title: "Supermarket Homepage",
    path: "/pages/goods/goods"
  },
  {
    icons: "iconfont icon-tupian",
    title: "Community picture",
    path: "/pages/pics/pics"
  },
  {
    icons: "iconfont icon-guanyuwomen",
    title: "contact us",
    path: "/pages/contact/contact"
  },
  {
    icons: "iconfont icon-shipin",
    title: "Learning video",
    path: "/pages/videos/videos"
  }
]
  1. Delete the above repeated structure. We use v-for to traverse the rendering structure and define the click jump method
<view class="nav">
  <view class="item" v-for="(item,index) in navs" :key="index" @click="navItemClick(item.path)">
    <view :class="item.icons"></view>
    <text>{{item.title}}</text>
  </view>
</view>
  1. We define the click method in methods
navItemClick(url) {
	uni.navigateTo({
		url
	})
}
  1. Then we can click jump

4.4 recommended products on the homepage

Single static structure

  1. We write a single static structure according to the renderings
<!-- Pick of the week -->
<view class="hot_goods">
	<view class="tit">Pick of the week</view>
	<!-- Single item-->
	<view class="goods_list">
		<view class="goods_item">
			<image></image>
			<view class="price">
				<text>1299</text>
				<text>12990</text>
			</view>
			<view class="name">Huawei( HUAWEI)Glory 6 Plus 16G Double 4 G edition</view>
		</view>
	</view>
</view>
  1. css Style
.hot_goods {
	background: #eee;

	.tit {
		border-top: 2px solid #eee;
		border-bottom: 2px solid #eee;
		margin-top: 20px;
		margin-bottom: 3px;
		color: $shop-color;
		height: 50px;
		line-height: 50px;
		text-align: center;
		letter-spacing: 20px;
		background: #fff;
	}

	.goods_list {
		display: flex;
		padding: 0 15rpx;
		justify-content: space-between;
		overflow: hidden;
		flex-wrap: wrap;

		.goods_item {
			width: 355rpx;
			margin-bottom: 15rpx;
			background: #fff;
			padding: 10px;
			box-sizing: border-box;

			image {
				height: 150px;
				width: auto;
				mix-width: 160px;
				margin: 10px auto;
			}

			.price {
				font-size: 18px;
				color: red;
				padding: 8px 0;

				text:nth-child(2) {
					color: #ccc;
					text-decoration: line-through;
					margin-left: 10px;
					font-size: 13px;
				}
			}

			.name {
				font-size: 14px;

			}
		}
	}
}

Commodity components

  1. Looking at the renderings, we find that the product card is a repeated structure, and we can draw it into a component
  2. We will create the components / goods list folder in the root directory, and create new goods-list.vue file


3. We copy the corresponding code to goods-list.vue

<template>
	<view>
		<!-- General usage -->
		<view class="goods_list">
			<view class="goods_item">
				<image></image>
				<view class="price">
					<text>1299</text>
					<text>12990</text>
				</view>
				<view class="name">Huawei( HUAWEI)Glory 6 Plus 16G Double 4 G edition</view>
			</view>
		</view>
	</view>
</template>

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

			};
		}
	}
</script>

<style lang="less">
	.goods_list {
		display: flex;
		padding: 0 15rpx;
		justify-content: space-between;
		overflow: hidden;
		flex-wrap: wrap;

		.goods_item {
			width: 355rpx;
			margin-bottom: 15rpx;
			background: #fff;
			padding: 10px;
			box-sizing: border-box;

			image {
				width: 80%;
				height: 150px;
				display: block;
				margin: auto;
			}

			.price {
				font-size: 18px;
				color: red;
				padding: 8px 0;

				text:nth-child(2) {
					color: #ccc;
					text-decoration: line-through;
					margin-left: 10px;
					font-size: 13px;
				}
			}

			.name {
				font-size: 14px;
			}
		}
	}
</style>
  1. stay index.vue Introduce and map to components in
import GoodsList from '../../components/goods-list/goods-list.vue'

components:{
	GoodsList
}
  1. In template
<view class="hot_goods">
	<view class="tit">Pick of the week</view>
	<goods-list></goods-list>
</view>
  1. design sketch

Get dynamic data

  1. stay index.vue,methods

Interface documentation

methods

// Get popular product list data
async getHotGoods () {
	const res = await this.$myRequest({
		url: '/api/getgoods?pageindex=1'
	})
	this.goods = res.data.message
},

data

data(){
	return {
		goods: []
	}
}
  1. In the declare periodic function, send the request
onLoad() {
	this.getHotGoods()
},

Pass data to subcomponent label

  1. transmit
<goods-list :goods="goods"></goods-list>
  1. The subcomponent label receives the data and renders the goods list according to the interface document
export default {
	props:['goods'],
}

template

<view class="goods_list">
	<view class="goods_item" v-for="item in goods" :key="item.id">
		<image :src="item.img_url"></image>
		<view class="price">
			<text>¥{{item.sell_price}}</text>
			<text>¥{{item.market_price}}</text>
		</view>
		<view class="name">{{item.title}}</view>
	</view>
</view>

Effect after configuration

5 detail page of single product

5.1 Click to jump

effect

Let's create a new page called "goods detail"

Bind Click to listen

Bind click monitoring for each product

index.vue

<goods-list @goodsItemClick="goGoodsDetail" :goods="goods"></goods-list>

Defining methods

goGoodsDetail (id) {
	uni.navigateTo({
		url: '/pages/goods-detail/goods-detail?id='+id
	})
}

Subcomponent trigger method

goods-list.vue

<view class="goods_item" v-for="item in goods" :key="item.id" @click="navigator(item.id)">

Defining methods

methods: {
	navigator (id) {
		this.$emit('goodsItemClick',id)
	}
}

5.2 access to detail page data

In the life cycle, data from

Get the corresponding data and save it in data

data() {
	return {
		id: 0,
},
onLoad (options) {
	this.id = options.id
}

Get the data of display carousel

We have observed that the displayed commodity image is a form of round robin. We can write static components first, which is also relatively scientific. We will not show it here, and directly obtain the data writing structure

Interface documentation

Write request method according to interface document

data() {
	return {
		id: 0,
		swipers: [],
	}
},
methods: {
	async getSwipers () {
		const res = await this.$myRequest({
			url: '/api/getthumimages/'+this.id
		})
		this.swipers = res.data.message
	},
}

Execute in lifecycle functions

onLoad (options) {
	this.getSwipers()
},

Page structure

<view class="goods_detail">
	<swiper indicator-dots>
		<swiper-item v-for="(item,index) in swipers" :key="index">
			<image :src="item.src"></image>
		</swiper-item>
	</swiper>
</view>

css

swiper{
	height: 700rpx;
	image{
		width: 100%;
		height: 100%;
	}
}

When we have finished the above, the detailed broadcast chart has been finished.

Get product information

Interface documentation

Write method according to interface document

data() {
	return {
		info: {},
},
async getDetailInfo () {
	const res = await this.$myRequest({
		url: '/api/goods/getinfo/'+this.id
	})
	this.info = res.data.message[0]
},

Call method in lifecycle

onLoad (options) {
	this.id = options.id
	this.getDetailInfo()
},

Page structure

<view class="box1">
	<view class="price">
		<text>¥{{info.sell_price}}</text>
		<text>¥{{info.market_price}}</text>
	</view>
	<view class="goods_name">{{info.title}}</view>
</view>
<view class="line"></view>
<view class="box2">
	<view>Article No.:{{info.goods_no}}</view>
	<view>stock:{{info.stock_quantity}}</view>
</view>
<view class="line"></view>

style

.box1 {
	padding: 10px;
	.price {
		font-size: 35rpx;
		color: $shop-color;
		line-height: 80rpx;
		text:nth-child(2){
			color: #ccc;
			font-size: 28rpx;
			text-decoration: line-through;
			margin-left: 20rpx;
		}
	}
	.goods_name{
		font-size: 32rpx;
		line-height: 60rpx;
	}
}
.box2 {
	padding: 0 10px;
	font-size: 32rpx;
	line-height: 70rpx;
}
.line {
	height: 10rpx;
	width: 750rpx;
	background: #eee;
}

design sketch

Get product introduction data

Interface documentation

Write the request method according to the interface document

data() {
	return {
		content: '',
},
async getDetailContent () {
	const res = await this.$myRequest({
		url: '/api/goods/getdesc/'+this.id
	})
	this.content = res.data.message[0].content
},

Executing methods in the lifecycle

onLoad (options) {
	this.getDetailContent()
},

Page structure
Note that the data put back is rich text, so we need to do special processing here, using < rich text >, Details click

<view class="box3">
	<view class="tit">Details</view>
	<view class="content">
		<rich-text :nodes="content"></rich-text>
	</view>
</view>

css

.box3 {
	padding-bottom: 50px;
	.tit{
		font-size: 32rpx;
		padding-left: 10px;
		border-bottom: 1px solid #eee;
		line-height: 70rpx;
	}
	.content {
		padding: 10px;
		font-size: 28rpx;
		color: #333;
		line-height: 50rpx;
	}
}

When we finish the above code, the following renderings will appear

We found that the whole picture is not completely displayed. We looked at the following printed data and found that there is a class attribute gomeImgLoad on each picture. We gave it a width, which must be placed in the global style App.vue

.gomeImgLoad{
	width: 750rpx;
	height: auto;
}

Refresh again, we find it's ready

5.3 use of UI components

Looking for components

  1. Open the official website of uniapp, click components, find the extended components, and find the product navigation


2. After opening the web page, we import the components and click to import the components using HBuilderX


3. Then select the imported project
4. We copy the code on the official website to our project

Lead in components

import uniGoodsNav from '@/components/uni-goods-nav/uni-goods-nav.vue'
export default {
    components: {uniGoodsNav}
}

Using components

<view class="goods_nav">
	<uni-goods-nav :fill="true" :options="options" :buttonGroup="buttonGroup" @click="onClick" @buttonClick="buttonClick" />
</view>
export default {
    data () {
      return {
        options: [{
            icon: 'headphones',
            text: 'customer service'
        }, {
            icon: 'shop',
            text: 'shop',
            info: 2,
            infoBackgroundColor:'#007aff',
            infoColor:"red"
        }, {
            icon: 'cart',
            text: 'Shopping Cart',
            info: 2
        }],
        buttonGroup: [{
          text: 'add to cart',
          backgroundColor: '#ff0000',
          color: '#fff'
        },
        {
          text: 'Buy now',
          backgroundColor: '#ffa200',
          color: '#fff'
        }
        ]
      }
    },
    methods: {
      onClick (e) {
        uni.showToast({
          title: `click${e.content.text}`,
          icon: 'none'
        })
      },
      buttonClick (e) {
        console.log(e)
        this.options[2].info++
      }
    }
}
  1. We can choose to fix it at the bottom of the page, in good- detail.vue Write the following code in
.goods_nav {
	position: fixed;
	bottom:0;
	width: 100%;
}
  1. We can choose the function we want according to the configuration, Details click

6 supermarket Homepage

6.1 complete basic layout

In fact, the display of goods here is similar to the display of our home page. We can use the components of the home page to display works.

  • Open pages/goods/goods.vue File, import our defined goods-list.vue File and map to components.
import goodsList from '../../components/goods-list/goods-list.vue'
components: {"goods-list":goodsList},
<view class="goods_list">
	<goods-list ></goods-list>
</view>

6.2 bottom touch loading

Bottom touch loading is a life cycle function, Details click
get data

Get data. Different from the home page, the home page only gets one page of data, and when it reaches the bottom here, it will get data again

Interface documentation

Define methods according to interface documents

data() {
	return {
		pageindex: 1,
		goods: [],
	}
},
methods: {
	// Get product list data
	async getGoodsList() {
		const res = await this.$myRequest({
			url: '/api/getgoods?pageindex='+this.pageindex
		})
		this.goods = res.data.message
	},
}

Execute in lifecycle

onLoad () {
	this.getGoodsList()
},

Passing data to components

<goods-list  :goods="goods"></goods-list>

When finished, the effect of the page is as follows

Bottom touch loading

  • The life cycle function required for bottom touch loading is onReachBottom. Bottom touch loading is mainly used to load the data of the second page, so write the following code
onReachBottom() {
	this.pageindex++
	this.getGoodsList()
},
  • Modify the request function
/* this.goods = res.data.message */
this.goods = [...this.goods,...res.data.message]

Bottom touch optimization

When the data is loaded, prompt that the data is loaded

<view class="goods_list">
	<goods-list :goods="goods"></goods-list>
	<view class="isOver" v-if="flag">-----I have a bottom line-----</view>
</view>
  • flag is whether the logo touches the bottom
data() {
	return {
		flag: false
	}
},

Add such a piece of code to the onrealbutton life cycle function

  • Each request to add is a product
if(this.goods.length<this.pageindex*10) return this.flag = true

Embellishment cue line

.goods_list {
	background: #eee;;
}
.isOver {
	width: 100%;
	height: 50px;
	line-height: 50px;
	text-align: center;
	font-size: 28rpx;
}

6.3 pull down refresh

Details click

  1. According to the official document, we need to start the pull-down refresh first, open pages.json Let's follow the text that can change the navigation
"style": {
	"navigationBarTitleText": "Product list",
	"enablePullDownRefresh": true
}
  1. Pull down refresh function
onPullDownRefresh() {
	console.log('Dropdown refreshed')
	this.pageindex = 1
	this.goods = []
	this.flag = false
	this.getGoodsList()
}
  • It should be noted that we need to stop the pull-down refresh, but we need to consider when to stop the pull-down refresh. Because the request is an asynchronous function, generally we should stop the pull-down refresh after requesting data, so we should optimize the request function and the pull-down refresh function
onPullDownRefresh() {
	console.log('Dropdown refreshed')
	this.pageindex = 1
	this.goods = []
	this.flag = false
	setTimeout(()=>{
	  this.getGoodsList(()=>{
			uni.stopPullDownRefresh()
		})	
	},1000)
},
async getGoodsList(callBack) {
	const res = await this.$myRequest({
		url: '/api/getgoods?pageindex='+this.pageindex
	})
	this.goods = [...this.goods,...res.data.message]
	callBack && callBack()
},

6.4 Click to jump to the details page

When we write home page data, in good- list.vue A function goodsItemClick has been defined in the component. Let's write the method again in this component. Of course, you can choose to copy and paste index.vue

<goods-list  @goodsItemClick="goGoodsDetail" :goods="goods"></goods-list>
goGoodsDetail (id) {
	uni.navigateTo({
		url: '/pages/goods-detail/goods-detail?id='+id
	})
}

7. Contact us

7.1 static page structure

open contact.vue Build a static page structure according to the renderings

<view class="contact">
	<image class="img" src="http://www.itcast.cn/2018czydz/images/gywmban.jpg"></image>
	<view class="info">
		<view @click="phone">Tel: 400-618-9090 ( Click to dial )</view>
		<view>Address: xxxxx</view>
	</view>
	<map class="map" :longitude="longitude" :scale="scale" :latitude="latitude" :markers="markers"></map>
</view>

style

.contact{
	.img{
		width: 750rpx;
		height: 320rpx;
	}
	.info{
		padding: 10rpx 20rpx;
		font-size: 30rpx;
		view{
			line-height: 80rpx;
			border-bottom: 1px solid #eee;
		}
	}
	
	.map{
		width: 750rpx;
		height: 750rpx;
	}
}
  • Here we use a component: map Details click
  • A click method is defined to make a call
  • Note that we need to give the map component a width and height

7.2 dynamic

export default {
	data() {
		return {
			longitude: 120.363172,
			latitude: 30.312212,
			scale: 13,
			markers:[
				{
					longitude: 120.363172,
					latitude: 30.312212,
					iconPath: '../../static/logo.png',
					width: 30,
					height: 30
				}
			]
		}
	},
	methods: {
		phone() {
			uni.makePhoneCall({
				phoneNumber: '400-618-9090'
			})
		}
	}
}

Here we only use one api, makePhoneCall, which is used to make phone calls, Details click

8. Community pictures

open pics.vue , observe the rendering, we find that the left and right parts belong to the scrolling part, which requires our component to control the scroll view, Details click

We can write the static components, and then write the dynamic components. We won't show it here. We can get the data directly from the background

Interface documentation

  • Get the classification of the picture on the left

  • Get the picture on the right

How to write a request

data() {
	return {
		cates: [],
		active: 0,
		secondData: []
	}
},
methods: {
	async getPicsCate () {
		const res = await this.$myRequest({
			url: '/api/getimgcategory'
		})
		this.cates = res.data.message
		this.leftClickHandle(0,this.cates[0].id)
	},
	async leftClickHandle (index,id) {
		this.active = index
		// Get data on the right
		const res = await this.$myRequest({
			url: '/api/getimages/'+id
		})
		this.secondData = res.data.message
	},
}
  • active identifies which one is currently clicked
  • leftClickHandle click the left side to get the data on the right side and modify active
  • Categories represents the classification on the left
  • secondData represents the classification on the right

Execute requests in the lifecycle

onLoad () {
	this.getPicsCate()
}

Write static structure

<view class="pics">
	<scroll-view class="left" scroll-y>
		<view 
		@click="leftClickHandle(index,item.id)"
		:class="active===index?'active':''" 
		v-for="(item,index) in cates" 
		:key="item.id">
		  {{item.title}}
		</view>
	</scroll-view>
	<scroll-view class="right" scroll-y>
		<view class="item" v-for="item in secondData" :key="item.id">
			<image @click="previewImg(item.img_url)" :src="item.img_url"></image>
			<text>{{item.title}}</text>
		</view>
		<text v-if="secondData.length === 0">No data available</text>
	</scroll-view>
</view>

Write style

page{
	height: 100%;
}
.pics{
	height: 100%;
	display: flex;
	.left{
		width: 200rpx;
		height: 100%;
		border-right:1px solid #eee;
		view{
			height: 60px;
			line-height: 60px;
			color: #333;
			text-align: center;
			font-size: 30rpx;
			border-top:1px solid #eee;
		}
		.active{
			background: $shop-color;
			color: #fff;
		}
	}
	.right{
		height: 100%;
		width: 520rpx;
		margin: 10rpx auto;
		.item{
			image{
				width: 520rpx;
				height: 520rpx;
				border-radius: 5px;
			}
			text{
				font-size: 30rpx;
				line-height: 60rpx;
			}
		}
	}
}

Finished rendering

9. Information

open news.vue

9.1 package basic components

Write a static page according to the renderings

Let's not show it here. Directly request data. Let's write it by ourselves. Observe the renderings. It's a column of repeated data. We can encapsulate it into a component news-list.vue

Interface documentation

Write method according to interface document

news.vue

data() {
	return {
		newsList: []
	}
},
methods:{
	async getNews() {
		const res = await this.$myRequest({
			url: '/api/getnewslist'
		})
		this.newsList = res.data.message
	},
},

Executing methods in the lifecycle

onLoad () {
	this.getNews()
}

Encapsulating static components

news-list.vue

<view>
	<view class="news_item" @click="navigator(item.id)" v-for="item in list" :key="item.id">
		<image :src="item.img_url"></image>
		<view class="right">
			<view class="tit">
				{{item.title}}
			</view>
			<view class="info">
				<text>Published:{{item.add_time | formatDate}}</text>
				<text>Browse:{{item.click}}</text>
			</view>
		</view>
	</view>
</view>
  • Note that a local filter is used here
  • Defines a method for external triggering
	export default {
		props: ['list'],
		filters: {
			formatDate (date) {
				const nDate = new Date(date)
				const year = nDate.getFullYear()
				const month = nDate.getMonth().toString().padStart(2,0)
				const day = nDate.getDay().toString().padStart(2,0)
				return year+'-'+month+'-'+day
			}
		},
		methods:{
			navigator (id) {
				this.$emit('itemClick',id)
			}
		}
	}
.news_item{
	display: flex;
	padding: 10rpx 20rpx;
	border-bottom: 1px solid $shop-color;
	image{
		min-width: 200rpx;
		max-width: 200rpx;
		height: 150rpx;
	}
	.right{
		margin-left: 15rpx;
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		.tit{
			font-size: 30rpx;
		}
		.info{
			font-size: 24rpx;
			text:nth-child(2){
				margin-left: 30rpx;
			}
		}
	}
}

Introduce components news.vue , and transfer data

<template>
	<view class="news">
		<news-item :list="newsList"></news-item>
	</view>
</template>
<script>
	import newsItem from '../../components/news-item/news-item.vue'
	components: {"news-item":newsItem},
</script>

9.2 jump to details page

New page

Create a new page news-detail.vue , write a static page according to the renderings

Interface documentation

Write method according to interface document

data() {
	return {
		id: 0,
		detail: {}
	}
},
methods: {
	async getNewsDetail () {
		const res = await this.$myRequest({
			url: '/api/getnew/'+this.id
		})
		console.log(res)
		this.detail = res.data.message[0]
	}
},

Executing methods in the lifecycle

onLoad(options){
	this.id = options.id
	this.getNewsDetail()
}
  • Because it's a list, when clicking the list, we will definitely pass a logo. We get the logo from the declaration cycle

Static structure of write detail page

<view class="news_detail">
	<text class="title">{{detail.title}}</text>
	<view class="info">
		<text>Published:{{detail.add_time | formatDate}}</text>
		<text>Browse:{{detail.click}}</text>
	</view>
	<view class="content">
		<rich-text :nodes="detail.content"></rich-text>
	</view>
</view>
.news_detail{
	font-size: 30rpx;
	padding: 0 20rpx;
	.title{
		text-align: center;
		width: 710rpx;
		display: block;
		margin: 20rpx 0;
	}
	.info{
		display: flex;
		justify-content: space-between;
	}
}

Define global filter
main.js

Vue.filter('formatDate',(date)=>{
	const nDate = new Date(date)
	const year = nDate.getFullYear()
	const month = nDate.getMonth().toString().padStart(2,0)
	const day = nDate.getDay().toString().padStart(2,0)
	return year+'-'+month+'-'+day
})

stay news.vue Jump method defined in

<news-item @itemClick="goDetail" :list="newsList"></news-item>
goDetail (id) {
	uni.navigateTo({
		url: '/pages/news-detail/news-detail?id='+id
	})
}

10 packing

Details click

10.1 applet packaging

10.2 H5 packing

10.3 App packaging

Tags: Vue JSON less Database

Posted on Sat, 13 Jun 2020 03:34:05 -0400 by hash1