从零用ui-app做的图片小程序| 小涵找图

388 阅读5分钟

目录

  • 项目介绍
  • 项目搭建
  • uni-ui
  • uni-api

1. 项目介绍

  • 微信小程序
  • 精美图片游览下载
  • 精美视屏游览下载

2. 项目搭建

2.1 新增tablbar页面

页面名称路径
首页home/index.vue
横屏horizontal/index.vue
精美视频video/index.vue
搜索search/index.vue
我的mine/index.vue
  1. 创建响应的文件夹

image

  1. 在这里弄好图标

image

  1. 在page.json粘贴如下代码

一定要注意好格式!

"tabBar": {
		"color": "#8a8a8a",
		"selectedColor": "d4237a",
		"backgroundColor": "#fff",
		"position": "bottom",
		"borderStyLe": "black",
		"list": [
			{
				"pagePath": "pages/home/index",
				"text": "首页",
				"iconPath": "./static/icon/_home.png",
				"selectedIconPath": "./static/icon/home.png"
			},
			{
				"pagePath": "pages/horizontal/index",
				"text": "横屏",
				"iconPath": "./static/icon/_picture.png",
				"selectedIconPath": "./static/icon/picture.png"
			},
			{
				"pagePath": "pages/video/index",
				"text": "精美视频",
				"iconPath": "./static/icon/_video.png",
				"selectedIconPath": "./static/icon/video.png"
			},
			{
				"pagePath": "pages/search/index",
				"text": "搜索",
				"iconPath": "./static/icon/_search.png",
				"selectedIconPath": "./static/icon/search.png"
			},
			{
				"pagePath": "pages/mine/index",
				"text": "我的",
				"iconPath": "./static/icon/_my.png",
				"selectedIconPath": "./static/icon/my.png"
			}
		]
	}

最后效果:

image

2.2 引入字体图标

  • 字体图标使用的是iconfont
  • 在App.vue中全局引入
  1. 在阿里下好 ,
  2. 用Unicode
  3. 去项目里拿到在线网址
  4. 新建css文件,
  5. 引入使用

具体方法

image

<style>
	/*每个页面公共css */
	@import "./styles/base.wxss";
	@import "./styles/iconfont.css";
	
</style>

最后效果 :

image

3. uni-ui

3.1 uni-ui 介绍

  • uni-ui是DCloud提供的一个跨端ui库,它是基于vue组件的、flex布局的、无dom的跨全端ui框架
  • uni-ui不包括基础组件,它是基础组件的补充
  • 数字角标、日历、卡片、折叠面板、倒计时、抽屉、悬浮按钮、收藏按钮、底部购物导航、宫格、图标、索引列表、列表、加载更多、自定义导航栏、通告栏、数字输入框、分页器、弹出层、评分、搜索栏、分段器、步骤条、滑动操作、轮播图指示点、标签、

3.2 uni-ui 使用

  • 安装uni-ui
  • 局部引入组件
  • 注册组件
  • 使用组件

用npm安装

指令:

image

在 script 中引用组件:

import {uniBadge} from '@dcloudio/uni-ui'
//import uniBadge from '@dcloudio/uni-ui/lib/uni-badge/uni-badge.vue' //也可使用此方式引入组件
export default {
    components: {uniBadge}
}

在 template 中使用组件:

<uni-badge text="1"></uni-badge>
<uni-badge text="2" type="success" @click="bindClick"></uni-badge>
<uni-badge text="3" type="primary" :inverted="true"></uni-badge>

4. uni-api

  • 原生的微信小程序的api都是不支持promise
  • uni-app对大部分的小程序的原生api做了封装,使之支持promise
  • 使用方式
    • 原生微信小程序 wx.request
    • uni-api的方式uni.request
    • 其他api的使用方式也类似

5. 功能分析

  • 修改导航栏的外观
  • 使用分段器组件搭建子页面
  • 封装自己异步请求

5.1 修改导航栏外观

