uniapp 微信小程序

官网:

  1. uniapp文档
  2. 微信小程序文档
  3. vue2文档
  4. vue3文档

单位

单位 描述
rpx 小程序中使用, 750rpx = 屏幕宽度
vw/vh h5的单位, 100vw = 屏幕宽度, 100vh = 屏幕的高度

图像

官网: image

image的mode一般有:

mode 描述
heightFix 高度不变,宽度自动变化,保持原图宽高比不变
widthFix 宽度不变,高度自动变化,保持原图宽高比不变
aspectFit 保持纵横比缩放图,可以完整地将图片显示出来。
aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来

导航

绑定触底事件

即, 下拉到底部时, 触发自定义的事件, 动态获取数据.

  1. 页面部分滚动

      <scroll-view
    	@scrolltolower="handleToLower"
    	scroll-y
    	class="view"
    	>
    </scroll-view>
    
    <style lang="scss" scoped>
    .view {
      // 计算滚动区域
      height: calc(100vh - 36px);
    }
    </style>
    

    假如scroll-view的display为flex时, 需要添加enable-flex属性

  2. 页面全部滚动

    <script>
    export default {
      onReachBottom(){
    	// ... 执行
      }
    };
    </script>
    

轮播图

一般需要指定三个属性

  1. autoplay 自动播放
  2. indicator-dots 指示器
  3. circular 衔接轮播
<swiper autoplay indicator-dots circular>
  <swiper-item v-for="item in banner" :key="item.id">
    <image :src="item.thumb"></image>
  </swiper-item>
</swiper>

注: swiper-item的高度和宽度都为100%,

分段器

即tab

<template>
  <view>
    <view class="home_tab">
      <view class="home_tab_title">
        <view class="title_inner">
          <uni-segmented-control
            :current="current"
            :values="items.map((item) => item.title)"
            @clickItem="onClickItem"
            styleType="text"
            activeColor="#dd3915"
          ></uni-segmented-control>
        </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>
    </view>
  </view>
</template>

<script>
import { homeAlbum } from "./home-album";
import { homeCategory } from "./home-category";
import { homeNew } from "./home-new";
import { homeRecommend } from "./home-recommend";
// 分段器
import { uniSegmentedControl } from "@dcloudio/uni-ui";

export default {
  components: {
    homeAlbum,
    homeCategory,
    homeNew,
    homeRecommend,
    uniSegmentedControl,
  },
  data() {
    return {
      items: [
        { title: "推荐" },
        { title: "分类" },
        { title: "最新" },
        { title: "专辑" },
      ],
      current: 0,
    };
  },
  methods: {
    onClickItem(e) {
      if (this.current !== e.currentIndex) {
        this.current = e.currentIndex;
      }
    },
  },
};
</script>

<style lang="scss">
.home_tab {
  .home_tab_title {
    .title_inner {
      width: 60%;
      margin: 0 auto;
    }
  }
}
</style>

使用scss

安装依赖
由于安装node-sass提示错误, 所以替换了:

"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"style-resources-loader": "^1.4.1",
<style lang="scss">
.home_tab {
  .home_tab_title {
    .title_inner {
      width: 60%;
      margin: 0 auto;
    }
  }
}
</style>

或:

<style lang="scss" scoped>
.home_tab {
  .home_tab_title {
    .title_inner {
      width: 60%;
      margin: 0 auto;
    }
  }
}
</style>

存储数据

  1. app.globalData

    // 设置
    getApp().globalData.data = {}
    
    // 获取
    const data = getApp().globalData.data
    
  2. vuex
    uniApp内已经内嵌了vuex
    第一步: 定义 ./stor/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    
    
    export default new Vuex.Store({
    	state: {
    		hasLogin: false, // 登录状态
    		userInfo: {}, // 用户信息
    	},
    	mutations: {
    		setHasLogin(state, value){
    			state.hasLogin = value
    			console.log(state.hasLogin)
    		}
    	},
    	actions: {},
    	getters: {}
    })
    

    第二步: 在mian.js中挂载store

    import Vue from 'vue'
    import App from './App'
    import store from './store'  
    
    Vue.config.productionTip = false
    Vue.prototype.$store = store
    
    App.mpType = 'app'
    
    const app = new Vue({
    	...App,
    	store,
    })
    app.$mount()
    

    第三步: 使用vuex

    // 获取state中的值
    this.$store.state.loginStatus
    
    // 修改state中的值
    this.$store.commit('setHasLogin', true);
    
    // 调用actions中的方法
    // 要在actions中定义方法
    this.$store.dispatch('',{number:123})
    
    // 调用getters中的方法
    // 要在getters中定义方法
    this.$store.getters.reverseLoginStatus
    
  3. uni.setStorage/uni.getStorage
    见: 数据缓存

生命周期钩子函数

有三类:
APP.vue生命周期:

函数名 说明
onLaunch uni-app 初始化完成时触发(全局只触发一次)
onShow uni-app 启动,或从后台进入前台显示
onHide uni-app 从前台进入后台
onError uni-app 报错时触发

pages/xxx/index.vue生命周期:

函数名 说明
onLoad 监听页面加载,其参数为上个页面传递的数据

组件生命周期

