Uni-app开发笔记 记录开发各种报错 datetime forms 状态机 Storage nav-bar
一、uni-app简介
PC端;移动端:(APP,WebApp);纯原生:(IOS,Android ) 应用商店;H5
Hybrid 模式(混合):(现在手机的99%都是这个模式)
uni-app是一个使用Vue.js开发所有前端应用的框架,支持Vue语法 + 小程序标签/API
跨终端: 开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用(华为、小米、vivo、OPPO)等多平台。
DCloud 国产
支持平台:
![](https://i-blog.csdnimg.cn/blog_migrate/921e638bee60e03086535bf78b981bea.png)
二、快速上手
2.1 开发工具
下载地址: https://www.dcloud.io/hbuilderx.html
三、开发微信小程序
3.1 相关配置
Uni-app项目运行至小程序开发工具需要提前设置小程序开发工具的安装路径
同时设置小程序开发工具拒绝访问问题
第一次使用需设置小程序开发工具的安装路径,否则无法打开开发工具
![](https://i-blog.csdnimg.cn/blog_migrate/34d7d8ef30f810cbf6a73c5cdfb795a7.png)
在小程序的开发工具中,设置/安全设置 开启端口:
![](https://i-blog.csdnimg.cn/blog_migrate/2f2f038dafd1a5879fcc6037932e4060.png)
四、语法介绍
4.1 官网使用指南
框架: 配置信息,框架接口(页面,页面生命周期等)
组件: 同小程序组件一样,用于布局
API: 用于实现指定的功能
a) 全局对象uni
b) 组成: ECMAScript的jsAPI + uni扩展api组成
c) 示例: uni.request || uni.setStorage
入口文件:main.js
![](https://i-blog.csdnimg.cn/blog_migrate/b325463b5441d412cc4fd521b6f63a00.png)
App.vue
会分别编译成 app.js 和app.wxss
![](https://i-blog.csdnimg.cn/blog_migrate/05f9309982fa50fa47d2a7332e0d60e9.png)
pages.json 相当于 app.json
manifest.json配置:
![](https://i-blog.csdnimg.cn/blog_migrate/b9458c5e9fd8e0854e217112d225c3a1.png)
既支持小程序的生命周期钩子函数,也支持vue的钩子函数
![](https://i-blog.csdnimg.cn/blog_migrate/a5126893f6110d98404b650150284417.png)
4.2 温馨提示
Uni-app的组件同原生小程序一样
Uni-app支持Vue语法
学好Vue + 原生小程序之后可快速上手uni-app
![](https://i-blog.csdnimg.cn/blog_migrate/092d697215a7cbacaef583c5c97d9266.png)
pages.json 自动生成:
![](https://i-blog.csdnimg.cn/blog_migrate/956fb27875cd4583f055e3911b7bc06c.png)
五、插件安装
5.1 内置插件安装
![](https://i-blog.csdnimg.cn/blog_migrate/7fb683499fc7af63a498d1817d09312e.png)
stylus特点:
预处理语言:less sass webpack==> css
@color:#fff
.test{
color: @color;
.title{#嵌套写法
font-size:17px;
}
}
省略大括号 ;缩进替代
省略键值对的分号和冒号;空格代替
支持样式缩进、嵌套
.test
colo rred
.title
font-size 17px
六、跨域处理
小程序:是不存在跨域!!不需要做兼容性处理。
6.1 方式一:vue.config.js配置
![](https://i-blog.csdnimg.cn/blog_migrate/c36b30e6259df23c395da82687da97f5.png)
6.2 方式二:mainfest.json配置
在mainfest.json中,针对H5进行跨域设置:
![](https://i-blog.csdnimg.cn/blog_migrate/8c2fc01764907ce3a3bcd7aec97ba743.png)
// 设置vue脚手架一些相关配置
module.exports={
devServer:{
proxy:{
'/api':{
target:'http://localhost:3000',
ws:true,
changeOrigin:true,
pathRewrite:{
'^/api':''
}
}
}
}
}
网易严选项目(一)开发
二、首页
2.1 效果图
![](https://i-blog.csdnimg.cn/blog_migrate/dc8f263a0819146b82ddf6bf13a975da.png)
iconfont:https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.39
无需下载直接引入方式:复制代码 新建 /static/iconfont/iconfont.styl 粘贴代码;
在App.vue 的<style>标签里引入该CSS :
@import url("/static/iconfont/iconfont.styl");
在pages/index/index.vue中布局
![](https://i-blog.csdnimg.cn/blog_migrate/4d1d621f4aaf07fcf1ed44cacf38319c.png)
css的定位属性position:absolute是什么意思?
position是“位置”、“放置方式”的意思,absolute是“绝对的”的意思,那么position:absolute指的是绝对定位的意思。
如果某元素添加了position:absolute属性,会把该元素设置为绝对定位,该元素会变成一个有框的空间,具体定义是这样的:
设置为绝对定位的元素框从文档流完全删除,并相对于其包含块定位,包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像该元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
简单理解就是:绝对定位的元素的位置相对于最近的已定位祖先元素(父元素),如果元素没有已定位的祖先元素(父元素),那么它的位置相对于最初的包含块。
![](https://i-blog.csdnimg.cn/blog_migrate/db3e912a770ec4f56fef77bdef951bc1.png)
滑动导航栏一直报错 感觉就是 resolve 后面多加个‘=’
import base from './base'//接收url域名
// getIndexData 我自己记的
export default (url,data={},method='GET')=>{
return new Promise ((resolve,reject)=>{
uni.request({
url:base.host+url, //小程序请求,
//url,//h5请求地址
data,
method,
success: (res) => {
resolve = (res.data);
},
fail:(err)=>{
reject(err)
}
});
})
}
import base from './base.js'
// /getIndexData 老师的
export default (url,data={},method='GET')=>{
return new Promise((resolve,reject)=>{
uni.request({
url:base.host+url, //小程序
// url,//H5
data,
method,
success(res) {
resolve(res.data);
},
fail(err) {
reject(err);
}
})
})
}
三、服务器端搭建
3.1 搭建步骤
创建包说明书:
npm init -y
安装 express
npm i express -S
Index.js:
constexpress=require('express')
constrouter=require('./router')
// 创建服务器
constapp=express();
app.use('/',router)
app.listen('7788',()=>{
console.log('服务端启动成功啦。。。。。');
console.log('http://localhost:7788');
})
router.js:
const express=require('express')
// 路由
const router=express.Router();
router.get('/test',(req,res)=>{
res.send({
data:'测试成功'
})
})
// 引入首页数据
const indexData=require('../datas/index.json');
// 注册index页接口
router.get('/getIndexData',(req,res)=>{
res.send({
status:200,
indexData,
})
})
module.exports=router;
每次需要重启服务器 在server文件位置cmd输入下一行:
node index.js
更改H5与小程序运行需要修改三个位置:
![](https://i-blog.csdnimg.cn/blog_migrate/166978f7f6a0841c2db1d7ff0a483be0.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3bba2d2836c2c30e1ee64ab417211a3c.png)
H5的时候要加v-if="indexData.kingkongModule",wx要去掉不然会无法出现滑块
H5出现KingkongModule undefined
(a.b.c报错?)
![](https://i-blog.csdnimg.cn/blog_migrate/297390108348522a30993e83ab6b3e98.png)
为什么在小程序里不报这个错误?
原因:小程序编译之后的代码,放到开发工具里,加载,所以不会出现上面的情况
解决方案:在父元素添加v-if
<!-- 横向滑块用scroll-x v-if解决H5页面渲染层异步加载问题 -->
<scroll-view class="navcroll" scroll-x="true" v-if="indexData.kingkongModule" >
<view class="navItem" :class="{ active: navIndex === -1 }" @click="changeIndex(-1)">推荐</view>
<view
class="navItem"
:class="{ active: navIndex === index }"
@click="changeIndex(index)"
v-for="(item, index) in indexData.kingKongModule.kingKongList"
:key="item.L1Id"
><!-- 点击谁 谁高亮-->
{{ item.text }}
</view>
</scroll-view>
面试题:
v-if :添加删除 DOM
v-show:显示、隐藏 DOM display:none
面试题: v-if 和 v-for 可以放在同一个标签上吗? 为什么
答案:不能。 v-for优先级高,需要同时使用的话, v-if 放到父元素上去
【【尚学堂】微信小程序开发教程+网易严选项目:Web前端小程序开发精选教程,从基础入门到项目上线,零基础自学前端】https://www.bilibili.com/video/BV1m94y1X7X1?p=38&vd_source=5475f4f6010a81c8e6d4789af8e1a20f
看到这里p38_38_回顾Vuex 03:41
主要问题是我为自己规划的是后端开发,前端知识还不怎么熟悉加上其它一些因素 暂时封存这个项目
![](https://i-blog.csdnimg.cn/blog_migrate/a5091d204f2fdfd5de640dd39a4e7b67.png)
——2023/1/24
2023/2/5 需要小程序知识 再次起手
网易严选项目(二)开发
一、搭建仓库
HBuilderX 打开终端无法输入指令
每次需要重启服务器 在server文件位置cmd输入下一行:
node index.js
请求回的首页数据,需要被多个组件共享使用,要么组件通信,要么使用vuex集中管理数据。
![](https://i-blog.csdnimg.cn/blog_migrate/ec0de965ccf58f79ccaace51d962e972.png)
初始化package.json:npm init -y
下载vuex:npm install vuex -D
1.1 回顾Vuex:
作用:
集中式管理状态
多个组件之间共享数据
核心:
state 存储状态
mutations:每个都是方法,同步修改state数据
面试题:mutations可以异步(但是不推荐)修改,但是vuex调试工具里,你看不到数据变化
![](https://i-blog.csdnimg.cn/blog_migrate/8580c6773bb080aece2a1f9c5939277d.png)
3. actions:每个都是方法,异步修改state数据。 同步触发mutations
4. getters:对state已有的数据加工处理(不修改原数据),返回计算属性
5. module : 分模块管理
1.2 引入Vuex-基本结构
二、从Vuex获取首页数据
之前,数据都是在首页发送request请求获取的。接下来,所有的数据需要从Vuex中获取。先得往Vuex的state里存数据,然后再取。
import request from '../../utils/request.js'//调用封装的发请求的request方法
const state={
test:'测试数据',
indexData:{},//首页数据
}
const mutations={
//修改首页数据
changeIndexDataMutations(state,indexData){
//(仓库数据,变量),接受变量直接修改数据
state.indexData=indexData;
}
}
const actions={
//发送网络请求 拿首页数据
async getIndexDataActions({commit}){//(contxet作为上下文对象(包含commit等属性) )
//1.执行异步任务,发送网络请求
const res=await request('/getIndexData');//小程序
//2.commit 触发 修改首页数据的mutation 就可以修改state的indexData数据
console.log(res);
commit('changeIndexDataMutations',res.indexData)//修改 回存
}
}
index.vue:
mounted() {
//获取仓库里的测试数据
console.log(this.$store.state.home.test);
//1.触发action this.$store.dispatch('模块名/action名')
//this.$store.dispatch('home/getIndexDataActions')
//2.mapActions触发 更方便
this.getIndexDataActions()
//this.getIndexData();
},
methods: {
//2.触发action 语法 ('模块名','['模块里的action名']');映射完 在mounted里当方法映射
...mapActions('home',['getIndexDataActions']),
async getIndexData(){//获取首页数据
const res=await request('/getIndexData');//小程序
// const res=await request('/api/getIndexData');//H5跨域
this.indexData=res.indexData;s
},
// 点击切换下标
changeIndex(index) {
// console.log(index);
this.navIndex = index;// 把点击当前项的Index,赋值给导航标记
},
},
computed: {
//...mapState('home',['indexData'])
//把indexData映射成当前属性的数据
...mapState({//函数方法实现映射mapState
indexData:(state)=>state.home.indexData,
//箭头函数省略return 把state.home.indexData返回给indexData
})
},
三、内容区
效果图
![](https://i-blog.csdnimg.cn/blog_migrate/3f86e11f90ea0217706bac9b86f689a7.png)
3.1 推荐模块
![](https://i-blog.csdnimg.cn/blog_migrate/07ab00b97d2befd35a1aea372f1a684b.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e58ca3581eafc70c2dcc91aeaeceeb51.png)
改版的直接改后端数据
P43没看
四、底部tabBar
效果图
![](https://i-blog.csdnimg.cn/blog_migrate/9b586e96315f4da46de4f262a5ad23f0.png)
新建分类页
pages 右键 “新建页面”:cart、category、personal
设置 tabBar 样式 page.json:
五、首页里-分类列表
首页 scrollView 导航中,除了推荐,其他的几个列表都是一样的。并且跟推荐都展示在一块区域。所以,需要封装组件 cateList
P46没看
一、分类页面TabBar
包含:搜索、左侧选项卡、后侧内容区
1.1 效果图
![](https://i-blog.csdnimg.cn/blog_migrate/ea20a3074f5604dbf65f57bc183de9f1.png)
二、个人中心
2.1 效果图
未登录状态:
![](https://i-blog.csdnimg.cn/blog_migrate/4b6a2cfd8022e1664f03021a9a77c998.png)
登录状态:
![](https://i-blog.csdnimg.cn/blog_migrate/dea071848805d17f601ed32491d16891.png)
2.2 布局
<template>
<div>
<div class="header">
<template v-if="userInfo.nickName">
<img class="userImg" :src="userInfo.avatarUrl" alt="" />
<view>{{ userInfo.nickName }}</view>
<button @click="exit">退出登陆</button>
</template>
<template v-else>
<img class="userImg" src="/static/images/personal/personal.png" alt="" />
<text class="userInfo" @click="toLogin">去登录吧</text>
</template>
</div>
<div class="content">
<h2>我的资产</h2>
<p class='line'></p>
<div class="myAssetList">
<div class='assetItem'>
<span>¥0</span>
<span>回馈金</span>
</div>
<div class='assetItem'>
<span>¥0</span>
<span>红包</span>
</div>
<div class='assetItem'>
<span>¥0</span>
<span>优惠券</span>
</div>
<div class='assetItem'>
<span>¥0</span>
<span>津贴</span>
</div>
<div class='assetItem'>
<span>¥0</span>
<span>礼品卡</span>
</div>
</div>
<!-- 列表选项 -->
<div class="personalList">
<div class="navItem" v-for='(item, index) in personalList' :key='index'>
<i class='iconfont ' :class='item.icon'></i>
<p>{{item.name}}</p>
</div>
</div>
</div>
</div>
</template>
三、登录
效果图
<template>
<view class="loginContainer">
<image class="logo" src="http://yanxuan.nosdn.127.net/39c5e4583753d4c3cb868a64c2c109ea.png" mode=""></image>
<p class='text'>网易自营,精品生活家居品牌</p>
<div class="loginMethods">
<button class="login wechatLogin" open-type="getUserInfo" @getuserinfo='handleGetUserInfo'>
微信登录
</button>
</div>
</view>
</template>
methods: {
getUserProfile() {
// 获取用户信息
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: res => {
console.log(res);
console.log(res.userInfo.avatarUrl); //获取用户微信头像
console.log(res.userInfo.nickName); //获取用户微信名
// 用户授权
wx.setStorage({
key: 'userInfo',
data: JSON.stringify(res.userInfo)
});
// 把其他页面关掉,跳转的某个页面
wx.reLaunch({
url: '/pages/personal/personal'
});
}
});
}
}
DIY项目总结
tama的没有服务器 一直报错 ;点击登录->没弹出提醒用户登录信息窗口; 用户信息也没log出来
![](https://i-blog.csdnimg.cn/blog_migrate/6c6b700017d38470f65c014618b179c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/e1bc78441eea9afbd99d7f66ced55aa0.png)
TypeError: Cannot read property 'call' of undefined
VM712:2687 页面【uni_modules/uni-forms/components/uni-forms/uni-forms]错误:
https://blog.csdn.net/weixin_55778010/article/details/127255772
做了两天,差不多是二十个小时把
总体来说还不错
效果图
![](https://i-blog.csdnimg.cn/blog_migrate/fe8185887980613f760b389ff0d28e06.png)
![](https://i-blog.csdnimg.cn/blog_migrate/1a711d197854fed1020361fb3221d2d9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/6b22cb4afaaa82baa4773cf92e9d63bd.png)
![](https://i-blog.csdnimg.cn/blog_migrate/324baec4d1a7f47253b0add0392aa765.png)