catalog
- 1 project construction
- 2. Frame up
- 3 get data from the background
- 4 home page
- 4.1 configure basic data of home page
- 4.2 rotation chart
- 4.3 navigation in the page
- 4.4 recommended products on the homepage
- 5 detail page of single product
- 6 supermarket Homepage
- 6.1 complete basic layout
- 6.2 bottom touch loading
- 6.3 pull down refresh
- 6.4 Click to jump to the details page
- 7. Contact us
- 8. Community pictures
- 9. Information
- 10 packing
Project source address: https://github.com/whynot-todo/uniapp_demo.git
1 project construction1.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
- 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.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
- pages/index/index
- pages/cart/cart
- pages/member/member
- pages/news/news
2. New page steps
- Right click under pages folder and select new page
- 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
- 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.1 package request component
- 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.
- 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
- Download phpStudy and open it. The version used here is 8.1.0.1
- Start MYSQL service
- Click open, click SQL_Front
- Click to open
- Right click localhost, select new, select database
- Enter the database name (the same as our local sql file), and click OK
- Right click our new database, click input, click sql file,
- Import the local file, note that the character set is utf-8
- After importing, we can close the current page, but we cannot exit phpStudy
- Open the server folder and run the command node app.js , running the background project.
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
- We need to use the swiper component, Details click
<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
- 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"; }
- We are index.vue Write the following structure in
<view> <view> <view></view> <text>Supermarket Homepage</text> </view> <view> <view></view> <text>contact us</text> </view> <view> <view></view> <text>Community picture</text> </view> <view> <view></view> <text>Video Zone</text> </view> </view>
- 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;
- 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
- /pages/goods/goods
- /pages/pics/pics
- /pages/contact/contact
- /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
- 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" } ]
- Delete the above repeated structure. We use v-for to traverse the rendering structure and define the click jump method
<view> <view v-for="(item,index) in navs" :key="index" @click="navItemClick(item.path)"> <view :class="item.icons"></view> <text>{}</text> </view> </view>
- We define the click method in methods
navItemClick(url) { uni.navigateTo({ url }) }
- Then we can click jump
4.4 recommended products on the homepage
Single static structure
- We write a single static structure according to the renderings
<!-- Pick of the week --> <view> <view>Pick of the week</view> <!-- Single item--> <view> <view> <image></image> <view> <text>1299</text> <text>12990</text> </view> <view>Huawei( HUAWEI)Glory 6 Plus 16G Double 4 G edition</view> </view> </view> </view>
- 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
- Looking at the renderings, we find that the product card is a repeated structure, and we can draw it into a component
- 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> <view> <image></image> <view> <text>1299</text> <text>12990</text> </view> <view>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>
- stay index.vue Introduce and map to components in
import GoodsList from '../../components/goods-list/goods-list.vue' components:{ GoodsList }
- In template
<view> <view>Pick of the week</view> <goods-list></goods-list> </view>
- design sketch
Get dynamic data
- 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: [] } }
- In the declare periodic function, send the request
onLoad() { this.getHotGoods() },
Pass data to subcomponent label
- transmit
<goods-list :goods="goods"></goods-list>
- The subcomponent label receives the data and renders the goods list according to the interface document
export default { props:['goods'], }
template
<view> <view v-for="item in goods" :key="item.id"> <image :src="item.img_url"></image> <view> <text>¥{}</text> <text>¥{}</text> </view> <view>{}</view> </view> </view>
Effect after configuration
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 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> <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> <view> <text>¥{}</text> <text>¥{}</text> </view> <view>{}</view> </view> <view></view> <view> <view>Article No.:{}</view> <view>stock:{}</view> </view> <view></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> <view>Details</view> <view> <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
- 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> <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++ } } }
- 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%; }
- We can choose the function we want according to the configuration, Details click
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> <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> <goods-list :goods="goods"></goods-list> <view 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
- 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 }
- 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> <image src="http://www.itcast.cn/2018czydz/images/gywmban.jpg"></image> <view> <view @click="phone">Tel: 400-618-9090 ( Click to dial )</view> <view>Address: xxxxx</view> </view> <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 picturesopen 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> <scroll-view scroll-y> <view @click="leftClickHandle(index,item.id)" :class="active===index?'active':''" v-for="(item,index) in cates" :key="item.id"> {} </view> </scroll-view> <scroll-view scroll-y> <view v-for="item in secondData" :key="item.id"> <image @click="previewImg(item.img_url)" :src="item.img_url"></image> <text>{}</text> </view> <text v-if="secondData.length === 0">No data available</text> </scroll-view> </view>
- Here we use a preview image api Details click
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
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 @click="navigator(item.id)" v-for="item in list" :key="item.id"> <image :src="item.img_url"></image> <view> <view> {} </view> <view> <text>Published:{}</text> <text>Browse:{}</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) } } }
- For the description of padStart, Details click
.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> <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> <text>{}</text> <view> <text>Published:{}</text> <text>Browse:{}</text> </view> <view> <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