uniapp

发布于:2025-07-18 ⋅ 阅读:(22) ⋅ 点赞:(0)

官方文档:uni-app官网

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发一套代码,可以在h5端、app端、小程序端同时使用。

开发一套代码,在微信小程序运行、h5端口、app端(手机模拟器 夜神模拟器)。

uniapp全局配置

index.html

App.vue

main.js

pages.json

globalStyle Object  否   设置默认页面的窗口表现 
pages   Object Array    是   设置页面路径及窗口表现 
easycom Object  否   组件自动引入规则    2.5.5+
tabBar  Object  否   设置底部 tab 的表现  

组件

1、内置组件

视图容器组件:view scroll-view swiper swiper-item

基础内容组件: icon text rich-text

表单组件:form input radio buttom checkbox switch textarea

媒体组件:image radio audio

路由跳转组件:navigator openType="navigate|redirect|switchTab|navigateBack"

map地图

2、扩展 组件 uni-ui

3、第三方组件库 uview-ui 秋云-ucharts (插件市场 )

uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架

scss语法(了解)

<template>
    <view class="outer">
        <view class="c1">
            <view class="c11">c1-->c11</view>
        </view>
        <view class="c2">
            <view class="c11">c2-->c11</view>
        </view>
    </view>
</template>
​
<script>
    export default {
        data() {
            return {
                
            }
        },
        methods: {
            
        }
    }
</script>
​
<style lang="scss">
    /* css选择器
     id #
     标签  标签名
     类选择  .
     属性选择器  [name='admin']
     子元素  >
     子孙元素  空格
     通配  *
     */
    // .c2{
    //  background-color: gray;
    //  height: 150px;
    // }
    // .c2>.c11{
    //  background-color: gold;
    //  height: 100px;
    // }
    .c1{
        .c11{
            background-color: red;
            height: 100px;
        }
    }
    .c2{
        background-color: gray;
        height: 150px;
        .c11{
            background-color: gold;
            height: 100px;
        }
    }
    
</style>
​

vue2语法(熟悉)

<template>
    <view class="container">
        
         {{id}}
         <button @click="m1()">++</button>
         <button @tap="m1()">++</button>
    </view>
</template>
​
<script>
    export default {
        data() {
            return {
                id:1,
                href: 'https://uniapp.dcloud.io/component/README?id=uniui'
            }
        },
        methods: {
            m1(){
                console.log("-----m1-----");
                this.id = ++this.id;
            },
            m2(){
                console.log("=====m2====");
            }
        },
        mounted() {
            this.m1();
        }
    }
</script>
​
<style>
    .container {
        padding: 20px;
        font-size: 14px;
        line-height: 24px;
    }
</style>

一、常见的事件类型

‌@click‌

用于处理用户点击操作。 可以绑定在按钮、列表项等元素上,当用户点击时触发相应的逻辑处理。 是标准的HTML DOM事件,在浏览器中通用。

‌@tap‌

也是用于处理用户点击事件。 是小程序和移动端框架(如微信、uni-app)封装的事件,专为触摸交互优化。 在移动端,由于浏览器的click延迟可能会导致用户体验卡顿,而@tap通过原生触摸事件(touchstart/touchend)实现即时响应。 在H5端,@tap会被编译为click(但通过触摸事件模拟,无延迟);在小程序/App端,@tap直接调用原生触摸事件;在PC端可能无效,需用@click。

‌@longpress‌ 和 ‌@longtap‌

用于处理长按操作。 可以绑定在需要长按触发逻辑的元素上,例如长按显示气泡框、长按删除等操作。 这两个事件在功能上相似,但具体实现和触发条件可能略有不同,具体使用哪个事件取决于你的应用需求和uniapp的版本。

‌其他手势事件‌: ‌@touchstart‌:手指触摸动作开始。 ‌@touchmove‌:手指触摸后移动。 ‌@touchcancel‌:手指触摸被打断,如来电提醒、弹窗。 ‌@touchend‌:手指触摸动作结束,如松开按钮。 这些事件为开发者提供了丰富的用户交互手段,可以根据实际需求选择合适的事件来处理用户交互和页面逻辑。

二、api

1、发起网络请求

uni.request

2、页面跳转的

uni.redirectTo

uni.naviateTo

uni.switchTab

uni.navigateBack

uni.relaunch

3、界面交互api

弹出框

uni.showToast uni.HideToast

uni.showLoading uni.HideLoading

4、定时任务

setTimeout

三、完整模块的api

列表查询

