uniapp笔记

属性用于设置组件是否被压缩

全局样式引入和底部导航栏开发

App.vue引入全局样式

App.vue是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件,App.vue本身不是页面、不能编写视图元素。

这个文件的作用包括:调用应用生命周期函数、配置全局样式、配置全局的存储globalData。

调用生命周期函数可以实现很多在特定的生命周期需要执行的动作,如在onLaunch时可以进行检测更新、网络监听、初始化数据等,onHide可用于应用运行到后台时暂停音乐、视频的播放。

该文件中可以引入样式、图标和动画等。

引入官方CSS样式库

项目目录下有common目录,下有uni.css文件,即为官方CSS样式库

static目录下的uni.ttf字体文件

App.vue文件中导入uni.css

引入自定义图标库

引入的图标主要是引入iconfont(https://www.iconfont.cn/)提供的图标。

解压下载的压缩包,将其中的iconfont.css拷贝到common目录下,并改名为icon.css,并修改其中的内容,删除对其他平台的兼容,只保留base64的图片即可

引入CSS动画库

动画库可以选择使用animate.csshttps://animate.style/)。

复制到common目录,再在App.vue中导入

<style>     
     /*每个页面公共css */     
     /* 官方CSS库 */   
     @import url("./common/uni.css");   
     /* 自定义图标库 */   
     @import url("./common/icon.css");  
     /* 动画库 */  
     @import url("./common/animate.css"); 
</style>

pages.json设置

全局属性globalStyle

pages.json文件用来对 uni-app 进行全局配置,定义页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等

uni-app项目中App.vue是程序的入口文件,可以导入CSS样式、第三方的图标和动画库,从而加速开发;pages.json文件用于配置页面文件的路径、窗口样式和底部原生tabbar等,全局样式globalStyle也在该文件中配置;实现了项目的社区、动态、消息和我的4个模块的导航栏设置。

tabbar

"tabBar": {
        "color":"#323232",
        "selectedColor":"#ED6384",
        "backgroundColor":"#FFFFFF",
        "borderStyle": "black",
        "list": [
            {
                "pagePath": "pages/index/index",
                "text": "首页",
                "iconPath": "static/tabbar/index.png",
                "selectedIconPath": "static/tabbar/indexed.png"
            },
            {
                "pagePath": "pages/news/news",
                "text": "动态",
                "iconPath": "static/tabbar/news.png",
                "selectedIconPath": "static/tabbar/newsed.png"
            },
            {
                "pagePath": "pages/msg/msg",
                "text": "消息",
                "iconPath": "static/tabbar/paper.png",
                "selectedIconPath": "static/tabbar/papered.png"
            },
            {
                "pagePath": "pages/my/my",
                "text": "我的",
                "iconPath": "static/tabbar/home.png",
                "selectedIconPath": "static/tabbar/homed.png"
            }
        ]
    }

“navigationStyle”: “custom” 隐藏小程序原生nav

image-20240401151747745

app-plus

配置编译到 App 平台时的特定样式,部分常用配置 H5 平台也支持,适用App、H5

"app-plus": {
                    // 导航栏配置
                    "titleNView": {
                        // 搜索框配置
                        "searchInput": {
                            "align":"center",
                            "backgroundColor":"#F5F4F2",
                            "borderRadius":"4px",
                            "disabled": true,
                            "placeholder": "搜索帖子",
                            "placeholderColor": "#6D6C67"
                        },
                        // 按钮设置
                        "buttons": [
                            {
                                "color":"#333333",
                                "colorPressed":"#FD597C",
                                "float":"right",
                                "fontSize":"20px",
                                "fontSrc":"/static/iconfont.ttf",
                                "text": "\ue668"
                            }
                        ]
                    }
                }

Vue.js和uni-app基础

数据渲染和动态绑定

数据渲染

数据渲染需要使用Vue中的语法,数据定义在script语句块中的data属性中,并提倡以函数的形式返回,在页面中用{{}}包含,即可渲染数据。数据可以是字符串、数值型、对象等。

class和style绑定

修改class来改变样式,要动态改变组件的属性时,属性前加v-bind::,例如v-bind:class:class

实现动态修改class和style属性

<template>
    <view>
        <view class="box" :class="{'bor':isBor, 'fs': isFs}">
            box
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                cls1: 'bor',
                cls2: 'fs',
                age: 18,
                gender: 'male',
                isBor: true,
                isFs: true
            }
        },
        methods: {

        }
    }
