title: 创建uniapp项目
date: 2024-10-11 16:51:08
tags: uniapp
uni-app微信小程序
一、创建uni-app项目(HbuilderX版本)
1.前提准备
HbuilderX下载、微信开发者工具下载
2.准备
还可以使用vscode,笔者之前写过相关的笔记,点击跳转
3.下载vue3插件
在工具->插件->vue3插件
4.添加小程序Id
在manifest中添加相关的id信息。
5.可能出现的问题
没有开启微信开发者工具的服务端口
二、page.json和tabBar案例
pages.json主要用于配置页面路由、导航栏、tabBar等页面类信息
图标放到static文件当中
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path" : "pages/my/my",
"style" :
{
"navigationBarTitleText" : "我的"
}
}
],
// 全局修改
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#1cac9d",
"backgroundColor": "#F8F8F8"
},
//对tabBar下导航栏进行相关的配置
"tabBar": {
"selectedColor": "#1cac9d",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/index1.png",
"selectedIconPath": "static/index2.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/my1.png",
"selectedIconPath": "static/my2.png"
}
]
},
"uniIdRouter": {}
}
三、uni-app与原生小程序区别
轮播图演示
<template>
<!-- 轮播图 -->
<!-- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<view class="swiper-item">
</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
</view>
</swiper-item>
</swiper> -->
<swiper indicator-dots autoplay circular class="banner" indicator-color="#999999">
<swiper-item v-for="item in pictures" :key="item.id">
<view class="swiper-item">
<img @tap="perviewPicure(item.url)" :src="item.url" alt="轮播图" srcset="" />
</view>
</swiper-item>
</swiper>
</template>
<script>
export default {
data() {
return {
title:"hello",
pictures:[
{id:"1",url:"https://s3.bmp.ovh/imgs/2024/10/10/f1dde620fe6205c8.png"},
{id:"2",url:"https://s3.bmp.ovh/imgs/2024/10/10/94baa8691e11b533.png"},
{id:"3",url:"https://s3.bmp.ovh/imgs/2024/10/10/d5d9c2974a47053f.png"},
{id:"4",url:"https://s3.bmp.ovh/imgs/2024/10/10/d58a0e5ea593ce21.png"},
]
}
},
onLoad() {
},
methods: {
perviewPicure (url){
uni.previewImage({
urls:this.pictures.map(v=>v.url),
current:url
})
}
}
}
</script>
<style>
.banner,
.banner image
{
width: 750rpx;
height: 750rpx;
}
</style>
四、相关的组件标签使用
1)前置说明
1.最外层需要template
2.将view(按view后+tab自动补全)当成div进行相关的布局设置,把text当成span标签使用
3.使用vue3中的语法糖结构setup
4.一般来说样式使用lang=“scss”
2)view
<template>
<view class="box" hover-class="boxHover" hover-stay-time="0">
<!-- 微信小程序中支持hover-stop-propagation,但是h5不行 ,他可以让子组件触发hover-class的时候不影响父组件-->
<view class="inner" hover-class="innerHover" hover-stop-propagation>
布局设置
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss">
.box{
width: 200px;
height: 200px;
background-color: #ccc;
}
.boxHover{
width: 300px;
height: 300px;
background-color: #000;
}
.inner{
width: 100px;
height: 100px;
background-color: red;
}
.innerHover{
background-color:hotpink;
}
</style>
3)text标签
不写在这个标签中,是没办法使用相关的信息的,没有办法长按拷贝。
<template>
<view>
<text selectable="true" space="emsp">可以被选择 多个空格可以存在不会被合并成一个空格 </text>
</view>
</template>
4)scroll-view属性
相关的属性太多了建议官网查看
scroll-y
<template>
<scroll-view scroll-y class="scrollStyle">
<view>测试数据</view>
<view>测试数据</view>
<view>测试数据</view>
<view>测试数据</view>
<view>测试数据</view>
<view>测试数据</view>
<view>测试数据</view>
</scroll-view>
</template>
<script>
</script>
<style>
.scrollStyle{
background-color: beige;
width: 300px;
height: 100px;
}
</style>
Scroll-x
默认这个元素是block类型,就算加上scroll-x也不能加上相关的横向滚动轴。
这个时候要将display改为inline-block可以显示相关的数据,但是会让但是数据超过了相关的要求之后会自动换行,想要不换行还要在父元素上使用white-space:nowrop
<template>
<view >
<scroll-view class="scrollStyle" scroll-x="true">
<view class="box">测试数据</view>
<view class="box">测试数据</view>
<view class="box">测试数据</view>
<view class="box">测试数据</view>
</scroll-view>
</view>
</template>
<script>
</script>
<style lang="scss">
.scrollStyle{
background-color: beige;
width: 200px;
height: 100px;
white-space: nowrap;
.box{
width: 100px;
height: 50px;
background-color: aqua;
display: inline-block;
}
}
</style>
5)swiper——轮播图
属性过多建议看官方轮播图的详细描述
还要注意图像标签中的mode属性可以帮助进行相关的排版。
<template>
<!-- 轮播图 -->
<!-- <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="1000">
<swiper-item>
<view class="swiper-item">
</view>
</swiper-item>
<swiper-item>
<view class="swiper-item">
</view>
</swiper-item>
</swiper> -->
<swiper indicator-dots autoplay circular class="banner" indicator-color="#999999">
<swiper-item v-for="item in pictures" :key="item.id">
<view class="swiper-item">
<img @tap="perviewPicure(item.url)" :src="item.url" alt="轮播图" srcset="" />
</view>
</swiper-item>
</swiper>
</template>
<script>
export default {
data() {
return {
title:"hello",
pictures:[
{id:"1",url:"https://s3.bmp.ovh/imgs/2024/10/10/f1dde620fe6205c8.png"},
{id:"2",url:"https://s3.bmp.ovh/imgs/2024/10/10/94baa8691e11b533.png"},
{id:"3",url:"https://s3.bmp.ovh/imgs/2024/10/10/d5d9c2974a47053f.png"},
{id:"4",url:"https://s3.bmp.ovh/imgs/2024/10/10/d58a0e5ea593ce21.png"},
]
}
},
onLoad() {
},
methods: {
perviewPicure (url){
uni.previewImage({
urls:this.pictures.map(v=>v.url),
current:url
})
}
}
}
</script>
<style>
.banner,
.banner image
{
width: 750rpx;
height: 750rpx;
}
</style>
6) navigator——超链接标签
navigator相当于html中的a标签,进行页面路由与页面跳转的配置。这个是基础知识,完善所有住了看官方文档的相关组件模块,还有相关的路由的API部分,但是这里讲的只是一些基础的知识,需要后续完善
<template>
<!-- reLaunchh跳转后销毁原先的页面 -->
<navigator url="/pages/index/spanLearn/spanLearn" open-type="reLaunch">跳转到text学习</navigator>
</template>
<script>
</script>
<style>
</style>
7)button、input
input使用type进行相关的类型的控制,
相关的type类型如下,点击的时候会出现不同的小键盘,方便用户输入。
confirm-type是让相关的小键盘中带上相关的按钮。
<button size="default" type="primary" plain loading >按 钮</button>
<view class="title">身份证输入的input</view>
<!-- 规定键盘输入的小键盘样式 -->
<input class="uni-input" type="idcard" placeholder="身份证输入键盘" password maxlength="6"
placeholder-style="color:red;" />
<!-- 键盘下标加搜索 -->
<input type="text" placeholder="输入商品内容" confirm-type="search"/>
五、vue3
1)模版语法
{{}}双括号放直接的变量名或者函数名或逻辑运算
setup语法糖,定义组合式API
<template>
<view >{{Date.now()}}</view>
<view >{{Math.random()}}</view>
<view >{{1<2?"1":"2"}}</view>
</template>
<script setup>
// setup是语法糖,支持组合式API
</script>
<style>
</style>
2)ref
<template>
<view >{{Date.now()}}</view>
<view >{{Math.random()}}</view>
<view >{{1<2?"1":"2"}}</view>
<view > 进入页面的第{{num}}秒</view>
</template>
<script setup>
import { ref } from 'vue';
const num = ref(0)
setInterval(()=>{
num.value++;
},1000)
</script>
<style>
</style>
3)v-bind :
缩写 :
1.上面的语法表示 active
是否存在取决于数据属性 isActive
的真假值。
2.style里在不带单位的时候可以不加’ ',但是一旦带了单位必须加
<div :class="{ active: isActive }"></div>
<div :class="isActive ?'active':'' "></div>
<div :style="{ width: '300px',height:260+'px',fontSize:fontSize+'px' }"></div>
const fontSize=ref(30)
3…绑定的对象并不一定需要写成内联字面量的形式,也可以直接绑定一个对象:
<div :class="classObject"></div>
const classObject = reactive({
active: true,
'text-danger': false
})
注意:父组件使用子组件,会包含子组件原来的样式
4)v-on @
事件映射表
// 事件映射表,左侧为 WEB 事件,右侧为 ``uni-app`` 对应事件
{
click: 'tap',
touchstart: 'touchstart',
touchmove: 'touchmove',
touchcancel: 'touchcancel',
touchend: 'touchend',
tap: 'tap',
longtap: 'longtap', //推荐使用longpress代替
input: 'input',
change: 'change',
submit: 'submit',
blur: 'blur',
focus: 'focus',
reset: 'reset',
confirm: 'confirm',
columnchange: 'columnchange',
linechange: 'linechange',
error: 'error',
scrolltoupper: 'scrolltoupper',
scrolltolower: 'scrolltolower',
scroll: 'scroll'
}
5)v-if
注意:可以使用在template标签上这样,虽然实现的效果是相同的但是相关的template包裹标签是不会显示的。
通常结构如下
<teampate v-if="">内容1</teampate>
<teampate v-else-if="">内容2</teampate>
<teampate v-else>内容3</teampate>
6)v-for
<view v-for="(item,index) in arrs" :key="item.id"></view>
为什key最好不要设置成index?
原因:假如你有复选框,假如你选择的是第二个元素,然后你删除了第二个元素,那么原来第三个元素的index就变成了第二个的,然后原来的第三个就被选中了,然而唯一选中的第二个已经被删除了。所以index不能唯一标识这个元素,他只标识在这个位置上的元素,然而位置在增删改查中可能会改变。
7)v-model
一般来书input是需要绑定相关的数据的,v-model原理是,:value=“变量”+@input=“改变变量的函数”——>输入影响与输入相关数据。直接实现了数据的双向绑定。
8)计算属性computed
一般用于简化template中比较复杂的部分放到script当中,这样可以让相关的函数在板子上边的清晰一些。他的便捷的地方在于,可以直接给他当成一个响应式的属性放在template的当中,而不是通过调用函数的形式。并且只有数据改变的时候他才会进行新的计算操作,就是即使在template中调用多次,但是computed只执行一次不会重复调用。函数是调用几次他就执行几次。
注意:
1.用的时候就将他尽量看成一个ref定义的一个变量,因为他在template中调用的时候只要写属性名,但是在script中调用的时候却要写成**“变量名.value”**拿到相关的数据,这种用法就很像ref。
2.尽量只将他堪称一个只读属性,要改的话就改他的数据源,而不是计算属性本身。比如不要直接给下面的fullName属性赋值,可以给firstName赋值来改变数据。
补充:
这个案例用到了相关的过滤属性,以下是完成的相关案例。filter进行相关的过滤,reduce进行求和。
数组对象.filter(item=>(过滤的要求))
.reduce((上一步的计算结果prev,当前的对象curr)=>{相关的计算函数},初始计算值)
9)watch监听器
注意:即使这个属性他是ref定义的响应式属性,也不用看他的value值,而是直接监听属性本身。
默认watch是一个浅层监听,就是属性中还有其他属性,其他属性变化了,他是监听不到的。
<template>
<view >
<input type="text" v-model="person" />
</view>
{{person}}
<view >
<input type="text" v-model="person2.name" />
</view>
{{person}}
</template>
<script setup>
import { ref,watch } from "vue";
const person = ref("0")
const person1 =ref("1")
const person2 = ref({
name:"张三",
age:23
})
//可以看到新值和老值,而计算属性只能得到变化后的值
watch(person,(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
})
//默认表层监听,再深一级是监听不到的(这个时候写函数传参数进来要加value)
watch(person2,(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
})
//开启深度监听getter函数(一般知道哪个属性会改变的时候使用)
watch(()=>person2.value.name,(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
})
//开启深度监听的第三个属性(一般不知到哪个属性会改变的时候使用)
watch(person2,(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
},{deep:true,immediate:true})
//虽然可以一起监听,但是建议使用单独监听方法
watch([person,person1],([newValue,oldeValue],[newValue1,oldeValue1])=>{
console.log(newValue,oldeValue);
console.log(newValue1,oldeValue1);
})
</script>
与computed的相同点
两者都可以依赖于响应式数据。
用于监听变化,并做出响应的处理。
与computed的不同点
1.computed基于依赖进行缓存,只有依赖发生变化他才重新计算。
watch监听属性允许我们在数据变化的时候执行异步操作或者复杂的逻辑,也知道新值和老值。
2.computed适用于组合出新的数据,比如对数组进行过滤、排序、格式化等操作。
watch监听属性适用于对数据的变化做出响应,比如在数据变化的时发送请求、处理副作用。
3.computed属性可以像普通对象一样直接使用**{{computed属性}}**进行模版调用
watch监听属性可以监听一个或者多个数据的变化,并且在数据变化的时候执行响应的操作。
4.computed属性中必须有return返回值。
watch监听属性不是必须要return返回值。
六、组件创建
1)局部组件
创建components文件夹,在文件夹下放相关的组件,在uniapp中的组件右击可以直接创建组件,而且不用倒包,但是传统的vue3项目是需要导包的。然后在page中的相关地方直接引入组件标签引入。
了解了自创建的局部组件之后,就可以使用相关的组件通信方式,作者有写相关的常用组件通信笔记
下面再补充一个组件通信方式,插槽。
插槽
插槽的使用方式,看官方文档比较直接。具体就是将外部组件放到组件中,外部组件中的插槽标签所在的位置,可以由组件更改。
使用在具体的插槽的地方,直接简写(具名插槽组件v-slot:的简写是# )
2)组件生命周期
咸虾米的博客这个讲的很清楚。注意使用ref绑定到标签中后,只有在onMounted的生命钩子当中,才能拿到数据,因为在这之前都还是虚拟挂在状态,相当于直接操纵dom元素相关的内容。
uniapp的生命周期和传统的vue3的生命周期是不同的
3)页面生命周期
uniapp的烨买安生命周期和传统的vue3的组件生命周期是不同的,uniapp有其独特的页面生命周期。
onLoad、onShow、onReady、onHide、onMounted
<template>
<view class="content">
姓名:{{name}}
</view>
<scroll-view scroll-y="true" ref="scroll">
<view></view>
</scroll-view>
<view >
计时:{{count}}
</view>
<view v-for="item in 50">{{item}}</view>
</template>
<script setup>
import { ref } from 'vue';
import {onLoad,onReady,onShow,onHide,onPageScroll} from"@dcloudio/uni-app"
const name = ref("张三")
const scroll = ref(null)
const count = ref(0)
let time = setInterval(()=>{
count.value++
},500)
//大多数的时候onLoad是用来接收携带过来的参数的,所以比较常用到
onLoad((e)=>{
console.log("onload函数,跳转到当前页面,在navigate中加的相关的数据");
console.log(e);
})
//代码中是先执行onLoad再执行onShow
//在跳转回上个页面的时候只有onShow会再次触发,不过是上个页面触发的(离开当前页面会触发)
//回到当前页面也会触发
onShow(()=>{
console.log("执行了onShow");
//回来继续计时
time = setInterval(()=>{
count.value++
},500)
})
//当a跳转到b页面时,a会触发onHide,而b会触发onShow。
onHide(()=>{
console.log("离开触发啦onHide");
//出去页面暂停
clearInterval(time)
})
//onLoad比onReady运行的更早,但是onLoad没办法拿到相关的dom元素,因为他比setup还早
//当一个标签元素绑定了ref,想要拿到相关的数据的时候就要使用onReady,有一些像onMounted,这个时候元素已经挂载上来了
onReady(()=>{
console.log(scroll.value);
})
//对页面进行滚动监听
onPageScroll((e)=>{
console.log(e);
//这个可以用作元素的显示
// if(e.scrollTop>200)
})
</script>
<style scoped>
</style>
七、uni-app项目搭建
1)rpx
市面上ui常用的工具有蓝湖、即时设计等等,使用px不会随着项目的改变而改变,一般可以用%、vw,由于手机屏幕的宽度很多,所以需要一个基准值,rpx当设计稿是750的基准稿子,假如写325px就相当于这个设计稿的一半。
2)样式导入
页面样式的权重会比app更高一些,加了scoped就不会影响到其他样式,在app文件中,常常会放一些通用的样式到这里面,比如box-sizing: border-box;(元素由padding + border + content 组成,加了这个样式后,宽度会包含这三个元素,而不是仅仅只包含content)
3)公共样式
Uniapp一般在这个文件中,放公共js、css、suss
css的引用方式如下,也和引用包的方法相类似。(注意uni.suss文件也被直接引用了,可以在那里写公共样式,也可以从common中引入相关的元素)
注意:自己主动加分号。
全局样式在page.json中,也很重要,要注意的是页面的权重大于全局,所以pages中的navigationBartitleText的优先级是大于globalStyle的。
// 全局修改
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#fff",
"backgroundColor": "#F8F8F8",
// 会直接取消导航栏
"navigationStyle": "custom",
//下拉刷新与其样式
"enablePullDownRefresh": true,
//距离底部多少的时候再进行相关的触发操作默认是50
"onReachBottomDistance": 200
"backgroundColorTop": "#ccc"
},
补充:到底加载(对应之前的上拉刷新)
//滑到底部加载
onReachBottom(()=>{
console.log("已经到底部了");
})
补充:页面样式与全局样式很类似
4)底部导航tabBar
在page.json中
//对tabBar下导航栏进行相关的配置
"tabBar": {
"selectedColor": "#1cac9d",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/index1.png",
"selectedIconPath": "static/index2.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "static/my1.png",
"selectedIconPath": "static/my2.png"
}
]
},
5)manifest
用来加载相关的id设置,尽量选择上传代码时自动压缩,在微信开发者工具里登录并填写了相关的appid的时候,可以真机预览。
6)vite.config
加入unplugin-auto-import这个插件,对满屏的import说拜拜。
npm install unplugin-auto-import
7) uni-api交互反馈
showToast
相关提示
//什么都不写就默认代表成功
//一般只支持一行7个字,但是可以将icon:"none"这个时候就可以定义多行了
uni.showToast({
title:"操作成功",
// icon:"success"
// image:"./成功.png"
mask:true,//弹窗出现的时候不能跳转,这个时候是可以跳转的
duration:3000,//默认也是300ms消失
success:res=>{
//成功后下一步走
console.log("成功了");
},
// fail: () => {
//失败后下一步走
// }
})
function hide(){
//就是在秒数没到达之前先按某个按钮让他提前被隐藏掉
uni.hideToast()
}
showLoading
//专门的loading的api,不会自动消失
uni.showLoading({
title:"加载中",
mask:true,
fail() {
//相关的操作失败的时候
uni.hideLoading()
}
})
showModal
弹窗
//弹窗与提示
function remove(){
uni.showModal({
title:"是否删除",
content:"删除后不恢复",
cancelText:"No",
confirmText:"Yes",
cancelColor:"#999",
confirmColor:"green",
success:res=>{
if(res.confirm) uni.showToast({
title:"删除成功"
})
}
})
}
showActionSheet
向上弹出的弹窗
uni.showActionSheet({
title:"请选择",
itemList:['高中',"大专","本科","研究生"]
})