<template>
    <view>
        <view class="u-page">
            <u-list>
              <u-list-item v-for="(item, index) in indexList" :key="index">
                <u-cell :title="item.channelName">
                  <u-avatar
                    slot="icon"
                    shape="square"
                    size="35"
                    :src="item.userImg"
                    customStyle="margin: -3px 5px -3px 0"
                  ></u-avatar>
                </u-cell>
              </u-list-item>
            </u-list>
          </view>
    </view>
</template>
​
<script>
    export default {
        data() {
            return {
                indexList:[]
            }
        },
        methods: {
            loadChannel(){
                //发起网络请求,查询数据
                uni.request({
                    url:"http://localhost:8080/system/channels/list",
                    method:"GET",
                    header: {
                        'authorization': 'Bearer '+uni.getStorageSync('token')
                    },
                    data:{
                        pageNum:1,
                        pageSize:10,
                    },
                    success: (res) => {
                        console.log(res.data);
                        this.indexList = res.data.rows;
                    }
                })
            }
        },
        onLoad() {
            this.loadChannel();
        }
    }
</script>
​
<style>
​
</style>
​

封装request.js

1. 创建环境配置文件

在项目根目录创建 config/env.js,管理不同环境的 URL:

// config/env.js
const ENV = process.env.NODE_ENV || 'development'; // 获取当前环境
​
const envConfig = {
  development: { // 开发环境
    BASE_API: 'http://dev.api.example.com',
    STATIC_URL: 'http://dev.static.example.com'
  },
  production: { // 生产环境
    BASE_API: 'https://api.example.com',
    STATIC_URL: 'https://static.example.com'
  },
  // 其他环境(如测试环境)
  test: {
    BASE_API: 'http://test.api.example.com',
    STATIC_URL: 'http://test.static.example.com'
  }
};
​
// 导出当前环境配置
export default envConfig[ENV];

2. 封装全局请求工具

创建 utils/request.js,实现以下功能:

  • 自动拼接基础 URL

  • 拦截请求/响应

  • 统一错误处理

  • 自动携带 Token

// utils/request.js
import env from '@/config/env'; // 引入环境配置
​
/**
 * 封装 uni.request
 * @param {Object} options 请求配置
 */
const request = (options) => {
  // 1. 处理请求 URL(拼接环境变量中的 BASE_API)
  if (!options.url.startsWith('http')) {
    options.url = env.BASE_API + options.url;
  }
​
  // 2. 默认请求配置
  const defaultOptions = {
    method: 'POST',
    header: {
      'Content-Type': 'application/json',
      'Authorization': uni.getStorageSync('token') || '' // 自动携带 Token
    }
  };
​
  // 3. 合并配置
  options = { ...defaultOptions, ...options };
​
  // 4. 返回 Promise
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success: (res) => {
        // 5. 统一处理 HTTP 状态码
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve(res.data); // 请求成功
        } else if (res.statusCode === 401) {
          // Token 过期处理
          uni.navigateTo({ url: '/pages/login/login' });
          reject(new Error('未登录或登录已过期'));
        } else {
          reject(res.data); // 其他错误
        }
      },
      fail: (err) => {
        // 6. 网络错误处理
        uni.showToast({ title: '网络错误', icon: 'none' });
        reject(err);
      }
    });
  });
};
​
// 7. 快捷方法封装(GET/POST/PUT/DELETE)
export const get = (url, data, options = {}) => {
  return request({ url, data, method: 'GET', ...options });
};
​
export const post = (url, data, options = {}) => {
  return request({ url, data, method: 'POST', ...options });
};
​
export default request;

3. 实际使用示例

import { get, post } from '@/utils/request';
​
export default {
  methods: {
    // GET 请求
    async fetchData() {
      try {
        const res = await get('/user/info', { id: 123 });
        console.log(res);
      } catch (err) {
        console.error(err);
      }
    },
​
    // POST 请求
    async submitForm() {
      try {
        const res = await post('/user/login', {
          username: 'admin',
          password: '123456'
        });
        console.log(res);
      } catch (err) {
        console.error(err);
      }
    }
  }
};

4、普通表单新增

<template>
    <view>
        <uni-forms ref="form" :modelValue="formData" :rules="rules">
            <uni-forms-item label="渠道名称" name="channelName">
                <uni-easyinput type="text" v-model="formData.channelName" placeholder="请输入渠道名称" />
            </uni-forms-item>
            <uni-forms-item label="渠道编码" name="channelCode">
                <uni-easyinput type="text" v-model="formData.channelCode" placeholder="请输入渠道名称" />
            </uni-forms-item>
