使用uni-app搭建微信小程序

0 问题待解决

  • import { } 与否
  • 为什么要封装
  • 对齐问题
  • 每次重启项目,sitemap就会消失
  • 动态修改标题失效
  • 图片问题多多 :高度自适应 改成image固定高度,mode:aspectFill
  • 微信小程序文档
  • b站视频链接
  • 后端接口文档

一、知识点

  • uni-app 是一个使用 Vue.js语法来开发所有前端应用的框架
  • 项目技术栈:js+vue+微信小程序+uni-app
  • 750rpx = 屏幕宽度(微信小程序)
  • 100vw = 屏幕宽度(H5)
  • 100vh = 屏幕高度(H5)
  • 微信小程序中不支持*通配符
  • 出现奇怪的报错后,可以npm重启项目
  • 原生的微信小程序不支持promise
  • uni-api支持promise,请求返回值是个数组,无法实现项目“等待中”效果,因此要自行封装异步请求
    在这里插入图片描述

二、基本语法

1. 数据展示

  • 在 js 的 data 中定义数据
  • 在 template中通过 {{ 数据 }} 来显示
  • 在标签的属性(自定义属性)上通过 :data-index='数据’来使用

2. 数据循环、条件编译、计算属性同vue语法

3. 事件传参(传入$event获取自定义属性)

思考:targetcurrentTarget的区别

<text data-id="myId" @click="showId($event)">点我显示id</text>
showId(event) {console.log(event.currentTarget.dataset.id)
}

在这里插入图片描述

4. 组件

1. 注册组件

  • 创建组件页面 .vue文件(组件样式也在这里修改)
  • import组件(注意不能用-,js中会当成减号)
  • 注册到vue实例上,components: {}
  • <template>中短横线形式,使用组件

2. 组件传参

1)父传子

  • props属性和data同级,并不是在data里面!
  • 为了父组件复用子组件

父组件
父组件中自定义属性mysrc(体现传值),右边内容若为变量,则须在mysrc前添加冒号

    <my-yuyan :mysrc="xuanyan" mytitle="渲言"></my-yuyan><my-yuyan :mysrc="yuyan" mytitle="喻言"></my-yuyan>
  data() {return {xuanyan: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591198770665&di=3bdaf80f7bd15f03dfea55bf88e391a0&imgtype=0&src=http%3A%2F%2Fimglf5.nosdn0.126.net%2Fimg%2FbjZaRmVpWExkaE1ScFc3VzRjUW1INUJhcTcxVGNTcVF0VGpFYkxXelNiZWZnMW1SYjAzUFJBPT0.jpg%3FimageView%26thumbnail%3D500x0%26quality%3D96%26stripmeta%3D0%26type%3Djpg",yuyan: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591200770069&di=a90535dc0ff79617758b4ec32484e1bd&imgtype=0&src=http%3A%2F%2Fwx2.sinaimg.cn%2Flarge%2F59853be1ly1gff7y14skvj20c80c8dna.jpg"};},

子组件
(父组件所传值)需要在子组件中声明:props中当与父组件的自定义属性相同

    <view><view>{{mytitle}}</view><image class="yuyan" :src="mysrc"></image></view>
export default {props:['mysrc', 'mytitle']
}

2)子传父

  • 子组件<template>绑定事件
  • 子组件methods部分触发自定义事件
  • 父组件<template>在子组件上监听自定义事件
  • 父组件methods部分处理子组件传来的参数

子组件
在这里插入图片描述
父组件
在这里插入图片描述
在这里插入图片描述

3)全局共享数据

*1. 通过 Vue的原型共享数据

main.js中定义

Vue.prototype.theme ="the 9"

.vue组件中使用

  onLoad() {console.log(this.theme)}
*2. 通过 globalData 共享数据

App.vue文件定义

globalData: {date: '2020-05-30'
}

获取

getApp().globalData.date

3. 组件插槽slo - 父向子传递标签

在父组件中使用到了子组件,在该页面的子组件内部插入标签,但是不知道具体的放置位置在哪,所以要在子组件定义的页面里用slot标签来占位。
父组件

  • 这个标签放在子组件内部!
    在这里插入图片描述
    子组件
  • 使用<slot>占位,制定父组件传来的标签出现在哪个位置
    在这里插入图片描述
    效果,救命啊~~~
    在这里插入图片描述

