一、为什么要拿uniapp去做这个微信小程序 (为什么不用原生小程序做?)
方便日后扩展其他端
二、蓝湖设计图
https://lanhuapp.com/link/#/invite?sid=lXJcIh1a
分享人: 41238206
蓝湖团队: 小鹿线团队的团队
相关项目: 办鹿
链接有效期: 20230223~20230309
三、前期项目搭建
3.1 项目创建(vue2版本)
3.2 ui组件的引入==>方便开发
引入方式:2形式(1. npm下载 2. 直接导入到项目中)
***引入方式区别:
npm下载的形式,在h5端没问题,在其他端可能无效(微信小程序)
直接导入到项目的是100%有效
a>插件市场导入
https://ext.dcloud.net.cn/plugin?id=1593
b> main.js
// main.js
import uView from '@/uni_modules/uview-ui'
Vue.use(uView)
c> uni.scss
/* uni.scss */
@import '@/uni_modules/uview-ui/theme.scss';
d> pages.json
{
// 如果您是通过uni_modules形式引入uView,可以忽略此配置
"easycom": {
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
3.3 请求二次封装,api解耦 ==》项目请求数据方便更好维护和管理
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
// 初始化请求配置
uni.$u.http.setConfig((config) => {
/* config 为默认全局配置*/
// #ifndef H5
config.baseURL = 'http://uat.banlu.xuexiluxian.cn'; /* 根域名 */
// #endif
return config
})
// 请求拦截
uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
// config.data = config.data || {}
// // 根据custom参数中配置的是否需要token,添加对应的请求头
// if(config?.custom?.auth) {
// // 可以在此通过vm引用vuex中的变量,具体值在vm.$store.state中
// config.header.token = vm.$store.state.userInfo.token
// }
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$u.http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data
return data === undefined ? {} : data
}, (response) => {
// 对响应错误做点什么 (statusCode !== 200)
return Promise.reject(response)
})
}
const http = uni.$u.http
// // post请求,获取菜单
// export const postMenu = (data) => http.post('/ebapi/public_api/index', data)
// // get请求,获取菜单,注意:get请求的配置等,都在第二个参数中,详见前面解释
// export const getMenu = (data) => http.get('/ebapi/public_api/index', {params:data})
3.4 工具类、混入、状态管理
四、vue和nvue文件的区别
uniapp的优势:一套代码生成多端(要写大量的条件编译)
uniapp的优点:app端性能不好
***怎么解决这个性能不好的问题:.nvue文件来解决(nvue文件是为了来做app端而生的)
五、工作流
1. appid ===》 公司给你
办鹿:wxc82730a0fc15e28a
2. 自己的开发者身份
***把自己的微信号发给助教老师
3. 接口文档
网址:http://doc.xuexiluxian.cn/web/#/
帐号:testapi
密码:123456
六、关于跨域问题
解决方式:
1.前端解决
其他的项目:jsonp...
vue的项目:代理
微信小程序:不校验URL,但是项目上线就必须交验url(所以要在后台配置合法域名)
h5端
//只是在h5端生效,在小程序端是不生效端
module.exports = {
devServer:{
proxy:{
'/':{
target:'http://uat.banlu.xuexiluxian.cn',
changeOrigin:true
}
}
}
}
需要将request.js修改
uni.$u.http.setConfig((config) => {
/* config 为默认全局配置*/
// #ifndef H5
config.baseURL = 'http://uat.banlu.xuexiluxian.cn'; /* 根域名 */
// #endif
return config
})
2.后端解决
tabar https://uniapp.dcloud.net.cn/collocation/pages.html#tabbar
{
"easycom": {
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
},
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/tabs/index",
"style": {
"navigationBarTitleText": "uni-app"
}
},
{
"path": "pages/tabs/list",
"style": {
"navigationBarTitleText": "uni-app"
}
},
{
"path": "pages/tabs/me",
"style": {
"navigationStyle": "custom"//自定义头部
}
}
],
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/tabs/index",
"text": "推荐"
}, {
"pagePath": "pages/tabs/list",
"text": "分类"
},
{
"pagePath": "pages/tabs/me",
"text": "我的"
}]
},
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {}
}
七、uniapp条件编译
是什么:针对于不同端执行不同代码
你在什么时候用过:在处理小程序和h5请求方便
八、微信一键登录流程
***前提要有:appid和开发者身份,要不然测试不了
1. 点击 【微信一键登录】按钮(说白了就是随便一个按钮来触发方法)
2. 调用uniapp提供的api:uni.getUserProfile//微信小程序也提供 https://uniapp.dcloud.net.cn/api/plugins/login.html
uni.getUserProfile是什么:获取用户信息。每次请求都会弹出授权窗口,用户同意后返回 userInfo。
3. 调用uni.login方法,会获取用户的code编码
这个code编码需要传递给后端,其实就是来看看这个用户在当前小程序之前有没有注册过
code码是字符串
4. 如果没有注册过,调用后端接口:wechatRegister(去注册),需要传递的数据有
unionId 是 string 开放平台ID,如果后端未返回则传OPENID
openId 是 string OPENID
sessionKey 是 string SESSION KEY
signature 是 string 签名
rawData 是 string 原始数据
encryptedData 是 string 加密数据
iv 是 string 偏移量
具体如下:
import { loginByWechat , wechatRegister } from '@/utils/api/login.js'
export default{
methods:{
login(){
uni.1({
desc:'登录后同步数据',
success( ures ){
console.log( 'getUserProfile',ures )
// ures是用来获取用户信息的
uni.login({
success( lres ){
//通过这个code来判断,这个用户在这个小程序有没有注册过[之前有没有登录过]
let params = {
code:lres.code
}
loginByWechat(params).then(res=>{
console.log('后端接口返回',res )
if( res.code == '60003' ){
//注册微信用户
wechatRegister({
unionId:res.data.unionId ? res.data.unionId : res.data.openid,
openId:res.data.openid,
sessionKey:res.data.sessionKey,
signature:ures.signature,
rawData:ures.rawData,
encryptedData:ures.encryptedData,
iv:ures.iv
}).then(resdata=>{
console.log( 11 , resdata )
//注册完成后存储token
//是否绑定手机号
})
}else{
//也可以不绑定
}
})
}
})
}
})
}
}
}
5. 注册功能后后端会给前端返回token
5.1 前端要把token存储起来 ==> 本地存储中 https://uniapp.dcloud.net.cn/api/storage/storage.html#setstorage
***注意:在微信小程序是没有cookie的
***注意:在uniapp中没有原生localStorage要用uni.setStorage/getStorage
uni.setStorage({
key: 'storage_key',
data: 'hello',
success: function () {
console.log('success');
}
});
uni.getStorage({
key: 'storage_key',
success: function (res) {
console.log(res.data);
}
});
那么具体改为
<template>
<view>
<button @click='login'>微信登录</button>
</view>
</template>
<script>
import { loginByWechat , wechatRegister } from '@/utils/api/login.js'
export default{
methods:{
//点击登录
login(){
let that = this;
uni.getUserProfile({
desc:'登录后同步数据',
success( ures ){
uni.login({
success( lres ){
//通过这个code来判断,这个用户在这个小程序有没有注册过[之前有没有登录过]
let params = {
code:lres.code
}
loginByWechat(params).then(res=>{
//当前微信用户未注册 ==》 60003
if( res.code == '60003' ){
let params = {
unionId:res.data.unionId ? res.data.unionId : res.data.openid,
openId:res.data.openid,
sessionKey:res.data.sessionKey,
signature:ures.signature,
rawData:ures.rawData,
encryptedData:ures.encryptedData,
iv:ures.iv
};
//那么就去注册
that.register(params);
}else if(res.code=='200'){
//之前注册过,检验是否绑定过是手机号
that.isMobile(res.data);
}
})
}
})
}
})
},
//注册微信用户
register( params ){
wechatRegister(params).then(res=>{
if( res.code == '200' ){
this.isMobile( res.data );
}else{
//失败的弹出信息
}
})
},
//登录
isMobile( data ){
//存储token
uni.setStorage({
key:'token',
data:data.token
})
//判断用户有没有绑定过手机号
if( !data.member.mobile ){
uni.showModal({
title:'提示信息',
confirmText:'去完善',
content:'根据国家规定,需要绑定手机号',
success( res ){
if( res.confirm ){
uni.navigateTo({
url:'/pages/login/bindPhone'
})
}else{//取消
}
}
})
}
}
}
}
</script>
<style>
</style>
九、当给你一个表单,你会处理那些问题?
1. 检验表单中输入的内容是否合规 从而也防止了 sql注入
uview中的纯数字输入键盘
2. 提交表单的时候,明文要加密(aes) uview封装的纯数字
<input class="uni-input" type="number" placeholder="这是一个数字输入框" v-model='form.phone'/>
a> 下载aes
npm install crypto-js -S
b> aes中配置了什么?你怎么配置的?
秘钥、偏移量、加密方法、解密方法
// 引入AES源码js
const CryptoJS = require('crypto-js')
// 默认的KEY与IV如果没有给||后端接口会给
// 秘钥:bGvnMc62sh5RV6zP
// 偏移量:1eZ43DLcYtV2xb3Y
const CryptoJS = require('crypto-js')
const key = CryptoJS.enc.Utf8.parse('bGvnMc62sh5RV6zP') // 十六位十六进制数作为密钥
const iv = CryptoJS.enc.Utf8.parse('1eZ43DLcYtV2xb3Y') // 十六位十六进制数作为密钥偏移量
// 解密方法
export function Decrypt(word) {
const encryptedHexStr = CryptoJS.enc.Hex.parse(word)
const srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)
const decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
return decryptedStr.toString()
}
// 加密方法
export function Encrypt(word) {
const srcs = CryptoJS.enc.Utf8.parse(word)
const encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 })
return encrypted.ciphertext.toString().toUpperCase()
}
//绑定是手机号的页面
<template>
<view>
<button @click='login'>微信一键登录</button>
</view>
</template>
<script>
import {
loginByWechat,
wechatRegister
} from '@/untils/api/login.js';
import {
mapState,
mapActions,
mapMutations
} from 'vuex';
import {
toArray
} from 'xe-utils';
export default {
methods: {
...mapMutations(['setToken']),
...mapActions(['getUserInfo']),
async login() {
let that = this
uni.getUserProfile({
desc: 'denglu',
success: (ures) => {
uni.login({
success(lres) {
let params = {
code: lres.code,
// code 是用来判断用户在这个小程序有没有注册过(之前有没有登陆过)
}
loginByWechat(params).then(res => {
// console.log(res)
if (res.code == '60003') {
// 说明用户还没有注册需要注册
console.log('还没有注册过')
let params = {
unionId: res.data.unionId ? res.data
.unionId : res.data.openid,
openId: res.data.openid,
sessionKey: res.data.sessionKey,
signature: ures.signature,
rawData: ures.rawData,
encryptedData: ures.encryptedData,
iv: ures.iv
}
return that.register(params)
} else if (res.code == '200') {
// 之前注册过,检验是否绑定过手机号
that.mobile(res.data)
}
})
}
})
}
})
},
// 注册微信用户
register(params) {
wechatRegister(params).then(resdata => {
if (resdata.code == '200') {
// 说明微信注册成功
this.mobile(resdata.data)
return
} else {
// 失败则弹出信息
console.log('注册失败')
}
})
},
// 检验使用之前是否绑定过手机号
async mobile(data) {
// 存储token
this.setToken(data.token)
if (!data.member.mobile) {
this.isMobile()
} else {
await this.getUserInfo()
// 如果绑定过手机号,返回上一页
uni.navigateBack()
}
},
async isMobile(data) {
let that = this
uni.showModal({
title: '去完善',
content: '根据国家规定需要绑定手机号',
async success(res) {
if (res.confirm) {
uni.navigateTo({
url: '/login/bindPhone'
})
} else {
await that.getUserInfo()
// 如果绑定过手机号,返回上一页
uni.navigateBack()
}
}
});
}
}
}
</script>
<style>
</style>
在store中有存储token和获取用户信息的方法(持久化存储)在index.ts这个页面中
import Vue from 'vue'
import Vuex from 'vuex'
//引入vuex持久化存储插件
import persistedstate from 'vuex-persistedstate'
Vue.use(Vuex);
import user from './modules/user'
const store = new Vuex.Store({
modules: {
user
},
plugins: [
persistedstate({
storage: {
getItem: key => uni.getStorageSync(key),
setItem: (key, value) => uni.setStorageSync(key, value),
removeItem: key => uni.removeStorageSync(key)
}
})
]
})
export default store
/modules/user
import {
userInfo
} from '@/untils/api/login.js';
export default {
state: {
token: '',
info: {
status: false
}
},
mutations: {
setToken(state, value) {
state.token = value;
},
getInfo(state, res) {
state.info = Object.assign({
status: true
}, res.data);
}
},
actions: {
async getUserInfo({
commit
}) {
let res = await userInfo();
if (res.code == '200') commit('getInfo', res);
}
}
}
绑定的手机号的页面
<template>
<view class="">
<input class="uni-input" type="number" placeholder="手机号" v-model="form.phone" />
<input type="text" placeholder="验证码" v-model="form.code">
<button @click="sendCode">{{codeText}}</button>
<button @click="bindPhone">确定</button>
</view>
</template>
<script>
import {
updateMobile,
sendMessage
} from '@/untils/api/login.js';
import {
Encrypt
} from '@/untils/aes.js';
import {
mapActions
} from 'vuex'
export default {
data() {
return {
form: {
phone: '',
code: ''
},
time: 10,
codeText: '获取手机验证码'
}
},
methods: {
...mapActions(['getUserInfo']),
// 发送短信验证码
async sendCode() {
let that = this;
let reg = /^1[2-9]\d{9}$/;
// 判断用户输入的手机号格式对不对
if (reg.test(this.form.phone)) {
let res = await sendMessage({
mobile: Encrypt(this.form.phone),
key: 'MODIFY_MOBILE'
})
// console.log(res)
// 说明手机号发送是成功的
if (res.code == '200') {
uni.showToast({
title: '验证码发送成功',
icon: 'none'
})
let time = this.time;
let timer = setInterval(function() {
if (time == 0) {
clearInterval(timer)
that.codeText = '重新获取手机验证码'
} else {
that.codeText = `还剩下${time}秒`;
time--
}
}, 1000)
}
} else {
uni.showToast({
title: '请输入正确的11位手机号',
icon: 'none'
})
}
},
//确定绑定
async bindPhone() {
let res = await updateMobile({
mobile: Encrypt(this.form.phone),
captcha: this.form.code
})
//绑定成功,跳转到首页
if (res.code == '200') {
//获取用户的信息
await this.getUserInfo();
//跳转页面
uni.switchTab({
url: "/pages/tabs/me"
})
} else {
uni.showToast({
title: '该手机号已被绑定'
})
}
}
}
}
</script>
反正不管绑定不绑定手机号他们都会跳转到上一页
接口联调
问问后端那个是是哪个的接口
十、性能问题
10.1 你做过哪些性能优化
a> 冻结对象 : Object.freeze
因为如果vue直接复制给data属性值,会走observer,使用Object.freeze冻结可以提升效率
****这个对象以后不能修改了
10.2 加入后端一次性给你10W条数据,你如何把数据放在页面
虚拟列表
swiper https://uniapp.dcloud.net.cn/component/swiper.html
十一、2月24作业
1. 项目登录做了,多去看看逻辑上哪里有问题?
2. 如何把表格的数据放在页面上(导入)
搜索vue把表格放在页面
3. 如何实现架构图
vue组织架构图
4. 数据重构 ex : 扁平化数据转换成多叉树 ...
import XEUtils from 'xe-utils';
相关作者
- 获取点赞0
- 文章阅读量264
评论()