​
        </uni-forms>
        <button @click="submit">Submit</button>
    </view>
</template>
​
<script>
    import {
        get,
        post
    } from '@/utils/request';
    export default {
        data() {
            return {
                // 表单数据
                formData: {
                    channelName: '平安好卫士',
                    channelCode: 'pyhws'
                },
                rules: {
                    // 对name字段进行必填验证
                    channelName: {
                        rules: [{
                                required: true,
                                errorMessage: '请输入渠道名',
                            },
                            {
                                minLength: 3,
                                maxLength: 5,
                                errorMessage: '长度在 {minLength} 到 {maxLength} 个字符',
                            }
                        ]
                    },
                    // 对code字段进行必填验证
                    channelCode: {
                        rules: [{
                            required: true,
                            errorMessage: '请输入渠道编码',
                        }]
                    }
                }
            }
        },
        methods: {
            async loadChannel() {
                const resp = await get('/system/channels/list', {});
                console.log(resp);
            },
            async submit() {
                const validate = await this.$refs.form.validate();
                console.log('表单数据信息:', validate);
                //接收数据
                console.log(this.formData);
                //发起网路请求
                const resp = await post('/system/channels', this.formData);
                console.log(resp, "新增结果");
                if (resp.code == 200) { //成功
                    //跳转到列表查询
                    uni.navigateTo({
                        url: "/pages/channel/channel"
                    })
                } else {
                    console.log("新增失败");
                }
            }
        },
        onLoad() {
            this.loadChannel();
        }
    }
</script>
​
<style>
</style>

5、文件上传+form表单

<template>
    <view>
        <uni-forms ref="form" :modelValue="formData" :rules="rules">
            <uni-forms-item label="渠道名称" name="channelName">
                <uni-easyinput type="text" v-model="formData.channelName" placeholder="请输入渠道名称" />
            </uni-forms-item>
            <uni-forms-item label="渠道编码" name="channelCode">
                <uni-easyinput type="text" v-model="formData.channelCode" placeholder="请输入渠道名称" />
            </uni-forms-item>
            <uni-forms-item label="选择图片" name="userImg">
                <u-upload :fileList="fileList1" @afterRead="afterRead" @delete="deletePic" name="1" multiple
                    :maxCount="10"></u-upload>
            </uni-forms-item>
        </uni-forms>
        <button @click="submit">Submit</button>
    </view>
</template>
​
<script>
    import {
        get,
        post
    } from '@/utils/request';
    export default {
        data() {
            return {
                fileList1: [],
                // 表单数据
                formData: {
                    channelName: '平安好卫士',
                    channelCode: 'pyhws'
                },
                rules: {
                    // 对name字段进行必填验证
                    channelName: {
                        rules: [{
                                required: true,
                                errorMessage: '请输入渠道名',
                            },
                            {
                                minLength: 3,
                                maxLength: 5,
                                errorMessage: '长度在 {minLength} 到 {maxLength} 个字符',
                            }
                        ]
                    },
                    // 对code字段进行必填验证
                    channelCode: {
                        rules: [{
                            required: true,
                            errorMessage: '请输入渠道编码',
                        }]
                    }
                }
            }
        },
        methods: {
            async loadChannel() {
                //const resp = await get('/system/channels/list', {});
                //console.log(resp);
            },
            async submit() {
                const validate = await this.$refs.form.validate();
                console.log('表单数据信息:', validate);
                //接收数据
                console.log(this.formData);
                //发起网路请求
                const resp = await post('/system/channels', this.formData);
                console.log(resp, "新增结果");
                if (resp.code == 200) { //成功
                    //跳转到列表查询
                    uni.navigateTo({
                        url: "/pages/channel/channel"
                    })
                } else {
                    console.log("新增失败");
                }
​
​
​
            },
            // 删除图片
            deletePic(event) {
                this[`fileList${event.name}`].splice(event.index, 1);
            },
            // 新增图片
            async afterRead(event) {
                // 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
                let lists = [].concat(event.file);
                let fileListLen = this[`fileList${event.name}`].length;
                lists.map((item) => {
                    this[`fileList${event.name}`].push({
                        ...item,
                        status: "uploading",
                        message: "上传中",
                    });
                });
                for (let i = 0; i < lists.length; i++) {
                    const result = await this.uploadFilePromise(lists[i].url);
                    // console.log(JSON.parse(result).url,"--------");
                    // this.formData.userImg = JSON.parse(result).url;
                    let item = this[`fileList${event.name}`][fileListLen];
                    this[`fileList${event.name}`].splice(
                        fileListLen,
                        1,
                        Object.assign(item, {
                            status: "success",
                            message: "",
                            url: JSON.parse(result).url,
                        })
                    );
                    fileListLen++;
                }
                //打印输出所有的文件列表
                console.log(this.fileList1);
                //选择第一张照片,存储到数据库表
                 this.formData.userImg =  this.fileList1[0].url;
            },
            uploadFilePromise(url) {
                return new Promise((resolve, reject) => {
                    let a = uni.uploadFile({
                        url: "http://localhost:8080/common/upload", // 仅为示例,非真实的接口地址
                        filePath: url,
                        name: "file",
                        formData: {
                            user: "test",
                        },
                        header: {
                            'authorization': 'Bearer ' + uni.getStorageSync('token')
                        },
                        success: (res) => {
                            setTimeout(() => {
                                console.log(res.data, "文件上传后返回响应对象");
                                resolve(res.data);
                            }, 1000);
                        },
                    });
                });
            }
​
        },
        onLoad() {
            this.loadChannel();
        }
    }