在page.json里:

	"globalStyle": {
		"navigationBarTextStyle": "white",
		"navigationBarTitleText": "小涵找图",
		"navigationBarBackgroundColor": "#000"
		
	},

5.2 搭建子页面

  • 首页模块分为4个部分,分别是推荐、分类、最新、专辑
  • 新建自定义组件来代替上述的4个页面
    • home-recommend
    • home-category
    • home-new
    • home-album
  1. 搭建好组件
  2. 引用组件
  3. 注册组件
<script>
import uniBadge from '@dcloudio/uni-ui';
import homeRecommend from "./home-recommend";
import homeCategory from "./home-category";
import homeNew from "./home-new";
import homeAlbum from "./home-album";
export default {

    data() {
        return {
            
        }
    },
    components:{
        homeRecommend,
        homeCategory,
        homeNew,
        homeAlbum
    }
    
}

</script>

效果图:

image

5.3 分段器介绍

简单来说 就是tab导航栏

  1. 去uni-ui官网找到分段器这个组件
  2. import引入一下
import {uniSegmentedControl} from '@dcloudio/uni-ui';
  1. 在components里注册组件
    components:{
        homeRecommend,
        homeCategory,
        homeNew,
        homeAlbum,
        uniSegmentedControl 
    },
  1. 补充组件需要的数据
    data() {
        return {
            items:[
                {title:"推荐"},
                {title:"分类"},
                {title:"最新"},
                {title:"专辑"}
            ],
            current:0 //当前激活数据的索引
        }
    },
   <view>
      <uni-segmented-control
        :current="current"
        :values="items.map(v=>v.title)"
        @clickItem="onClickItem"
        styleType="text"
        activeColor="#d4237a"
      ></uni-segmented-control>
      <view class="content">
        <view v-if="current === 0"> <home-recommend></home-recommend> </view>
        <view v-if="current === 1"> <home-category></home-category> </view>
        <view v-if="current === 2">  <home-new></home-new></view>
        <view v-if="current === 3"> <home-album></home-album> </view>
      </view>
    </view>

点击索引切换的点击事件

    methods: {
        onClickItem(e){
            if (this.current !== e.currentIndex) {
                this.current = e.currentIndex;
        }
    }
    }

5.4 优化分段器

  1. 改颜色和边框 :
          <uni-segmented-control
            :current="current"
            :values="items.map((v) => v.title)"
            @clickItem="onClickItem"
            styleType="text"
            activeColor="#d4237a"
          ></uni-segmented-control>
  1. 调整他的结构
    <view class="home_tab">
      <view class="home_tab_title">
        <view class="title_inner">
          <uni-segmented-control
            :current="current"
            :values="items.map((v) => v.title)"
            @clickItem="onClickItem"
            styleType="text"
            activeColor="#d4237a"
          ></uni-segmented-control>
        </view>
        <view class="iconfont icon-sousuo"></view>
      </view>

      <view class="home_tab_content">
        <view v-if="current === 0"> <home-recommend></home-recommend> </view>
        <view v-if="current === 1"> <home-category></home-category> </view>
        <view v-if="current === 2"> <home-new></home-new></view>
        <view v-if="current === 3"> <home-album></home-album> </view>
      </view>

修改css:

<style lang="scss">
.home_tab {
  .home_tab_title{
    position: relative;
    .title_inner{
      width: 60%;
      margin: 0 auto;
    }
    .icon-sousuo{
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      right: 5%;
    }
  }
  .home_tab_content {

  }
}
</style>

效果图:

image

6. 封装自己的异步请求

6.1 为什么要封装

  • 原生的请求不支持promise
  • uni-api的请求不能够方便的添加请求中效果
  • uni-api的请求返回值是个数组,不方便

6.2 封装的思路

  • 基于原生的promise来封装
  • 挂载到Vue的原型上
  • 通过this.request的方式来使用

接口文档

封装的代码:

//基于es6 promise wxapi