5. 生命周期

  • uni-app框架的生命周期结合了 vue 和 微信小程序的生命周期

  • 全局的APP中 使用 onLaunch 表示应用启动时

  • 页面中 使用 onLoad 或者 onShow 分别表示 页面加载完毕时 和页面 显示时

  • 组件中使用 mounted 组件挂载完毕时

三、项目

(一)项目开始

0. 接口文档

接口文档

1. 起步

项目名称:my-project → 默认模板 → 注意项目目录(C:\try\uniapp\my-project\dist\dev\mp-weixin)→ AppId可暂时忽略
在这里插入图片描述

全局安装
npm install -g @vue/cli
创建项目
vue create -p dcloudio/uni-preset-vue my-project
启动项目(微信小程序)
npm run dev:mp-weixin
微信小程序开发者工具导入项目

2. 引入saas (在启动项目前安装)

安装依赖
npm install sass-loader node-sass
vue组件中,添加属性 <style lang='scss'>

注意: 这里需要在vscode里编辑C:\try\uniapp\my-project路径下的项目

3. 页面

app.js 文件 (微信小程序中)

  "pages": ["pages/index2/index","pages/index/index"],

pages数组中第一项表示应用启动页


pages.json(vscode中)

"pages": [ {"path": "pages/index/index","style": {"navigationBarTitleText": "uni-app"}},{"path": "pages/index2/index","style": {"navigationBarTitleText": "uni-app"}}]

4. 报错 sitemap配置

官网配置

VM303:1 sitemap.json
Error: 未找到入口 sitemap.json 文件,或者文件读取失败,请检查后重新编译。

在这里插入图片描述
在vscode的微信小程序的根目录下新建sitemap.json

{"rules":[{"action": "allow","page": "*"}]
}

5. uni-api

uni-api

  • 原生的微信小程序的api都是不支持promise

  • uni-app对大部分的小程序的原生api做了封装,使之支持promise

使用方式 :
wx.request(原生微信小程序)修改为uni.request (uni-api的方式 )

微信小程序:

wx.request({url: '',success(res) {console.log(res)}
})

uni-api:

uni.request({url: ''
})
.then(res=> {console.log(res)
})

6. uni-ui

uni-ui

uni-ui的使用方式

  • 安装uni-ui
  • 局部引入组件
  • 注册组件
  • 使用组件
cnpm install @dcloudio/uni-ui
import {uniBadge} from '@dcloudio/uni-ui'
export default {components: {uniBadge}
}
<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>

7. 全局引入字体图标、样式

styles文件夹放入src路径下
在这里插入图片描述
App.vue文件中引入,注意不能使用@

<style>@import "./styles/iconfont.wxss";
</style>

使用

<text class="iconfont iconvideocamera"></text>

8. 小程序导航栏标题、样式修改

pages.json

	"globalStyle": {"navigationBarTextStyle": "white","navigationBarTitleText": "青春有你","navigationBarBackgroundColor": "#000"}

(二)首页模块

1. 组件分段器-tab栏/标签页

tab栏:推荐、分类、最新、专辑

1. 组件引入

分段器的使用
文档中以下部分要修改:

  1. 引入路径
import { uniSegmentedControl } from "@dcloudio/uni-ui";
  1. 参数e
    onClickItem(e) {if (this.current !== e.currentIndex) {this.current = e.currentIndex;}}
  1. 样式从button改为text
    <uni-segmented-controlstyle-type="text"></uni-segmented-control>

2. 结构分析

在这里插入图片描述
上下结构

  • 上:左右结构

2.【专题】 图片详情 - 第48课

1. 封装组件

首页-推荐-热门中的图片跳转到到图片详情页面

  1. 将热门中的图片标签封装为超链接组件(js方式跳转)/ 图片详情组件
  2. 缓存(图片详情页面需要的)图片数组图片索引 (组件传值,存储到全局数据中)
  3. 图片详情页面要使用到插槽
    父组件:
<view class="img_wrap" v-for="(item, index) in hots" :key="item.id"><go-detail :list="months.items" :index="index"><image :src="item.thumb" mode="widthFix"></image></go-detail>
</view>