</script>
​
<style>
</style>

6、删除

request.js

export const put = (url, data, options = {}) => {
  return request({ url, data, method: 'PUT', ...options });
};
​
export const del = (url, data, options = {}) => {
  return request({ url, data, method: 'DELETE', ...options });
};
​

<u-list-item v-for="(item, index) in indexList" :key="index">
                    <u-cell :title="item.channelName">
                        <u-avatar slot="icon" shape="square" size="35" :src="item.userImg"
                            customStyle="margin: -3px 5px -3px 0"></u-avatar>
                        <text slot="value">修改|</text>
                        <text slot="value" @click="deleteChannel(item, index)">删除</text>
                    </u-cell>
                </u-list-item>
</u-list>
​
​
​
​
async deleteChannel(item, index){
                //获取主键
                console.log(item.channelId);
                const res = await del("/system/channels/"+item.channelId);
                console.log(res);
                //判断失败,提醒
                //成功,刷新
                this.loadChannel();
            },

7、修改

1、点击修改按钮,传递id到修改页面

2、修改页面 onload函数中获取主键id

3、判断id是否存在,存在根据id查询详情,回显数据

4、更新数据到数据库表

5、联调新增和修改。

toEdit(item){
                //跳转到新增|修改页面  传递主键
                uni.navigateTo({
                    url:"/pages/channel/channelAdd?id="+item.channelId
                })
            },
onLoad(options) {
            //判断是否是修改
            if(options != null && options.id!=null && options.id!=''){
                uni.setNavigationBarTitle({
                    title: '修改渠道'
                });
                //调用方法,查询详情
                this.getChannelDtail(options.id);
            }
            
        }
async submit() {
                const validate = await this.$refs.form.validate();
                //接收数据
                console.log(this.formData);
                var resp = null ;
                //发起网路请求
                if(this.formData.channelId==null || this.formData.channelId==''){//新增
                     resp = await post('/system/channels', this.formData);
                }else{//修改
                     resp = await put('/system/channels', this.formData);
                }
                if (resp.code == 200) { //成功
                    //跳转到列表查询
                    uni.navigateTo({
                        url: "/pages/channel/channel"
                    })
                } else {
                    console.log("操作失败");
                }

​
            },

8、下拉刷新

"globalStyle": {
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "uni-app",
        "navigationBarBackgroundColor": "#dfd7ce",
        "backgroundColor": "#F8F8F8",
        "app-plus": {
            "background": "#efeff4"
        },
        "enablePullDownRefresh": true
    }
onPullDownRefresh() {
            let pageSize = Math.ceil(this.total/3);
            if(this.currentPage >= pageSize){
                console.log("已经最后一页");
            }else{
                this.loadChannel(++this.currentPage);
            }
            setTimeout(()=>{
                uni.stopPullDownRefresh();
            },1000);
        }

9、搜索+分页

<uni-forms ref="form" :modelValue="formData" >
                    <uni-forms-item label="渠道名称" name="channelName">
                        <uni-easyinput type="text" v-model="formData.channelName" placeholder="请输入渠道名称" />
                    </uni-forms-item>
                    <uni-forms-item label="渠道编码" name="channelCode">
                        <uni-easyinput type="text" v-model="formData.channelCode" placeholder="请输入渠道编码" />
                    </uni-forms-item>
                </uni-forms>
                <button @click="search">搜索</button>
async search(){
                this.indexList = [];
                this.loadChannel(1) ;
            }, 

网站公告

今日签到

点亮在社区的每一天
去签到