</script>

<style>
    .box {
        width: 400upx;
        height: 400upx;
        border-radius: 100%;
        background: #00FF7F;
        font-size: 50upx;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    .bor {
        border: 10upx solid #007AFF;
    }
    .fs{
        font-size: 70upx;
        color: #8A6DE9;
    }
</style>
```vue
<template>
    <view>
        <view class="box" :style="{'color': color, 'font-size': size+'px'}">
            box
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                color: '#333333',
                size: 50
            }
        },
        methods: {

        }
    }
</script>

<style>
    .box {
        width: 400upx;
        height: 400upx;
        border-radius: 100%;
        background: #00FF7F;
        font-size: 50upx;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>

条件渲染

条件渲染也是使用Vue中的v-if实现。

v-if的既可以是布尔值变量,也可以是逻辑表达式,同时可以动态渲染

v-show也能实现条件显示,满足条件再显示

v-if是真正的条件渲染,满足条件才进行渲染;

v-show是不管是否条件成立都会渲染元素,符合条件就显示,不符合条件就相当于设置display属性为none,即将元素隐藏。

两者的进一步比较可参考https://blog.csdn.net/happy81997/article/details/106135153

还可以嵌套<template/><block/>,来实现列表渲染和条件渲染。

<template/><block/>并不是组件,它们仅仅是包装元素,不会在页面中做任何渲染,只接受控制属性。

可以参考文档https://uniapp.dcloud.io/frame?id=template-block

列表渲染

使用v-for实现列表渲染,可以对数组或对象进行遍历。 可查看文档https://uniapp.dcloud.io/use?id=列表渲染

为了指定列表中项目的唯一的标识符,一般会指定:key属性。

可以列表和对象多层嵌套

<template>
    <view>
        <view class="ls" v-for="(val, index) in list3" :key="index">
            <view class="ls">{{index}}:{{val.province}}</view>
            <view v-for="(v, i) in val.city" :key="i">{{i}}-{{v}}</view>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                list1: ['Basketball', 'Football', 'Ping-Pong'],
                list2: [{
                        'name': 'Basketball',
                        'count': 3
                    },
                    {
                        'name': 'Football',
                        'count': 5
                    },
                    {
                        'name': 'Ping-Pong',
                        'count': 8
                    },
                ],
                list3: [
                    {
                        province: '广东',
                        city: ['广州', '深圳', '佛山']
                    },
                    {
                        province: '四川',
                        city: ['成都', '绵阳', '宜宾']
                    }
                ]
            }
        },
        methods: {

        }
    }
</script>

<style>
    .ls {
        font-size: 50upx;
    }
</style>

事件和属性处理

事件处理器

事件处理器用于处理点击、长按、表单输入、提交表单等事件。 可参考文档https://uniapp.dcloud.io/vue-basics?id=eventhandler

@tap@click都是绑定点击事件。

实现阻止冒泡事件。给事件增加@tap.stop属性即可

监听属性

监听属性在watch属性中定义,实现与被监听的属性同名的方法,其参数值即为属性的值。

属性监听可以用于组件中实时监听某个值并通知父组件修改某个值。

<template>
    <view>
        <view class="font">{{num}}</view>
        <button type="default" @tap="changeNum()">按钮</button>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                num: 1
            }
        },
        watch: {
            num(val){
                console.log(val)
            }
        },
        methods: {
            changeNum(){
                this.num += 5;
            }
        },
    }
</script>

<style>
    .font {
        font-size: 50upx;
    }
</style>

计算属性

计算属性在computed中定义,每一个计算属性都包含一个getter和一个setter,默认是利用getter来读取。所有getter和setter的this上下文自动地绑定为 Vue 实例。 具体可参考文档https://uniapp.dcloud.io/vue-basics?id=计算属性和侦听器https://cn.vuejs.org/v2/guide/computed.html

例如,要实现区别化地显示重量,可以如下:

<template>
    <view>
        <view class="font">
            {{weight>1000?(weight/1000)+'kg':weight+'g'}}
        </view>     
        <button type="default" @tap="changeWeight()">按钮</button>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                weight: 150
            }
        },
        methods: {
            changeWeight(){
                this.weight += 300;
            }
        },
    }
</script>

<style>
    .font {
        font-size: 50upx;
    }
</style>

可以看到,达到了目标,但是页面中有过多的计算代码,不利于维护,此时就可以使用计算属性

<template>
    <view>
        <view class="font">
            {{transWeight}}
        </view>     
        <button type="default" @tap="changeWeight()">按钮</button>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                weight: 150
            }
        },
        computed: {
            transWeight(){
                return this.weight>1000?(this.weight/1000)+'kg':this.weight+'g';
            }
        },
        methods: {
            changeWeight(){
                this.weight += 300;
            }
        },
    }
</script>

<style>
    .font {
        font-size: 50upx;
    }
</style>

uni-app 支持的通用 css 单位

包括 px、rpx:

  • px 即屏幕像素。
  • rpx 即响应式px,一种根据屏幕宽度自适应的动态单位。以750宽的屏幕为基准,750rpx恰好为屏幕宽度。

开发者可以通过设计稿基准宽度计算页面元素 rpx 值,

设计稿 1px 与框架样式 1rpx 转换公式为设计稿 1px / 设计稿基准宽度 = 框架样式 1rpx / 750rpx

所以页面元素宽度在 uni-app 中的宽度计算公式为750 * 元素在设计稿中的宽度 / 设计稿基准宽度。 更多可参考https://uniapp.dcloud.io/frame?id=尺寸单位。

封装样式组件

common下新建文件base.css,保存公共样式。base.css文件不仅可以应用于该项目,也可以应用于其他uni-app项目。

common.css保存本项目全局样式

App.vue中导入CSS文件

<style>
    /*每个页面公共css */
    /* 官方CSS库 */
    @import url("./common/uni.css");
    /* 自定义图标库 */
    @import url("./common/icon.css");
    /* 动画库 */
    @import url("./common/animate.css");
    /* 自定义样式库 */
    @import url("./common/base.css");
    /* 全局样式 */
    @import url("./common/common.css");
</style>

将列表项封装为组件

项目下新建components目录,下新建common目录,下建common-list.vue作为列表组件

<template>
    <view class="p-2">
        <!-- 头像、昵称和关注按钮 -->
        <view class="flex align-center justify-between">
            <view class="flex align-center">
                <!-- 头像 -->
                <image class="rounded-circle mr-2" :src="item.userpic" mode="" style="width: 65rpx; height: 65rpx;"
                 lazy-load></image>
                <!-- 昵称和发布时间 -->
                <view>
                    <view class="font" style="line-height: 1.5;">{{item.username}}</view>
                    <text class="font-sm text-light-muted" style="line-height: 1.5;">{{item.newstime}}</text>
                </view>
            </view>
            <!-- 按钮 -->
            <view class="flex align-center justify-center rounded bg-main text-white" style="width: 90rpx; height: 50rpx;">
                {{item.isFollow?'已关注':'关注'}}
            </view>
        </view>
        <!-- 标题 -->
        <view class="font my-1">
            {{item.title}}
        </view>
        <!-- 图片 -->
        <image class="rounded w-100" :src="item.titlepic" style="height: 350rpx;"></image>
        <!-- 图标按钮 -->
        <view class="flex align-center">
            <view class="flex align-center justify-center flex-1">
                <text class="iconfont icon-dianzan mr-2"></text>
                <text>{{item.support.support_count}}</text>
            </view>
            <view class="flex align-center justify-center flex-1">
                <text class="iconfont icon-cai mr-2"></text>
                <text>{{item.support.unsupport_count}}</text>
            </view>
            <view class="flex align-center justify-center flex-1">
                <text class="iconfont icon-pinglun mr-2"></text>
                <text>{{item.comment_count}}</text>
            </view>
            <view class="flex align-center justify-center flex-1">
                <text class="iconfont icon-fenxiang mr-2"></text>
                <text>{{item.share_count}}</text>
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        props: {
            item: Object,
            index: Number
        },
    }
</script>

<style>
</style>

`index.vue中导入并使用组件即可,如下:

<template>
    <view>
        <block v-for="(item, index) in list" :key="index">
            <!-- 列表 -->
            <common-list :item="item" :index="index"></common-list>
        </block>

    </view>
</template>

<script>
    import commonList from '@/components/common/common-list.vue';
    export default {
        data() {
            return {
                list: [
                    {
                        username: "Corley",
                        userpic: "/static/img/userpic/12.jpg",
                        newstime: "2021-01-24 上午11:30",
                        isFollow: false,
                        title: "uni-app入门教程",
                        titlepic: "/static/img/datapic/42.jpg",
                        support: {
                            type: "support",
                            support_count: 1,
                            unsupport_count: 2
                        },
                        comment_count: 2,
                        share_count: 2
                    },
                    {
                        username: "Ashley",
                        userpic: "/static/img/userpic/20.jpg",
                        newstime: "2021-01-24 下午14:00",
                        isFollow: true,
                        title: "uni-app实战之社区交友APP",
                        titlepic: "/static/img/datapic/30.jpg",
                        support: {
                            type: "support",
                            support_count: 5,
                            unsupport_count: 1
                        },
                        comment_count: 3,
                        share_count: 0
                    }
                ]
            }
        },
        components: {
            commonList
        },
        onLoad() {

        },
        methods: {

        }
    }
</script>

<style>

</style>

全局分割线

局分割线也是以组件的形式添加。 先在components/common下新建divider.vue如下:

<template>
    <view style="height: 15rpx; background-color: #F5F5F4;"></view>
</template>

<script>
</script>

<style>
</style>

因为分割线可能在很多地方都会用到,所以可以添加到全局组件,main.js中添加如下:

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false

// 引入全局组件
import divider from './components/common/divider.vue';
Vue.component('divider', divider)

App.mpType = 'app'

const app = new Vue({
    ...App
})
app.$mount()

index.vue中无需导入、直接使用即可,如下:

<template>
    <view>
        <block v-for="(item, index) in list" :key="index">
            <!-- 列表 -->
            <common-list :item="item" :index="index"></common-list>
            <!-- 全局分割线 -->
            <divider></divider>
        </block>

    </view>
</template>

帖子没有封面图,因此需要v-if进行判断显示隐藏

<!-- 图片 -->
        <image v-if="item.titlepic" class="rounded w-100" :src="item.titlepic" style="height: 350rpx;"></image>

关注 踩 横向滚动选项卡 选项卡与列表同步切换 切换监听 上拉加载数据

methods: {
            // 关注
            follow(e) {
                console.log('Index followed');
                console.log(e);
                this.list[e].isFollow = true;
                uni.showToast({
                    title: '关注' + this.list[e].username + '成功'
                })
            },
            // 顶踩操作
            doSupport(e) {
                console.log(e);
                // 获取当前列表项
                let item = this.list[e.index];
                let msg = e.type === 'support' ? '顶' : '踩';
                // 之前未顶踩过
                if (item.support.type === '') {
                    item.support[e.type + '_count']++;
                }
                // 之前已顶过并且现在的操作为踩,则顶-1、踩+1
                else if (item.support.type === 'support' && e.type === 'unsupport') {
                    item.support.support_count--;
                    item.support.unsupport_count++;
                }
                // 之前已踩过并且现在的操作为顶,则踩-1、顶+1
                else if (item.support.type === 'unsupport' && e.type === 'support') {
                    item.support.unsupport_count--;
                    item.support.support_count++;
                }
                item.support.type = e.type;
                uni.showToast({
                    title: msg + '成功'
                })
            },
            // 切换选项
            changeTab(index) {
                if (this.tabIndex === index) {
                    return;
                }
                this.tabIndex = index;
                // 滚动到指定元素
                this.scrollInto = 'tab' + index;
            },
            // 监听滑动
            onChangeTab(e) {
                console.log(e);
                this.changeTab(e.detail.current);
            },

            // 上拉加载更多
            loadMore(index) {
                // 获取当前列表
                let item = this.newsList[index];
                // 判断是否处于可加载状态
                if (item.loadmore !== '上拉加载更多') return;
                // 修改当前列表加载状态
                item.loadmore = '加载中...';
                // 模拟数据请求
                setTimeout(() => {
                    // 加载数据
                    item.list = [...item.list, ...item.list];
                    // 恢复加载状态
                    this.newsList[index].loadmore = '上拉加载更多';
                }, 2000)
            }
        }

组件封装和CSS样式提取等,有利于项目的维护和扩展。

搜索组件

<uni-search-bar @confirm="search" :focus="true" v-model="searchValue" @blur="blur" @focus="focus" @input="input" @cancel="cancel" @clear="clear">
</uni-search-bar>

| 事件称名 | 说明 | 返回参数 |
| :——: | :———————————————————-: | :————–: |
| @confirm | uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value | e={value:Number} |
| @input | uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value | e=value |
| @cancel | 点击取消按钮时触发事件,返回参数为uniSearchBar的value | e={value:Number} |
| @clear | 点击清除按钮时触发事件,返回参数为uniSearchBar的value | e={value:Number} |
| @focus | input 获取焦点时触发事件,返回参数为uniSearchBar的value | e={value:Number} |
| @blur | input 失去焦点时触发事件,返回参数为uniSearchBar的value | e={value:Number} |

多图上传功能

uni-app官方模板hello_uniapp项目提供了多图上传接口,位于pages/API/image目录下,image.vue

<template>
    <view class="px-2">
        <view class="uni-uploader" v-if="show">
            <view class="uni-uploader-head">
                <view class="uni-uploader-title">点击预览</view>
                <view class="uni-uploader-info">{{imageList.length}}/9</view>
            </view>
            <view class="uni-uploader-body">
                <view class="uni-uploader__files">
                    <block v-for="(image,index) in imageList" :key="index">
                        <view class="uni-uploader__file position-relative">
                            <image class="uni-uploader__img rounded" :src="image" :data-src="image" mode="aspectFill"
                                @tap="previewImage"></image>
                            <view class="position-absolute top-0 right-0 rounded"
                                style="padding: 0 15rpx; background-color: rgba(0, 0, 0, 0.5);"
                                @click.stop="deleteImage(index)">
                                <text class="iconfont tn-icon-delete text-white"></text>
                            </view>
                        </view>
                    </block>
                    <view class="uni-uploader__input-box rounded">
                        <view class="uni-uploader__input" @tap="chooseImage"></view>
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>
<script>
    import permision from "@/common/permission.js"
    var sourceType = [
        ['camera'],
        ['album'],
        ['camera', 'album']
    ]
    var sizeType = [
        ['compressed'],
        ['original'],
        ['compressed', 'original']
    ]
    export default {
        props: {
            list: Array,
            show: {
                type: Boolean,
                default: true
            }
        },
        data() {
            return {
                title: 'choose/previewImage',
                imageList: [],
                sourceTypeIndex: 2,
                sourceType: ['拍照', '相册', '拍照或相册'],
                sizeTypeIndex: 2,
                sizeType: ['压缩', '原图', '压缩或原图'],
                countIndex: 8,
                count: [1, 2, 3, 4, 5, 6, 7, 8, 9]
            }
        },
        onUnload() {
            this.imageList = [],
                this.sourceTypeIndex = 2,
                this.sourceType = ['拍照', '相册', '拍照或相册'],
                this.sizeTypeIndex = 2,
                this.sizeType = ['压缩', '原图', '压缩或原图'],
                this.countIndex = 8;
        },
        mounted() {
            console.log(this.list);
            this.imageList = this.list;
        },
        methods: {
            chooseImage: async function() {
                // #ifdef APP-PLUS
                // TODO 选择相机或相册时 需要弹出actionsheet,目前无法获得是相机还是相册,在失败回调中处理
                if (this.sourceTypeIndex !== 2) {
                    let status = await this.checkPermission();
                    if (status !== 1) {
                        return;
                    }
                }
                // #endif

                if (this.imageList.length === 9) {
                    let isContinue = await this.isFullImg();
                    console.log("是否继续?", isContinue);
                    if (!isContinue) {
                        return;
                    }
                }
                uni.chooseImage({
                    sourceType: sourceType[this.sourceTypeIndex],
                    sizeType: sizeType[this.sizeTypeIndex],
                    count: this.imageList.length + this.count[this.countIndex] > 9 ? 9 - this.imageList
                        .length : this.count[this.countIndex],
                    success: (res) => {
                        this.imageList = this.imageList.concat(res.tempFilePaths);
                        this.$emit('change', this.imageList);
                    },
                    fail: (err) => {
                        // #ifdef APP-PLUS
                        if (err['code'] && err.code !== 0 && this.sourceTypeIndex === 2) {
                            this.checkPermission(err.code);
                        }
                        // #endif
                        // #ifdef MP
                        uni.getSetting({
                            success: (res) => {
                                let authStatus = false;
                                switch (this.sourceTypeIndex) {
                                    case 0:
                                        authStatus = res.authSetting['scope.camera'];
                                        break;
                                    case 1:
                                        authStatus = res.authSetting['scope.album'];
                                        break;
                                    case 2:
                                        authStatus = res.authSetting['scope.album'] && res
                                            .authSetting['scope.camera'];
                                        break;
                                    default:
                                        break;
                                }
                                if (!authStatus) {
                                    uni.showModal({
                                        title: '授权失败',
                                        content: '需要从您的相机或相册获取图片,请在设置界面打开相关权限',
                                        success: (res) => {
                                            if (res.confirm) {
                                                uni.openSetting()
                                            }
                                        }
                                    })
                                }
                            }
                        })
                        // #endif
                    }
                })
            },
            isFullImg: function() {
                return new Promise((res) => {
                    uni.showModal({
                        content: "已经有9张图片了,是否清空现有图片?",
                        success: (e) => {
                            if (e.confirm) {
                                this.imageList = [];
                                res(true);
                            } else {
                                res(false)
                            }
                        },
                        fail: () => {
                            res(false)
                        }
                    })
                })
            },
            previewImage: function(e) {
                var current = e.target.dataset.src
                uni.previewImage({
                    current: current,
                    urls: this.imageList
                })
            },
            async checkPermission(code) {
                let type = code ? code - 1 : this.sourceTypeIndex;
                let status = permision.isIOS ? await permision.requestIOS(sourceType[type][0]) :
                    await permision.requestAndroid(type === 0 ? 'android.permission.CAMERA' :
                        'android.permission.READ_EXTERNAL_STORAGE');

                if (status === null || status === 1) {
                    status = 1;
                } else {
                    uni.showModal({
                        content: "没有开启权限",
                        confirmText: "设置",
                        success: function(res) {
                            if (res.confirm) {
                                permision.gotoAppSetting();
                            }
                        }
                    })
                }

                return status;
            },
            deleteImage(index) {
                uni.showModal({
                    title: '删除提示',
                    content: '是否要删除该图片?',
                    showCancel: true,
                    cancelText: '不删除',
                    confirmText: '删除',
                    success: res => {
                        if (res.confirm) {
                            this.imageList.splice(index, 1);
                            this.$emit('change', this.imageList);
                        }
                    },
                    fail: () => {},
                    complete: () => {}
                });
            }
        }
    }
</script>

<style>
    .cell-pd {
        padding: 22rpx 30rpx;
    }

    .list-pd {
        margin-top: 50rpx;
    }
</style>

组件引用

<template>
    <view>

        <!-- 文本域组件 -->
        <textarea v-model="content" placeholder="说一句话吧~" class="uni-textarea px-2" />
        <!-- 多图上传 -->
        <upload-image :show="show" ref="uploadImage" :list='imageList' @change="changeImage"></upload-image>
        <!-- 底部操作条 -->
        <view class="fixed-bottom bg-white flex align-center" style="height: 85rpx;">
            <view class="iconfont tn-icon-topic footer-btn animate__animated" hover-class="animate__jello"></view>
            <view class="iconfont tn-icon-image footer-btn animate__animated" hover-class="animate__jello"
                @click="iconClickEvent('uploadImage')"></view>

            <view class="bg-main text-white ml-auto flex align-center justify-center rounded mr-2 animate__animated"
                hover-class="animate__jello" style="width: 140rpx; height: 60rpx;">发送</view>
        </view>
    </view>
</template>

<script>
    import uploadImage from '@/components/common/unpload-image.vue';
    export default {
        data() {
            return {
                content: '',
                imageList: [],
                // 是否已经弹出提示框
                showBack: false
            }
        },
        components: {
            uploadImage
        },
        computed: {
            show() {
                return this.imageList.length > 0;
            }
        },
        // app h5监听返回
        onBackPress() {
            if ((this.content !== '' || this.imageList.length > 0) && !this.showBack) {
                uni.showModal({
                    title: '返回提示',
                    content: '是否要保存为草稿?',
                    showCancel: true,
                    cancelText: '不保存',
                    confirmText: '保存',
                    success: res => {
                        // 点击确认
                        if (res.confirm) {
                            this.store();
                        }
                        // 点击取消
                        else {
                            uni.removeStorage({
                                key: 'add-input'
                            });
                        }

                        // 手动执行返回
                        uni.navigateBack({
                            delta: 1
                        });
                    }
                });
                this.showBack = true;
                return true;
            }
        },
        onUnload() {
            if ((this.content !== '' || this.imageList.length > 0) && !this.showBack) {
                uni.showModal({
                    title: '返回提示',
                    content: '是否要保存为草稿?',
                    showCancel: true,
                    cancelText: '不保存',
                    confirmText: '保存',
                    success: res => {
                        // 点击确认
                        if (res.confirm) {
                            this.store();
                        }
                        // 点击取消
                        else {
                            uni.removeStorage({
                                key: 'add-input'
                            });
                        }

                        // 手动执行返回
                        uni.navigateBack({
                            delta: 1
                        });
                    }
                });
                this.showBack = true;
                return true;
            }
        },
        onLoad() {
            uni.getStorage({
                key: 'add-input',
                success: (res) => {
                    console.log(res);
                    if (res.data) {
                        let result = JSON.parse(res.data);
                        this.content = result.content;
                        this.imageList = result.imageList;
                    }
                }
            })
        },
        methods: {
            changeImage(e) {
                console.log(e);
                this.imageList = e;
            }, // 保存草稿
            store() {
                let obj = {
                    content: this.content,
                    imageList: this.imageList
                };
                // 保存为本地存储
                uni.setStorage({
                    key: 'add-input',
                    data: JSON.stringify(obj),

                })
                console.log(JSON.stringify(obj)+"aaaaaaaaaaa")
            },
            // 返回上一步
            goBack() {
                uni.navigateBack({
                    delta: 1
                })
            },
            // 底部图标点击事件
            iconClickEvent(e) {
                switch (e) {
                    case 'uploadImage':
                        this.$refs.uploadImage.chooseImage();
                        break;
                }
            }
        }
    }
</script>

<style>
    .footer-btn {
        width: 86rpx;
        height: 86rpx;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 50rpx;
    }
</style>