export default (params)=>{
    //加载中
    uni.showLoading({
        title:'加载中'
    })
    return new Promise((resolve,reject)=>{
        wx.request({
            ...params,
            success(res){
                resolve(res.data);

            },
            fail(err){
                reject(err);
            },
            complete(){
                uni.hideLoading();
            }
        })
    })
}

在main。js里引入

import request from './utils/request'

Vue.config.productionTip = false
Vue.prototype.request=request;

在index。vue里通过this。request使用

    this.request({
      url:'http://157.122.54.189:9088/image/v3/homepage/vertical'
    })
    .then(res=>{
      console.log(res);
    })

7. 编写首页推荐模块

7.1 功能介绍

  • 数据动态渲染
  • moment.js 的使用
  • “热门”列表的基于scroll-view的分页加载

图片高度自适应:

<image mode="widthFix" :src="item.thumb"></image>

图片的样式:

运用了flex布局

<style lang="scss" scoped>
    .recommend_wrap{
        display: flex;
        flex-wrap: wrap;
        .recommend_item {
            width: 50%;
            border: 5rpx solid #fff;
        }
    }
</style>

vue的列表渲染:

        <!-- 推荐 开始 -->
        <view class="recommend_wrap">
            <view class="recommend_item" v-for="item in recommends" :key="item.id">
                <image mode="widthFix" :src="item.thumb"></image>
            </view>
        </view>
        <!-- 推荐 结束 -->

数据的请求:

    // 组件挂载完成
    mounted(){
        this.request({
            url:"http://157.122.54.189:9088/image/v3/homepage/vertical",
            data: {

                //获取几条数据
                limit:30,
                // 关键字
                order: "hot",
                // 要跳过几条
                skip: 0
                
            }
        })
        .then(result=>{
            console.log(result);
            this.recommends=result.res.homepage[1].items;
        })
    }

原先接口坏了 找到的新接口

service.picasso.adesk.com/v3/homepage/vertical

小结:

  1. 先找到数据来源
  2. 图片是个数组,用vue对他列表循环

效果图:

image

7.2 分页功能

  • 使用scroll-view标签充当分页的容器
  • 绑定滚动条触底事件scrolltolower
  • 实现分页逻辑
  1. 将参数变为全局变量便于修改
  2. 更开skip拿数据,在点击事件里处理

8. 专辑模块

10. 精美视频模块

10.1 功能分析

  • 分段器的使用
  • 发送请求获取数据
  • 渲染页面
  • 分页加载
  • 页面渲染
  • 播放视频
  • 开关声音
  • 转发
  • 下载视频

10.2 发送请求获取数据

  • 每一个子页面用到的接口地址或者接口参数都不一样
  • 将每一个页面的接口地址和接口参数都封装到标题组中
  • 点击标题的时候,也传递对应的接口路径和参数给内容组件
  • 需要在组件中使用“watch”来监控接收的参数发生了变化
  • 内容组件接收参数,发送请求渲染页面

简单来说

把接口放在标题里,通过数组传参到子组件

,回到子组件里先接受,然后发请求拿数据, 通过watch实现监控点击触发

image

10.3 视频播放功能

  • 页面渲染
  • 播放视频
  • 开关声音
  • 转发
  • 下载视频

做两件事

  • 缓存数据
  • 跳转播放视频
  1. 先给图片设置点击事件,点了跳转到播放页
  2. 设置一个全局变量共享,让播放页能拿到数据
  3. 在播放页页面渲染

10.31 开关声音和转发

  • video标签的 muted 属性实现声音的开关
  • button的open-type设置为share 实现转发

效果完成图:

image

10.32 下载视频功能

设置点击事件 handleDownload

    //   下载视频
    async handleDownload(){

            await uni.showLoading({title:"下载中"});
            // 1. 将远程文件下载到小程序内层中
            
           const{tempFilePath}=(await uni.downloadFile({url:this.videoObj.video}))[1];
           // 2. 将内存中的文件下到本地
           uni.saveVideoToPhotosAlbum({
               filePath:tempFilePath
           });

           uni.hideLoading();

           await uni.showToast({title:"下载成功"})
    }

未完待续~