子组件

<template><view @click="clickHotImg"> 图片详情组件<slot></slot></view>
</template><script>
export default {props:['list', 'index'],methods:{clickHotImg() {getApp().globalData.imgList = this.listgetApp().globalData.imgIndex = this.indexuni.navigateTo({url: '../../pages/imgDetail/index' -- 也可以用根路径/pages的形式,见图片分类})}}};
</script>

图片详情页面,需要在pages.json中配置

<template><view>图片详情页面</view>
</template><script>
export default {onLoad() {console.log('缓存的数据', getApp().globalData)}
};
</script>

在这里插入图片描述

2. 项目中所有需要跳转的表情替换为组件

  1. 首页-推荐-热门
  2. 首页-推荐-月份
  3. 专辑-专辑详情-wallpaper

3. 【问题】:组件不渲染

  • 将slot前的文字去除,自定义组件不渲染了?
    在这里插入图片描述
  • 修改slot前的文字,影响了组件的宽度?
    在这里插入图片描述
    给自定义组件加样式,继承宽高,这时原来scallToFill的模式图片不显示了,原因未知(高度为0),只好用回widthFix,再给外部标签加overflow:hidden
<view class="wallpaper_image" v-for="(item, index) in wallpaper" :key="item.id"><!-- :src="item.thumb+item.rule.replace('$<Height>',360)" --><go-detail :list="wallpaper" :index="index" class="wallpaperDetail">    <image :src="item.thumb+item.rule.replace('$<Height>',360)" mode="widthFix" ></image></go-detail>
</view>
.wallpaper {display: flex;flex-wrap: wrap;.wallpaper_image {width: 33.3%;height: 130rpx;border: 1rpx solid #fff;.wallpaperDetail {display: flex;justify-content: center;align-items: center;height: 100%;width: 100%;overflow: hidden;}}
}

4. 约定

图片详情页面包括:专辑图像+专辑相关+最热评论+最新评论
在这里插入图片描述

5. 判断图片src存在后再渲染

本地图片未加载成功的情况 Failed to load local image resource /pages/XXX/处理

<image  v-if="imgList[imgIndex].thumb+imgList[imgIndex].rule.replace('$<Height>',360)" :src="imgList[imgIndex].thumb+imgList[imgIndex].rule.replace('$<Height>',360)">
</image>

6. 用全局数据初始化

这样写太土了

data() {return {imgList: getApp().globalData.imgList,imgIndex: getApp().globalData.imgIndex}
}```go
export default {onLoad() {const{imgList, imgIndex} = getApp().globalDatathis.imgDetail = imgList[imgIndex]console.log('缓存的数据', getApp().globalData)},data() {return {imgDetail: {}}}
};

在这里插入图片描述

7. moment.js处理时间戳为几天前

  • fromNow() 实现显示为XX天/月/年前
  • moment.locale('zh-cn') 使用中文语言(写在js里)
this.commemtTime = moment(this.imgDetail.atime*1000).fromNow()

3. 【专题】封装手势滑动组件 - P66

在这里插入图片描述

  1. 手指在容器上产生了移动
  •  手指按下屏幕事件 touchstart
    
  •   手指离开屏幕事件 touchend 
    
  •   手指在屏幕上的坐标 event.changedTouches[0].clientX  和 clientY
    
  1. 手指在容器上滑动的时间不能太长 - Date.now()时间戳
  •   记录按下屏幕的时间
    
  •   记录离开屏幕的时间
    
  1. 根据坐标判断滑动的方向
  •   手指离开屏幕的时候根据坐标判断滑动的方向
    

子组件

<template><view @touchstart="handleTouchStart" @touchend="handleTouchEnd"><slot></slot></view>
</template><script>
export default {data() {return {//按下的时间startTime: 0,startX: 0,startY: 0};},methods: {handleTouchStart(event) {this.startTime = Date.now()this.startX = event.changedTouches[0].clientX this.startY = event.changedTouches[0].clientY },handleTouchEnd(event) {const endTime = Date.now()const endX = event.changedTouches[0].clientXconst endY = event.changedTouches[0].clientYif (endTime - this.startTime > 2000) {return}let direction = ''if (Math.abs(endX - this.startX) > 10) {direction = endX -this.startX > 0 ? 'right': 'left'} else {return}this.$emit('swipeAction', {direction})}}
};
</script>

父组件

<swipe-action @swipeAction="handleSwipeAction"><image  v-if="imgUrl" :src="imgUrl"mode="scaleToFill"></image>
</swipe-action>
handleSwipeAction (e) {console.log(e)
}

*. 解决bug:垂直距离滑动造成的翻页

  if (Math.abs(endX - this.startX) > 10 && Math.abs(endY - this.startY) < 10) {direction = endX -this.startX > 0 ? 'right': 'left'} else {return}

4. 【专题】下载图片

  • downloadFile 下载远程文件到小程序的内存中
  • saveImageToPhotosAlbum 将 图片从内存中下载到本地
async handleClick() {await uni.showLoading({title: '下载中'})const res1 = await uni.downloadFile({url: this.imgDetail.img})const {tempFilePath} = res1[1]const res2 = await uni.saveImageToPhotosAlbum({ filePath: tempFilePath})uni.hideLoading()await uni.showToast({title: '下载成功'})
}

(三)推荐模块

1. 封装异步请求

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

2. for循环

注意:在uni-app框架里,仍用v-for指令

<view class="recommend_item" v-for="item in recommends" :key="item.id"><image :src="item.thumb"></image>
</view

3. 理解flex:wrap

flex-wrap: nowrap | wrap | wrap-reverse;

两栏布局常见:
(限定了每一循环项的宽度为一半,并且换行)

width: 50%;
flex-wrap: wrap;

4. 插件CssTree

快速根据html结构,生成对应sass结构(选中代码,ctrl+shift+P

5. sass的变量使用,定义主题颜色

uni.scss文件中定义:
在这里插入图片描述
在样式中使用:
在这里插入图片描述

6. 对齐问题

这种结构很不好啊,避免这种结构在这里插入图片描述
块级元素和行内元素同时存在的情况,如何基线对齐

7. moment.js第三方库处理时间

moment.js官方文档

  • cnpm install moment --save

优化:
在这里插入图片描述
在这里插入图片描述
由于月份是请求来的数据,防止在一开始渲染的时候,出现undefined,需要改造组件:

<!-- 月份列表 开始 -->
<view class="months_wrap" v-if="Object.keys(months).length!==0" >

或者在最外层标签加:

<scroll-view v-if="recommends.length > 0" scroll-y class="recommend_view" @scrolltolower="handlerToLower" >

8. 【专题】翻页效果:使用scroll-view改造容器

  • 原先使用view标签的情况(template内第一个最外层的view),不能冻结头部tab栏,因此替换为scroll-view标签

  • 添加scroll-y属性

  • 计算高度height: calc(100vh - 45px); (屏幕的高减去头部固定高度)

  • 绑定滚动条触底事件,@scrolltolower,当到底时,①skip+=limit,②再次发起请求,③且hots做数据叠加,达到分页效果

  • 如何叠加?使用es6语法this.hots = [...this.hots, ...res.res.vertical]

  • hasMore判断是否还有更多,当返回值.length为0,将hasMore置为false

  • 头部的轮播图无须多次请求,当this.xx.length为0,才初始化

   methods: {getList() {this.request({url: "http://157.122.54.189:9088/image/v3/homepage/vertical",data: this.params}).then((res)=> {if(res.res.vertical.length === 0) {uni.showToast({title: '到底了宝贝儿:)',icon: 'none'})this.hasMore = falsereturn}        if(this.recommends.length === 0) {// 首次请求this.recommends = res.res.homepage[1].itemsthis.months = res.res.homepage[2]this.months.MM = moment(this.months.stime).format("MM")this.months.DD = moment(this.months.stime).format("DD")}this.hots = [...this.hots, ...res.res.vertical]})},handlerToLower() {if(this.hasMore) {this.params.skip+=this.params.limitthis.getList()} else {uni.showToast({title: '到底了:)',icon: 'none'})}}}

9. 【专题】写分页容易错的地方

加了分页代码后,小程序报错Cannot read property 'replace' of undefined
这可不是小程序的bug,定位到使用replace方法的地方
<image :src="item.thumb+item.rule.replace('$<Height>',360)"></image>
因此意味着item.rule可能是null/undefined,那么直接将src赋值为 item.thumb看看效果:
在这里插入图片描述
法宣循环多出了一个空白的image,并且this.wallpaper的首项是一个空数组,那一定是在分页请求,做数据叠加除了问题,定位到代码:

this.wallpaper = [this.wallpaper, ...res.res.wallpaper]

竟然是没有写解构,惊了(ಥ﹏ಥ)(ಥ﹏ಥ)(ಥ﹏ಥ),吸取教训,遇到问题冷静排查。

(三)专辑模块

1. 轮播图组件swiper

indicator-dots 面板指示圆点
autoplay 自动播放
circular 连续播放

    <view class="album_swiper"><swiper indicator-dots autoplay circular> <swiper-item v-for="item in banner" :key="item.id"> <image :src="item.thumb" mode="widthFix"></image></swiper-item></swiper>

注意屏幕尺寸变化时,轮播图、图片应该随之变化:
在不设置的情况下,调整为大屏,图片显示不全。
在这里插入图片描述
在这里插入图片描述

  • swiper组件默认高度150px,不能由内容撑开,宽度750rpx
  • 图片默认宽320px,默认高240px,由于项目里base.wxss重置了样式,图片宽为100%
  • 应当重新赋值给swiper的高,使之与图片宽高等比
  • 检查元素,看图片实际宽640px、高284px
  • swiper的高为 750/(640/284),图片高度设置为100%
  • 注意calc不要再写错了!不要有多余的样式,否者可能会不生效
  swiper {height: calc(750rpx / (640/284));image {height: 100%;}}

2. 组件中动态修改页面标题

在每个组件的mounted钩子中添加如下代码:

  mounted() {uni.setNavigationBarTitle({title: '分类'})}

3. 【专题】左右布局

外容器:flex布局
左:flex: 1 → 内image固定宽高
image:height+width: 200rpx; mode=“aspectFill”
右:flex: 2
在这里插入图片描述
当红框中内容是子绝父相定位到底部时,由于绝对定位宽度由内容撑开,因此子需要加width: 100%使之占满整行,这样做justify-content: space-between时才能两端对齐。

  .bgInfo {display: flex;height: 80rpx;align-items: center;padding: 0 20rpx;justify-content: space-between;position: absolute;width: 100%;bottom: 10rpx;color: #fff;.albumName {font-size: 40rpx;}.followBtn {width: 152rpx;height: 60rpx;display: flex;justify-content: center;align-items: center;border-radius: 10rpx;padding: 5 10rpx;font-size: 30rpx;background-color: $themeColor;}}

图片填满格子:
mode=“scaleToFill”

  .wallpaper_image {width: 33.3%;height: 170rpx;border: 3rpx solid #fff;display: flex;justify-content: center;align-items: center;image {width: 100%;height: 100%;}}

在这里插入图片描述

4. 【专题】文字一行显示,超出显示省略号

右:flex: 2 + overflow: hidden(否则会被文字撑开)

        text-overflow: ellipsis;overflow: hidden;white-space: nowrap;

5. 点击推荐页面,跳转到专辑详情,并获取id参数

改造成navigator组件,注意绑定的url是在" "内再使用模板字符串

<navigator :url="`/pages/album/index?id=${item.target}`" class="recommend_item" v-for="item in recommends" :key="item.id"><image :src="item.thumb" mode="widthFix"></image>
</navigator>

在方法里的url又不用带双引号" "

    getAlbumDetail() {this.request({url: `http://157.122.54.189:9088/image/v1/wallpaper/album/${this.id}/wallpaper`,data: this.params}).then(res => {console.log('专辑详情', res)})    }

在跳转到的页面打印来源页面所携带的参数(接收参数id):

export default {onLoad(options) {console.log(options)}
}

6. 小程序设置默认tabs页

设置分段器tab栏自带的current属性
而pages.json文件中,pages数组的首项为项目启动首页

	"pages": [ {"path": "pages/album/index"},{"path": "pages/home/index"}

7. 后端返回代码有换行符,前端如何处理

view标签里包裹一层text即可

        <view class="author_info"><text>{{album.desc}}</text></view>

后端返回:

"desc":"急先锋是一种精神,他们急流勇进,先锋夺人!\n急先锋是一份责任,他们上天入地,护你周全!"

效果:
在这里插入图片描述

8. onReachBottom上拉加载事件

scroll-view组件分页的区别:保持头部tab栏不动
专辑详情页面上拉加载:整个页面的加载更多分页

(四)分类模块

1. css3渐变效果

.imgName {background-image: linear-gradient(to right top, rgba(0,0,0,.2),rgba(0,0,0,0));
}

在这里插入图片描述

2. 点击图片跳转详情

<navigator class="img" v-for="item in category" :key="item.id" url='/pages/imgCategory/index'><image :src="item.cover" mode="aspectFill"></image><div class="imgName">{{item.name}}</div>
</navigator>

这里用url='/pages/imgCategory/index' 根路径/

3. 图片分类-最新/热门修改分段器

由于最新和热门的数据渲染只需改变请求参数,因此修改分段器,将参数order写入

items: [{ title: "最新", order:"new"}, { title: "热门", order:"hot"}]

同时分段器绑定的values也要返回新的数组

<uni-segmented-control:current="current":values="items.map(e=>e.title)"@clickItem="onClickItem"style-type="text"active-color="#d4237a"
></uni-segmented-control>

同时,最新/热门只使用一个组件

<view class="category_tab_content"><view class="cate_item" v-for="item in vertical" :key="item.id"><image :src="item.thumb" mode="aspectFill"></image></view>
</view>

4. 根据tabs请求数据

  1. 点击tab栏,更新请求参数
  2. 重新发请求

5. scroll-view标签使用flex布局的注意点

在这里插入图片描述
若未进行设置 enable-flex 属性以使 flexbox 布局生效设置,flex效果失效
在这里插入图片描述

<scroll-view scroll-y enable-flex class="category_tab_content"><view class="cate_item" v-for="item in vertical" :key="item.id"><image :src="item.thumb" mode="aspectFill"></image></view>
</scroll-view>

6. 下拉事件加载更多的注意点(数据重置)

  1. bug1:点击tab栏时skip应被初始化为0
  2. bug2:vertical的数组不断被叠加,切换tab栏时还显示之前的数据
  3. 优化:当重复点击“最新”或“热门”时,后续代码不必重复执行
onClickItem(e) {if (this.current !== e.currentIndex) {this.current = e.currentIndexthis.params.skip = 0 this.vertical = []this.params.order = this.items[e.currentIndex].orderthis.getCategoryDetail()} else {return}
}

(五)精美视频

在这里插入图片描述

1. 组件选择

  1. 每一个子页面用到的接口地址或接口参数都不一样
  2. 将每一个页面的接口地址或接口参数都封装到标题数组中
  3. 点击标题时,也传递对应的接口路径和参数给内容组件(使用watch监听参数变化)
  4. 内容组件接收参数,发送请求渲染页面

接口:

  • 推荐:http://157.122.54.189:9088/videoimg/v1/videowp/featured
  • 娱乐:http://157.122.54.189:9088/videoimg/v1/videowp/category/59b25abbe7bce76bc834198a
  • 最新:http://157.122.54.189:9088/videoimg/v1/videowp/videowp(改变参数的order
  • 热门:http://157.122.54.189:9088/videoimg/v1/videowp/videowp (改变参数的order
  • 分类:http://157.122.54.189:9088/videoimg/v1/videowp/category
<view class="video_tab_content"><view v-if="current < 4"><video-main :urlobj="{url: items[current].url, params:items[current].params}"></video-main></view><view v-if="current === 4"><video-category></video-category></view>
</view>

具体哪个组件需要做分页,就在子组件内部用scroll-view标签

2. watch监听urlobj

  1. 重新发请求
  2. 在点击tab栏时重置参数(去除数组叠加)
  watch: {urlobj() {this.getVideoList()this.content = []}},

3. 跳转视频详情

  1. 在子组件缓存视频信息到全局
  2. 页面跳转
  3. 在详情页面的onLoad里拿到数据

子组件

<view class="video_item" v-for="item in content" :key="item.id" @click="goVideo(item)"><image :src="item.img" mode="aspectFill"></image>
<view>
goVideo(item){getApp().globalData.video = itemuni.navigateTo({url: '/pages/videoPlay/index'})
}

详情页面

onLoad() {console.log(getApp().globalData.video)
}

4. 视频播放页面

在这里插入图片描述

1. 让video标签铺满容器

<video :src="video.video" objectFit="fill"></video>

2. 静音功能

video标签的muted属性控制是否静音false/true

<video :src="video.video" objectFit="fill" :muted="isMuted"></video>
<view class="iconfont iconjingyin" @click="handleMute"></view>

3. 转发功能

button标签的open-type属性设置为share

<view class="iconfont iconzhuanfa"><button open-type="share" class="share"></button>
</view>
.iconzhuanfa {position: relative;.share {position: absolute;right: 0;bottom: 0;height: 80rpx;width: 80rpx;opacity: 0;}
}

4. 下载视频

  1. 先观察返回值
async downloadVideo(){const res = await uni.downloadFile({ url: this.video.video })console.log('下载临时路径', res)
}

在这里插入图片描述

async downloadVideo(){await uni.showLoading({title: '下载中'})const { tempFilePath } = (await uni.downloadFile({ url: this.video.video }))[1]await uni.saveVideoToPhotosAlbum({filePath: tempFilePath})uni.hideLoading()await uni.showToast({title: '下载成功'})
}

在这里插入图片描述

5. 背景图片使用滤镜效果

.bgImg {position: absolute;height: 100vh;width: 100vw;filter: blur(20px);z-index: -1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HttpTomcat

本节内容&#xff1a; Http协议Tomcat服务器下面开始的一系列内容都是JavaEE的内容&#xff0c;主要的内容见下图。JavaEE主要是做服务器端开发。 JavaEE全部规范&#xff1a;有13门技术&#xff0c;主要做web开发的需要学习servlet和jsp。其他技术&#xff0c;像EJB、 JNDI、J…

python---线程与进程

一 线程 1.1 概述 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流&#xff0c;一个进程中可以并发多个线程&#xff0c;每条线程并行执行不同的任务。 Threading用于提供线程相关…

javascrpt --- 使用jquery添加dom元素和Angular ng-repeat生成select性能比较

今天用两种方法实现了动态的给select添加option的功能. 第一种是用jquery. // html <select id"drag-pointList"></select> // js $(#drag-pointList).children(option).remove(); // 清空之前的option let list res.data.list ; // res是ajax请…

【C语言及程序设计】项目2-15:模块化的简单银行系统设计

问题描述&#xff1a; https://edu.csdn.net/course/play/456/4808 // 银行系统.cpp: 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <stdlib.h> #pragma warning (disable: 4996)int PassTest(); void ibalance(); void withdraw(); void de…

Android 6.0 动态权限申请

1. 概述 Android 6.0 (API 23) 之前应用的权限在安装时全部授予&#xff0c;运行时应用不再需要询问用户。在 Android 6.0 或更高版本对权限进行了分类&#xff0c;对某些涉及到用户隐私的权限可在运行时根据用户的需要动态授予。这样就不需要在安装时被强迫同意某些权限。 2. …

el-input输入金额,保留两位小数

需求&#xff1a;“只允许输入金额保留两位小数”&#xff0c;有2种实现方法 方法一&#xff08;通过正则控制&#xff09;&#xff1a; html&#xff1a; <el-inputv-model"inputTable.amount"input"formatNum(form.amount, amount)" ></el-i…

斜率DP总结

chunlvxiong的博客 T1&#xff1a;防御准备 三个月后第一次写博客&#xff0c;我们从这个题开始&#xff1a;http://www.lydsy.com/JudgeOnline/problem.php?id3156。 这道题DP方程比较好写&#xff1a;用dp[i]表示1到i全部被控制的最小代价&#xff0c;那么dp[i]min{dp[j](i-…

前端使用react-intl-universal进行国际化

一、国际化 / i18n 目前国际化&#xff0c;就是开发者写对象&#xff0c;一个key关联若干语种的翻译。相比于浏览器自带的翻译功能&#xff0c;语义更加准确。 “国际化”的简称&#xff1a;i18n&#xff08;其来源是英文单词 internationalization的首末字符i和n&#xff0c;…

2021前端面试题

基础知识与素养 JS基本功训练与思考 程序设计的渗透与应用 业务技巧的积累与训练 生产力转换 项目的组织架构 转换专业人才的全面生产力 什么样的技术水平决定了你应该学习什么样的知识与技术&#xff0c;什么样的知识与技术水平决定了你到什么样的公司&#xff0c;到什么样的公…

glog日志库使用笔记

日志能方便地诊断程序原因、统计程序运行数据&#xff0c;是大型软件系统必不可少的组件之一。glog 是google的开源日志系统&#xff0c;相比较log4系列的日志系统&#xff0c;它更加轻巧灵活。 在Github上下载glog&#xff0c;解压后用CMake生成VS2017工程&#xff08;默认生成…

elementPlus关闭弹窗,页面原先滚动条消失

一开始以为是弹窗内容超过一屏引起&#xff0c;改为一屏内也不能解决。 打开控制台&#xff0c;发现弹窗后自动给body标签加上了类el-popup-parent–hidden&#xff0c;关闭后也没去除&#xff0c;因此手动删除该类。 document.getElementsByTagName(body)[0].className ;

在Windows下如何创建虚拟环境(默认情况下)

很多小伙伴平时在使用Python的时候&#xff0c;有的项目需要使用Python2来进行开发&#xff0c;有的项目则是需要Python3来进行开发。当不清楚怎么分开环境的时候&#xff0c;此时两个环境开始打架&#xff0c;彼此傻傻分不清楚。虚拟环境作为隔离的利器应运而生&#xff0c;其…

selenium python 入门-元素定位

环境搭建 安装教程 http://www.testclass.net/selenium_python/install-selenium/ chrome浏览器 还需要下载chrome driver 把下载的chromedriver .exe放到chrome安装目录下的Application目录下和 python所在的安装目录下&#xff0c;比如我的目录是C:\Program Files (x86)\Goog…

DPDK helloworld 源码阅读

在 DPDK Programmers Guides 中的 EAL 一篇中有一个图可以很清晰地看到一个DPDK的应用程序的大致执行思路&#xff1a; 初始化检查CPU支持、微架构配置等完成后&#xff0c;执行main()函数。 第一步是 rte_eal_init()&#xff0c;核心初始化和启动。其中线程使用的是pthread库&…

看了吗网址链接

sklearn实战-乳腺癌细胞数据挖掘&#xff08;博主亲自录制视频&#xff09; https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare # -*- coding: utf-8 -*- ""&qu…

JMeter 性能测试进阶实战

课程简介 本课程制作的主要目的是为了让大家快速上手 JMeter&#xff0c;期间穿插了大量主流项目中用到的技术&#xff0c;以及结合当今主流微服务技术提供了测试 Dubbo 接口、Java 工程技术具体实施方案&#xff0c;注重实践、注意引导测试思维、拒绝枯燥的知识点罗列、善于用…

JavaScript高级程序设计阅读笔记

2020-11-15 通过初始化指定变量类型 数字-1 对象null和null的比较&#xff08;不理解&#xff09;使用局部变量将属性查找替换为值查找&#xff08;算法复杂度&#xff09;循环的减值迭代&#xff0c;降低了计算终止条件的复杂度switch快多个变量声明逗号隔开使用数组和对象字面…

windows任务计划程序 坑

转载于:https://www.cnblogs.com/kaibindirver/p/8109041.html

javascript --- 类、class、事件委托的编程风格

类风格: // 父类 function Widget(width, height) {this.width width || 50;this.height height || 50;this.$elem null; } Widget.prototype.render function($where) {if(this.$elem) {this.$elem.css({width: this.width "px",height: this.height "p…

堆和堆排序

堆和优先队列 普通队列&#xff1a;FIFO&#xff0c;LILO 优先队列&#xff1a;出队顺序和入队顺序无关&#xff0c;和优先级相关。一个典型应用就是操作系统中。动态选择优先级高的任务执行 堆的实现 最典型的堆就是二叉堆&#xff0c;就像是一颗二叉树。这个堆的特点&#xf…