函数名 说明
beforeCreate 在实例初始化之后被调用
created 在实例创建完成后被立即调用
beforeMount 在挂载开始之前被调用
mounted 挂载到实例上去之后调用
beforeUpdate 数据更新时调用,发生在虚拟 DOM 打补丁之前 (仅H5平台支持)
updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子 (仅H5平台支持)
beforeDestroy 实例销毁之前调用
destroyed Vue 实例销毁后调用

封装request

// 封装自定义请求

export default (params) => {
  return new Promise((resolve, reject) => {
    // 加载中
    uni.showLoading({
      title: "加载中...",
    });
    wx.request({
      ...params,
      success(res) {
        // .data => 服务器返回的数据
        resolve(res.data); // 成功
      },
      fail(err) {
        reject(err); // 失败
      },
      complete() {
        // 完成请求时
        // 隐藏loading
        uni.hideLoading();
      },
    });
  });
};

main.js中:

import Vue from "vue";
import App from "./App";
import request from "./utils/request";

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

App.mpType = "app";

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

使用时:

this.request({
  url: "http://xxxx",
  data: {}
})

登录组件

<!-- 微信授权登录全程代码实现 -->
<template>
  <view>
    <view v-if="isLoading">
      <view>
        <view class="header">
          <!-- <image src="../../static/img/wx_login.png"></image> -->
        </view>
        <view class="content">
          <view>申请获取以下权限</view>
          <text>获得你的公开信息(昵称,头像、地区等)</text>
        </view>

        <button
          class="bottom"
          type="primary"
          open-type="getUserInfo"
          withCredentials="true"
          lang="zh_CN"
          @getuserinfo="getUserInfo"
        >
          授权登录
        </button>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      SessionKey: "",
      OpenId: "",
      appKey: "abcdef",
      nickName: null,
      avatarUrl: null,
      isLoading: uni.getStorageSync("isLoading") || true, //默认为true
    };
  },
  methods: {
    getUserInfo() {
      /* 获取用户信息 */
      uni.getUserInfo({
        provider: "weixin",
        // 获取成功后调用
        success: (infoRes) => {
          let nickName = infoRes.userInfo.nickName; //获取用户登录昵称
          let avatarUrl = infoRes.userInfo.avatarUrl; //获取用户头像
          this.nickName = nickName;
          this.avatarUrl = avatarUrl;

          console.log("nickName: ", nickName);
          console.log("avatarUrl: ", avatarUrl);
          try {
            uni.setStorageSync("isLoading", false); //记录是否第一次授权  false:表示不是第一次授权
            this.updateUserInfo();
          } catch (e) {
            console.log(e);
          }
        },
        fail(res) {},
      });
    },
    login() {
      /* 登录函数 */
      uni.showLoading({
        title: "登录中...",
      });

      // 1.wx获取登录用户code
      uni.login({
        provider: "weixin",
        success: (loginRes) => {
          let code = loginRes.code;
          if (!this.isLoading) {
            //非第一次授权获取用户信息

            uni.getUserInfo({
              provider: "weixin",
              success: (infoRes) => {
                //获取用户信息后向调用信息更新方法
                let nickName = infoRes.userInfo.nickName; //昵称
                let avatarUrl = infoRes.userInfo.avatarUrl; //头像
                this.nickName = nickName;
                this.avatarUrl = avatarUrl;

                console.log("nickName: ", nickName);
                console.log("avatarUrl: ", avatarUrl);
                this.updateUserInfo(); //调用更新信息方法
              },
            });
          }

          //2.将用户登录code传递到后台置换用户SessionKey、OpenId等信息
          uni.request({
            url: `${this.serveHost}/login`, //接入后端提供的登录接口
            data: {
              code: code, //传入参数code获取登录凭证
            },
            method: "GET",
            header: {
              "content-type": "application/json",
            }, //请求头
            success: (res) => {
              // 成功登录后调用
              // 可以: openId、或SessionKdy存储//隐藏loading

              uni.hideLoading();
            },
          });
        },
      });
    },

    updateUserInfo() {
      /* 向后台更新信息 */

      uni.request({
        url: `${this.serveHost}/user`, //服务器端地址
        data: {
          appKey: this.appKey, //Vuex封装app密钥 this.$store.state.appKey
          customerId: "this.customerId", //自定义id  this.customerId
          nickName: this.nickName, //昵称
          headUrl: this.avatarUrl, //头像
        },
        method: "POST",
        header: {
          "content-type": "application/json",
        },
        success: (res) => {
          if (res.data.state == "success") {
            uni.reLaunch({
              //信息更新成功后跳转到小程序首页
              url: "/pages/home/index",
            });
          }
        },
      });
    },
  },
  onLoad() {
    //默认加载
    this.login();
  },
};
</script>

<style>
.header {
  margin: 90rpx 0 90rpx 50rpx;
  border-bottom: 1px solid #ccc;
  text-align: center;
  width: 650rpx;
  height: 300rpx;
  line-height: 450rpx;
}

.header image {
  width: 200rpx;
  height: 200rpx;
}

.content {
  margin-left: 50rpx;
  margin-bottom: 90rpx;
}

.content text {
  display: block;
  color: #9d9d9d;
  margin-top: 40rpx;
}

.bottom {
  border-radius: 80rpx;
  margin: 70rpx 50rpx;
  font-size: 35rpx;
}
</style>
posted @ 2021-12-29 17:46  403·Forbidden  阅读(548)  评论(0编辑  收藏  举报