Uni-app从入门到精通全网最强保姆级教程(持续更新中)

view机text常用视图容器组件

view

属性说明

属性名类型默认值说明
hover-classStringnone指定按下去的样式类。当 hover-class="none" 时,没有点击态效果
hover-stop-propagationBooleanfalse指定是否阻止本节点的祖先节点出现点击态,App、H5、支付宝小程序、百度小程序不支持(支付宝小程序、百度小程序文档中都有此属性,实测未支持)
hover-start-timeNumber50按住后多久出现点击态,单位毫秒
hover-stay-timeNumber400手指松开后点击态保留时间,单位毫秒

text组件

文本组件。用于包裹文本内容。

属性名类型默认值说明平台差异说明
selectableBooleanfalse文本是否可选
user-selectBooleanfalse文本是否可选微信小程序
spaceString显示连续空格钉钉小程序不支持
decodeBooleanfalse是否解码百度、钉钉小程序不支持

属性 HarmonyOS Next 兼容性

名称HarmonyOS Next 兼容性
selectableHBuilderX 4.23
spaceHBuilderX 4.23
decodeHBuilderX 4.23

space 值说明

说明
ensp中文字符空格一半大小
emsp中文字符空格大小
nbsp根据字体设置的空格大小
<template>
<view class="box" hover-class="boxHover">
	<view class="inner" hover-class="innerHover" hover-stop-propagation>
		内部元素	
	</view>
</view>
<view>----</view>
<text selectable space="emsp">text文本              标签</text>
</template>

<script setup>

</script>

<style lang="scss">
.box{
	width: 200rpx;
	height: 200rpx;
	background-color: red;
}
.boxHover{
	width: 500rpx;
	height: 500rpx;
background-color: blue;	
}

.inner{
width: 100rpx;
height: 100rpx;
background-color: yellow;
}
.innerHover{
	width:150rpx;
	height: 150rpx;
	background-color: green;
}

</style>

scroll-view可滚动视图区域组件

<template>
<scroll-view scroll-x class="scrollView">
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
	<view class="box">scroll子元素</view>
</scroll-view>
</template>

<script setup>

</script>

<style lang="scss">
.scrollView{
	width: 80%;
	height: 220px;
	border:1px solid red;
	white-space: nowrap;
	.box{
		width: 100px;
		height: 100px;
		background: green;
		display: inline-block;
		border: 1px solid blue;
		margin: 5px;
	}

}
</style>

swiper滑块视图容器的用法

<template>
	<view>
		<swiper indicator-dots indicator-color="blue" indicator-active-color="#4cd964" circular
		autoplay="" vertical="" duration="50000000000000"
		>
			<swiper-item>111</swiper-item>
			<swiper-item>11122</swiper-item>
			<swiper-item>11133</swiper-item>
			<swiper-item>111444</swiper-item>
			<swiper-item>111444</swiper-item>
			<swiper-item>111444</swiper-item>
			<swiper-item>111444</swiper-item>
			<swiper-item>111444</swiper-item>
		</swiper>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				
			}
		},
		methods: {
			
		}
	}
</script>

<style lang="scss">
swiper{
	width: 100vw;
	height: 200px;
	border: 1px solid green;
	swiper-item{
		width: 100%;
		height: 100%;
		background-color: pink;
	}
	swiper-item:nth-child(2n){
		background-color: orange;
	}
}


</style>

navigator路由与页面跳转

<navigator url="/pages/demo2/demo2">跳转到demo2</navigator>

常用的表单组件button和input

<button type="primary" :loading="false" :disabled="false">按钮</button>
<input type="number" placeholder="请输入搜索内容" />

vue3的模板语法插值表达式用法

<template>
<view>姓名:张三</view>
<view>{{2+3}}</view>
<view>{{a+11}}</view>
<view>{{Date.now()}}</view>
<view>{{Math.random()}}</view>
<view>{{1<2?'张三':'李四'}}</view>
<view>{{fn()}}</view>
</template>

<script setup>
const a=6;
function fn(){
	return "vue3学习"
}

</script>

<style lang="scss">

</style>

使用ref定义响应式数据变量

<template>
<view>{{num1}}</view>
<view>{{num2}}</view>
<view>{{test}}</view>
<view>{{arr}}</view>
<view>{{obj}}</view>
</template>

<script setup>
import { ref } from 'vue';
let num1=6
// setInterval(()=>{
// 	num1++;
// 	console.log(num1)
// },1000)
//响应式
let num2=ref(10);
setInterval(()=>{
	num2.value++;
	console.log(num2.value)
},1000)
let test=ref("咸鱼")
let arr=ref([1,2,3,4]);
let obj=ref({name:"黑子",age:18})
obj.value.name="小黑子"



</script>

<style lang="scss">

</style>

v-bind指令配合图片轮播案例

<template>
	<image v-bind:src="pic" mode=""></image>
	<image :src="arrs[2]" mode=""></image>
<button type="primary" :loading="false" disabled="false">按钮</button>
</template>

<script setup>
	import {
		ref
	} from "vue";
	const arrs = ref(["../../static/1.png", "../../static/2.jpg", "../../static/3.jpg", "../../static/4.jpg"])
	const pic = ref("../../static/1.png")
	let i=0;
	setInterval(()=>{
		i++;
		pic.value=arrs.value[i%4]
	},1000)
	
</script>

<style lang="scss">

</style>

class类和style内联样式的绑定

<template>
	<image v-bind:src="pic" mode=""></image>
	<image :src="arrs[2]" mode=""></image>
<button type="primary" :loading="false" disabled="false">按钮</button>
//多个样式切换
//响应式
<view class="box" :class="{active:isActive}" >
	v-bind指令多个样式切换
</view>
//三元表达式
<view class="box" :class="isActive?'active':''"></view>
<view class="box" style="width: 300px;">
	内联样式权重更高
</view>
<view class="box" :style="{width: '400px',height:100+'px',fontSize:size+'px'}">
	内联样式三目运算方法
</view>
</template>

<script setup>
	import {
		ref
	} from "vue";
	const isActive=ref(true);
	const arrs = ref(["../../static/1.png", "../../static/2.jpg", "../../static/3.jpg", "../../static/4.jpg"])
	const pic = ref("../../static/1.png")
	const size=ref(30)
	let i=0;
	setInterval(()=>{
		i++;
		size.value+=i;
		pic.value=arrs.value[i%4]
		//
		isActive.value=!isActive.value;
	},1000)
	
</script>

<style lang="scss">
.box{
	width: 200px;
	height: 200px;
	background: orange;
	font-size: 20px;
}
.active{
	background: green ;
	color: white;
}

</style>

原生事件监听及组件内置事件处理

 

<template>
<view class="box" @click="onClick" :style="{background:color}">
{{num}}
</view>
<switch :checked="false" @change="onChange" />

<button type="primary" :loading="isLoading">普通按钮</button>
</template>

<script setup>
import {proxyRefs, ref} from "vue";
const num=ref(1);
const color=ref("#fc359a");
const isLoading=ref(false);
function onClick(){
	num.value++;
	color.value="#"+String(Math.random()).substring(3,9);
	// isLoading.value=true;
	console.log(String(Math.random()).substring(3,9))
}
function onChange(e){
	console.log(e.detail)
	isLoading.value=e.detail.value;
}

</script>

<style lang="scss">
.box{
	width: 200px;
	height: 200px;
	background: orange;
}


</style>

创建自定义模板快速创建uniapp的vue3页面结构

<template>
	<view class="">
		
	</view>
</template>
<script setup>
	
</script>
<style lang="scss" scoped>
	
</style>

v-if条件渲染及v-show的选择对比

<template>
	<view v-if="shop">京东</view>
     <view v-else>淘宝网</view>
<view v-if="day===1">星期一</view>
<view v-else-if="day===2">星期二</view>
<view v-else-if="day===3">星期三</view>
<view v-else-if="day===4">星期四</view>
<view v-else-if="day===5">星期五</view>
<view v-else-if="day===6">星期六</view>
<view v-else-if="day===7">星期天</view>
<view v-else>格式错误</view>

<view class="box1" v-if="true">
	<image src="../../static/2.jpg" mode=""></image>
</view>
<view class="box" v-show="true">
	<image src="../../static/3.jpg" mode=""></image>
</view>
<template v-if="false">
<image src="../../static/1.png" mode=""></image>
<view>logo</view>
</template>
<template v-else>
<image src="../../static/4.jpg" mode=""></image>
<view>A
	pic4
</view>
</template>

</template>
<script setup>
	import{ref} from "vue";
	const shop =ref(true)
	const day=ref(30)
</script>
<style lang="scss" scoped>	
</style>

v-for列表渲染的用法

<template>
<view class="out">
	<view class="box" v-for="(i,index) in 10" :key="index">box模块-{{index+1}}</view>
	<view v-for="i in nba" :key="i.id">{{i.name}}----{{i.num}}号</view>
</view>
</template>
<script setup>
import {ref} from "vue";
const nba=ref([
	{id:"1",name:"乔当",num:23},
	{id:"2",name:"詹姆斯",num:6},
	{id:"3",name:"科比",num:24},
])


</script>
<style lang="scss" scoped>	


</style>

[购物车案例]for循环为什么使用key

<template>
	<view class="out">
		<view class="item" v-for="(i,index) in goods" :key="i.id">
			<checkbox></checkbox>
			<text class="title">{{i.name}}</text>
			<text class="del" @click="remove(index)">删除</text>
		</view>
	</view>
</template>
<script setup>
	import {
		ref
	} from "vue";
	const goods = ref([{
			id: 11,
			name: "小米"
		},
		{
			id: 22,
			name: "华为"
		},
		{
			id: 33,
			name: "oppo"
		},
		{
			id: 44,
			name: "苹果"
		},
	])

	function remove(e) {
		console.log(e);
		goods.value.splice(e, 1)
	}
</script>
<style lang="scss" scoped>
	.out {
		padding: 10px;

		.item {
			padding: 0px 0;

			.del {
				padding-left: 10px;
				color: red;
			}
		}
	}
</style>

【小鸡案例】表单focus和blur事件用法

 

 

<template>
	<view class="out">
	<input type="text" :value="iptValue" @focus="onFocus" @blur="onBlur"/>
	<input type="text" :value="iptValue" @focus="isActive=true" @blur=""/>
	<image src="../../static/chicken.gif" mode="" class="pic" :class="isActive?'active':''"></image>
	</view>
</template>
<script setup>
import{ref} from "vue";
const iptValue =ref("");
const isActive=ref(false)
function onFocus(e){
	isActive.value=true;
}
function onBlur(e){
	isActive.value=false;
}
</script>
<style lang="scss" scoped>
	.out {
		padding: 0 20px;
		margin-top: 40px;
		position: relative;
		input{
		border: 1px solid #ccc;
			height: 40px;
			position: relative;
			z-index: 2;
			background: #fff;
		}
		.pic{
			width: 24px;
			height: 24px;
			z-index: 1;
			position: absolute;
			top: 0px;
			left: calc(50% - 12px);
			transition: top 0.3s;
		}
		.pic.active{
			top: -24px;
		}
	}
</style>as

v-model双向绑定的实现原理

<template>
	<view class="out">
	<input type="text" :value="iptValue" @focus="onFocus" @blur="onBlur" @input="event=>iptValue=event.detail.value" @confirm="onConfirm"/>
	<input type="text" :value="iptValue"  v-model="iptValue" @focus="isActive=true" @blur=""/>
	<image src="../../static/chicken.gif" mode="" class="pic" :class="isActive?'active':''"></image>
	</view>
	<view>预览:{{iptValue}}</view>
</template>
<script setup>
import{ref} from "vue";
const iptValue =ref("");
const isActive=ref(false);
function onConfirm(e){
	console.log(e);
}
function onInput(e){
	iptValue.value=e.detail.value;
}
function onFocus(e){
	isActive.value=true;
}
function onBlur(e){
	isActive.value=false;
}
</script>
<style lang="scss" scoped>
	.out {
		padding: 0 20px;
		margin-top: 40px;
		position: relative;
		input{
		border: 1px solid #ccc;
			height: 40px;
			position: relative;
			z-index: 2;
			background: #fff;
		}
		.pic{
			width: 24px;
			height: 24px;
			z-index: 1;
			position: absolute;
			top: 0px;
			left: calc(50% - 12px);
			transition: top 0.3s;
		}
		.pic.active{
			top: -24px;
		}
	}
</style>as

【热梗案例】知识点阶段性综合汇总

<template>
	<view class="title">
		近期热梗
	</view>
	<view class="out">	  
<view class="list">
			<view class="row" v-for="(item,index) in lists" :key="item.id">
				<view class="text">{{index+1}}. {{item.title}}</view>
				<view class="close" @click="onClose(index)">
					<icon type="clear" size="26" />
				</view>
			</view>
		</view>
		<view class="count">
			共{{lists.length}}条梗
		</view>
		<view class="comment">
			<input type="text" placeholder="请输入热梗..." v-model="iptValue" 
			@confirm="onSubmit"
			/>
			<button size="mini" type="primary" :disabled="!iptValue.length" @click="onSubmit"
			
			>发布</button>
		</view>
	</view>
</template>

<script setup>
	import {
		ref
	} from "vue";
	const iptValue = ref("");
	const lists = ref([{
			id: 111,
			title: "刚满18岁"
		},
		{
			id: 222,
			title: "我不吃牛肉"
		},
		{
			id: 333,
			title: "遥遥领先"
		},
		{
			id: 444,
			title: "哪里贵了"
		}
	])
	const onClose = function(index) {
		lists.value.splice(index, 1)
	}
	const onSubmit = function() {
		lists.value.push({
			id: Date.now(),
			title: iptValue.value
		});
		iptValue.value = "";
	}
</script>

<style lang="scss" scoped>
	.title {
		font-size: 26px;
		text-align: center;
		color: #3c3c3c;
		padding: 30px 0 15px;
	}

	.out {
		width: 90vw;
		margin: 15px auto;
		box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
		border-radius: 5px;
		padding: 15px;
		box-sizing: border-box;

		.list {
			.row {
				padding: 10px 0;
				border-bottom: 1px solid #e8e8e8;
				display: flex;
				justify-content: space-between;
				align-items: center;
				font-size: 18px;
				color: #333;

				.text {
					padding-right: 5px;
					box-sizing: border-box;
				}
			}
		}

		.count {
			padding: 10px 0;
			font-size: 15px;
			color: #888;
			text-align: center;
		}

		.comment {
			display: flex;
			margin-top: 10px;

			input {
				flex: 4;
				background: #f4f4f4;
				margin-right: 5px;
				height: 100%;
				height: 32px;
				border-radius: 4px;
				padding: 0 10px;
				color: #333;
			}

			button {
				flex: 1;
			}
		}
	}
</style>

computed计算属性用法及方法对比

<template>
	<view class="out">
		<input type="text" v-model="firstName" placeholder="请输入名"/>
		<input type="text" v-model="lastName" placeholder="请输入姓"/>
		<view>全称:{{fullName}}</view>
		<view>全称:{{fullname}}</view>
		<view>全称{{fulllname()}}</view>
	</view>
</template>

<script setup>
	import {computed, ref} from "vue";
const firstName	=ref("");
const lastName=ref("");
const fullName=computed(()=>firstName.value-lastName.value)
const fullname=computed(()=>{
	return firstName.value+"-"+lastName.value;
});
const fulllName=function(){
	return firstName.value+"-"+lastName.value;
}
</script>
<style lang="scss" scoped>
	.out{
	padding: 20px;
	input{
		border: 1px solid #ccc;
		height: 40px;
		padding: 0 10px;
		margin: 10px 0;
	}	
	}
</style>

【计价案例】计算属性配合循环遍历统计总价

<template>
	<view class="out">
		<checkbox-group @change="itemChange">
			

		<view class="item" v-for="(i,index) in goods" :key="i.id">
			<checkbox :value="i.id" :checked="i.checked"></checkbox>
			<text class="title">{{i.name}}</text>
			<text class="price">{{i.price}}</text>
			<text class="del" @click="remove(index)">删除</text>
		</view>
				</checkbox-group>
		<view class="card">
			<view class="text">
				选中了{{totalNumber}}个产品,总价:{{totalPrice}}元
			</view>
		</view>
		{{selectGroup}}
		<view>---</view>
		{{goods}}
	</view>
</template>
<script setup>
	import {
		computed,
		ref
	} from "vue";
	const goods = ref([{
			id: "11",
			name: "小米",
			price:999,
			checked:false,
		},
		{
			id: "22",
			name: "华为",
			price:699,
			checked:false,
		},
		{
			id: "33",
			name: "oppo",
			price:699,
			checked:false,
		},
		{
			id: "44",
			name: "苹果",
			price:699,
			checked:false,
		},
	])
const selectGroup=ref([]);
const totalNumber=computed(()=>selectGroup.value.length);
const totalPrice=computed(()=>{
	return goods.value.filter(item=>item.checked).reduce((prev,curr)=>prev+curr.price,0)
});
	function remove(e) {
		console.log(e);
		goods.value.splice(e, 1)
	}
	function itemChange(e){
		selectGroup.value=e.detail.value;
		goods.value.forEach(item=>{
			item.checked=selectGroup.value.includes(item.id);
		})
	};
</script>
<style lang="scss" scoped>
	.out {
		padding: 10px;

		.item {
			padding: 10px 0;

			.price {
				margin-left: 30px;
			}

			.del {
				color: #c00;
				margin-left: 30px;
			}
		}
		.card{
			margin-top:30px;
			border-top:1px solid #eee ;
			padding: 10px;
		}
	}
</style>

watch和watchEffect监听的使用

在Vue3中,computed和watch都是用于响应式地处理数据变化的工具,但它们有一些重要的异同点。

异同点如下:

计算属性 (Computed):

  • 计算属性是基于它们的依赖进行缓存的。只有在依赖发生变化时,计算属性才会重新计算,可以避免不必要的重复计算。
  • 计算属性适用于派生出一些新的数据,比如对数据进行过滤、排序、格式化等操作。
  • 计算属性可以像普通属性一样使用,而不需要在模板中调用方法。
  • 计算属性中的函数必须有return返回值


监听属性 (Watch):

  • 监听属性允许我们在数据变化时执行异步操作或复杂的逻辑。
  • 监听属性适用于对数据变化做出响应,比如在数据变化时发送请求、处理副作用等。
  • 监听属性可以监听一个或多个数据的变化,并在数据变化时执行相应的操作。
  • 监听属性中的函数不是必须要用return返回值。

相似之处:

  • 计算属性和监听属性都可以依赖于响应式数据。
  • 它们都可以用于监测数据的变化,并作出相应的处理。

总的来说,计算属性适用于派生出新的数据,而监听属性适用于在数据变化时执行异步操作或复杂逻辑。

<template>
	<view class="">
		<input type="text" v-model="person.name" />

		
	</view>
	{{person}}
</template>
<script setup>
	import {ref,watch} from "vue";
	const person=ref({
		name:"张三",
		age:23
	});
	
	// watch(()=>person.value.name,(newValue)=>{
	// 	console.log(newValue);
			
	// })
//深度监听	
	watch(person,(newValue)=>{
		console.log(newValue)
	},{deep:true,immediate:true})
	
</script>
<style lang="scss" scoped>
	
</style>

<template>
	<view class="out">
		<input type="text" v-model="firstName" placeholder="请输入名"/>
		<input type="text" v-model="lastName" placeholder="请输入姓"/>
		
		<view>全称:{{fullName}}</view>
	</view>
</template>

<script setup>
	import {computed, ref, watch,watchEffect} from "vue";
const firstName	=ref("迈克尔");
const lastName=ref("乔丹");
const fullName=ref("");
// watch([firstName,lastName],([NfirstName,NlastName],[OfirstName,OlastName])=>{
// 	console.log(NfirstName,NlastName);
// 	console.log(OfirstName,OlastName);
// })
watchEffect(()=>{
	console.log(firstName.value,lastName.value)
})
</script>
<style lang="scss" scoped>
	.out{
	padding: 20px;
	input{
		border: 1px solid #ccc;
		height: 40px;
		padding: 0 10px;
		margin: 10px 0;
	}	
	}
</style>

uniapp创建组件、vue官方文档的差异对比以及在组件中通过Props进行数据传递

<template>
	<view class="content">
	<!-- 	<UserInfo username="咸虾米" avatar="../../static/4.jpg"></UserInfo>
		<UserInfo :username="name" avatar="../../static/3.jpg"></UserInfo>
		<UserInfo username="李四" avatar="../../static/2.jpg"></UserInfo> -->
		<view>{{name}}111</view>
		<UserInfo :obj="userinfo"></UserInfo>
		<xxm-header></xxm-header>
	</view>
</template>

<script setup>
	import {ref} from "vue";
const userinfo=ref({name:"张三",avatar:"../../static/4.jpg"})
</script>

<style>

</style>

<template>
	<view class="userinfo">
		<image :src="obj.avatar" mode="" class="avatar"></image>
		<view class="username">{{obj.name}}</view>
	
	</view>
</template>

<script setup>
import { computed,defineProps } from 'vue';
const props = defineProps({
	username: {
		type: String,
		required: true
	},
	avatar: {
		type: String,
		required: true
	},
	obj:{
		type:Object,
		default:()=>({})
	}
});
const myname=computed(()=>props.username+"@")
console.log(props)
</script>

<style lang="scss" scoped>
.userinfo{
	width: 100%;
	height: 200px;
	background: #ccc;
	display: flex;
	flex-direction: column;
	image{
		width: 100px;
		height: 100px;
	}
}
</style>

<template>
	<view>
		这是header组件
	</view>
</template>

<script>
	export default {
		name:"xxm-header",
		data() {
			return {
				
			};
		}
	}
</script>

<style lang="scss">

</style>

Prop校验与prop默认值用法及循环遍历数组对象

<template>
	<view class="content">
	<!-- 	<UserInfo username="咸虾米" avatar="../../static/4.jpg"></UserInfo>
		<UserInfo :username="name" avatar="../../static/3.jpg"></UserInfo>
		<UserInfo username="李四" avatar="../../static/2.jpg"></UserInfo> -->
		<view>{{name}}111</view>
		<!-- <UserInfo :obj="userinfo"></UserInfo> -->
		<UserInfo v-for="(item,index) in userinfo" :obj="item"></UserInfo>
		<xxm-header></xxm-header>
	</view>
</template>

<script setup>
	import {ref} from "vue";
const userinfo=ref([{name:"张三",avatar:"../../static/4.jpg"},
{name:"李四",avatar:"../../static/2.jpg"},
{name:"王五",avatar:"../../static/3.jpg"},
])
</script>

<style>

</style>
<template>
	<view class="userinfo">
		<image :src="obj.avatar" mode="" class="avatar"></image>
		<view class="username">{{obj.name}}</view>
	
	</view>
</template>

<script setup>
import { computed,defineProps } from 'vue';
const props = defineProps({
	username: {
		type: String,
		required: true
	},
	avatar: {
		type: String,
		required: true
	},
	obj:{
		type:Object,
		default:()=>{
			return {name:"匿名",avatar:"../../static/logo.png"}
		}
	}
});
const myname=computed(()=>props.username+"@")
console.log(props)
</script>

<style lang="scss" scoped>
.userinfo{
	width: 100%;
	height: 200px;
	background: #ccc;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	image{
		width: 100px;
		height: 100px;
		border-radius: 50%;
	}
	.username{
		padding: 10px 0;
		font-size: 20px;
	}
}
</style>

插槽Slots及具名插槽实现组件高度定制化


demo1.vue

<template>
	<view class="">
		<xxm-layout>
			<view class="row" v-for="(item,index) in 10">每一行{{item}}</view>
		</xxm-layout>
	</view>
</template>
<script setup>
	
</script>
<style lang="scss" scoped>
	
</style>

demo2.vue

<template>
	<view class="">
		<xxm-layout>
			<template #header>
				demo2的头部
			</template>
			<template #main>
				<view class="main">

				</view>
			</template>
		</xxm-layout>
	</view>
</template>
<script setup>

</script>
<style lang="scss" scoped>
	.main {
		width: 100px;
		height: 100px;
		background: pink;
	}

	.box1 {
		width: 100px;
		height: 100px;
		background: pink;
	}

	.box2 {
		width: 130px;
		height: 130px;
		background: green;
	}
</style>

xxm-layout.vue

<template>
	<view class="layout">
		<view class="header">
			<slot name="header"></slot>
		</view>
		<view class="main">
			<slot name="main"></slot>
		</view>
		<view class="footer">
			底部内容区
		</view>
	</view>
</template>

<script setup>
	
	
</script>

<style lang="scss">
.layout{
	.header{
		height: 100px;
		background: #cfcfcf;
	}
	.main{
		min-height: 200px;
	}
	.footer{
		height: 120px;
		background: orange;
	}
}
</style>

组件中emit的声明触发事件

<template>
	<view class="">
		<xxm-child @add="onAdd" @change="onChange"></xxm-child>
		<view class="box" :style="{background:color,fontSize:size+'px',}">num:{{num}}</view>
	</view>
</template>
<script setup>
	import{ref} from "vue"
	const num=ref(0)
	const color=ref('#ccc')
	const size=ref(12)
	const onAdd=function(e){
		console.log(e);
		num.value=e;
		color.value="#"+String(e).substring(3,6)
	}
	const onChange=function(e){
		console.log(e);
		size.value=e;
	}
</script>
<style lang="scss" scoped>
	.box{
		width: 200px;
		height: 200px;
		background: red;
	}
</style>

<template>
	<view>
		子组件
		<!-- <button @click="$emit('add',Math.random())">按钮</button> -->
		<button @click="onClick">按钮</button>
		<view>----</view>
		<input type="text" @input="onInput"/>
	</view>
</template>

<script setup>
import {ref} from "vue";
	const emit=defineEmits(["add","change"])
function onClick(){
	emit("add",Math.random())
}
function onInput(e){
	console.log(e.detail.value);
	emit("change")
}
</script>

<style lang="scss" scoped>
input{
	border: 1px solid #cfcfcf;
	height: 40px;
}
</style>

vue3组合式API中的组件的生命周期函数(钩子函数)

vue3组合式API中的组件的生命周期函数(钩子函数)

<template>
	<view class="layout">
		<scroll-view scroll-x scroll-y="true" class="scroll" ref="scroll">
			<view></view>
		</scroll-view>
		<life-demo v-if="show"></life-demo>
	</view>
</template>
<script setup>
	import {onMounted, ref} from "vue";
	const scroll=ref(null);
	const show=ref(true)
	setTimeout(()=>{
		show.value=false
	},2000)
	
	onMounted(()=>{
		console.log(scroll.value);
	})
	
</script>
<style lang="scss" scoped>
	
</style>

<template>
	<view>
		子组件
	</view>
</template>

<script setup>
import { onMounted,onUnmounted,ref } from 'vue';
onUnmounted(()=>{
	console.log("子组件被卸载了")
})


</script>

<style lang="scss">

</style>

使用defineExpose暴漏子组件的属性及方法

<template>
	<view class="layout">
	<demo-child ref="child"></demo-child>
		<view>----</view>
		<button @click="update">点击修改子值+1</button>
	</view>
</template>
<script setup>
	import {onMounted, ref} from "vue";
	const child=ref(null);
	const update=function(){
		child.value.updateCount();
	}
	onMounted(()=>{
	console.log(child.value);
	})

</script>
<style lang="scss" scoped>
	
</style>

<template>
	<view class="out">
		子组件1111count值:{{count}}
	</view>
</template>

<script setup>
import {ref} from "vue";
const count=ref(100)
const updateCount=function(){
	count.value++
}

defineExpose({
	count,
	str:"闲虾米",
	updateCount,
})
</script>

<style lang="scss" scoped>
.out{
	padding: 20px;
	background: #eee;
}


</style>

页面生命周期onLoad和onReady在vue3组合式api中的使用

<navigator url="/pages/demo6/demo6?name=王五&age=20">跳转到demo6</navigator>

<template>
	<view class="">
		姓名:{{name}} - {{age}}
		<scroll-view scroll-y="true" ref="scroll">
			<view></view>
		</scroll-view>
	</view>
</template>
<script setup>
 import {ref} from "vue"
 import {onLoad,onReady} from "@dcloudio/uni-app"
 const name=ref("张三")
 const age=ref(18)
 const scroll=ref(null)
 onLoad((e)=>{
	 console.log("onload函数");
	 console.log(scroll.value)
	 console.log(e);
	 name.value=e.name;
	 age.value=e.age;
 })
onReady((e)=>{
	console.log(scroll.value);
})

</script>
<style lang="scss" scoped>
	
</style>

 

onShow和onHide钩子的对比和执行顺序

<template>
	<view class="layout">
	<demo-child ref="child"></demo-child>
		<view>----</view>
		<button @click="update">点击修改子值+1</button>
		<navigator url="/pages/demo6/demo6?name=王五&age=20">跳转到demo6</navigator>
	</view>
</template>
<script setup>
	import {onMounted, ref} from "vue";
	const child=ref(null);
	const update=function(){
		child.value.updateCount();
	}
	onMounted(()=>{
	console.log(child.value);
	
	})

</script>
<style lang="scss" scoped>
	
</style>

<template>
	<view class="">
		姓名:{{name}} - {{age}}
		<scroll-view scroll-y="true" ref="scroll">
			<view></view>
		</scroll-view>
		<navigator url="/pages/demo5/demo5">跳转demo5</navigator>
		<view>----</view>
		<view>计数:{{count}}</view>
	</view>
</template>
<script setup>
 import {onBeforeMount, onMounted, ref} from "vue"
 import {onLoad,onReady,onShow,onHide} from "@dcloudio/uni-app"
 const name=ref("张三")
 const age=ref(18)
 const scroll=ref(null)
 const count=ref(0)
 let time=setInterval(()=>{
	 count.value++
 },50)
 
 onLoad((e)=>{
	 console.log("onload函数");
	 console.log(scroll.value)
	 console.log(e);
	 name.value=e.name;
	 age.value=e.age;
 })
 onShow(()=>{
	 console.log("onShow函数");
  time=setInterval(()=>{
  	 count.value++
  },50)
 })
 onHide(()=>{
	 console.log("onHide函数");
	 clearInterval(time)
 })
onReady((e)=>{
	console.log("onReady");
})
onBeforeMount(()=>{
	console.log("onBeforeMount函数")
})
onMounted(()=>{
	
	console.log("onMounted函数");
})
</script>
<style lang="scss" scoped>
	
</style>

onUnload页面卸载和onPageScroll监听页面滚动

<template>
	<view class="">
		姓名:{{name}} - {{age}}
		<scroll-view scroll-y="true" ref="scroll">
			<view></view>
		</scroll-view>
		<navigator url="/pages/demo5/demo5">跳转demo5</navigator>
		<view>----</view>
		<view>计数:{{count}}</view>
		<view>----</view>
		<navigator open-type="reLaunch" url="/pages/demo4/demo4">demo4页面</navigator>
	<view v-for="item in 50">{{item}}</view>
	<view class="fixed" v-if="fixed">^</view>
	</view>
</template>
<script setup>
 import {onBeforeMount, onMounted, ref} from "vue"
 import {onLoad,onReady,onShow,onHide,onUnload,onPageScroll} from "@dcloudio/uni-app"
 const name=ref("张三")
 const age=ref(18)
 const scroll=ref(null)
 const count=ref(0)
 const fixed=ref(false)
 let time=setInterval(()=>{
	 count.value++
 },50)
 
 onLoad((e)=>{
	 console.log("onload函数");
	 console.log(scroll.value)
	 console.log(e);
	 name.value=e.name;
	 age.value=e.age;
 })
 onShow(()=>{
	 console.log("onShow函数");
  time=setInterval(()=>{
  	 count.value++
  },50)
 })
 onHide(()=>{
	 console.log("onHide函数");
	 clearInterval(time)
 })
onReady((e)=>{
	console.log("onReady");
})
onBeforeMount(()=>{
	console.log("onBeforeMount函数")
})
onMounted(()=>{
	
	console.log("onMounted函数");
})
onUnload(()=>{
	console.log("卸载页面")
})
onPageScroll((e)=>{
	console.log(e.scrollTop);
	// if(e.scrollTop>200){
	// 	fixed.value=true
	// }else{
	// 	fixed.value=false
	// }
	fixed.value=e.scrollTop>200
})
</script>
<style lang="scss" scoped>
	.fixed{
		width: 100px;
		height: 100px;
		background: orange;
		position: fixed;
		bottom: 100px;
		right:20px;
	}
	
</style>

响应式单位rpx及搭配使用UI产品工具

rpx和px的区别

rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应。
规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px

设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)
iPhone5 1rpx = 0.42px    1px = 2.34rpx
iPhone6 1rpx = 0.5px     1px = 2rpx
iPhone6s 1rpx = 0.552px    1px = 1.81rpx

@import导入css样式及scss变量用法与static目录

<template>
	<view class="layout">
		<view class="box">这是box</view>
		<view class="text">
			欢迎使用
		</view>
	</view>
</template>
<script setup>
	
</script>
<style lang="scss" scoped>
	.box{
		width: 200px;
		height: 200px;
		background: orange;
		font-size: 28rpx;
	}
	.text{
		font-size: 52rpx;
		color: $custom-color-2;
	}
</style>

uni.scss

@import "@/common/scss/self.scss";

self.scss

$custom-color-1:red;
$custom-color-2:green;
$custom-color-3:#35570f;

pages.json页面路由globalStyle的属性

<template>
	<view class="content">
	<image src="../../static/logo.png" mode=""></image>
	<view class="" v-for="item in 100">
		{{item}}
	</view>
	</view>
</template>

<script setup>
import  {onReachBottom} from "@dcloudio/uni-app"
onReachBottom(()=>{
	console.log("到底了")
})

</script>

<style>
.content{
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
</style>

pages设置页面路径及窗口表现

{
	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
		{
			"path": "pages/index/index",
			"style": {
				"navigationBarTitleText": "uni-app"
			}
		},
		{
			"path": "pages/user/user",
			"style": {
				"navigationBarTitleText": "用户中心"
			}
		},
		{
			"path" : "pages/classify/classify",
			"style" : 
			{
				"navigationBarBackgroundColor": "#F2E6DE",
				"navigationBarTextStyle": "black",
				"navigationBarTitleText": "分类",
				"enablePullDownRefresh": true
			}
		},
		
		{
			"path" : "pages/demo1/demo1",
			"style" : 
			{
				"navigationBarTitleText" : "demo1"
			}
		},
		{
			"path" : "pages/demo2/demo2",
			"style" : 
			{
				"navigationBarTitleText" : "demo2"
			}
		},
		{
			"path" : "pages/demo3/demo3",
			"style" : 
			{
				"navigationBarTitleText" : "demo3"
			}
		},
		{
			"path" : "pages/demo4/demo4",
			"style" : 
			{
				"navigationBarTitleText" : "44444"
			}
		},
		{
			"path" : "pages/demo5/demo5",
			"style" : 
			{
				"navigationBarTitleText" : "d5"
			}
		},
		{
			"path" : "pages/demo6/demo6",
			"style" : 
			{
				"navigationBarTitleText" : "666"
			}
		},
		{
			"path" : "pages/demo7/demo7",
			"style" : 
			{
				"navigationBarTitleText" : "777"
			}
		}

	],
	"globalStyle": {
		"backgroundColor": "#CAF0DF",
		"navigationBarTextStyle": "white",
		"navigationBarTitleText": "闲虾米",
		"navigationBarBackgroundColor": "#2B9939",
		// "navigationStyle": "custom"
		"enablePullDownRefresh": true,
		"backgroundTextStyle": "light",
		"onReachBottomDistance": 50
	},
	"uniIdRouter": {}
}

tabBar设置底部菜单选项及iconfont图标

 

	"tabBar": {
		"color": "#999",
		"selectedColor": "#fe1c32",
		"backgroundColor": "#ccc",
		"borderStyle": "black",
		// "position": "top",
		"list": [
			{
				"pagePath": "pages/index/index",
				"text": "首页",
				"iconPath": "static/tabBar/home.png",
				"selectedIconPath": "static/tabBar/home-h.png"
			},{
				"pagePath": "pages/classify/classify",
				"text": "分类",
				"iconPath": "static/tabBar/user.png",
				"selectedIconPath": "static/tabBar/user-h.png"
			}
		]
	},

manifest.json配置和注册微信小程序a ppid

vite.config中安装插件unplugin-auto-import自动导入vue和uniapp

开发uniapp使用Vue3组合式API版本,如何实现从vue模块中自动导入

uni-api交互反馈showToast的用法

showLoading加载和showModal模态框示例

showLoading加载和showModal模态框示例

showActionsheet从底部向上弹出操作菜单

showActionsheet从,底部向上弹出操作菜单

动态设置页面导航条的样式

uniapp动态页面API

setTabBar设置TabBar和下拉刷新API

tabBar设置底部菜单选项以及iconfont图标,setTabBar设置TabBar和下拉刷新API

页面和路由APl-navigateTo及页面栈getCurrentPages

uniapp路由与页面跳转详解:API调用与Navigator组件实战

StorageSync数据缓存API

小程序本地存储API·同步和异步的区别

<template>
	<view class="content">
	<button @click="remove">删除一个</button>
	<button @click="clear" type="warn">删除全部</button>
	</view>
</template>

<script setup>

uni.setStorageSync('sbcwe','hello');
uni.setStorageSync('sbcwe','黑子说话');
uni.setStorageSync('arr',[1,2,3]);
let kk=uni.getStorageSync("sbcwe");
console.log(kk);
const res=uni.getStorageInfoSync();
console.log(res);
function remove(){
	uni.removeStorageSync("arr")
}
function clear(){
	uni.clearStorageSync();
}
</script>

<style>
.content{
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}
</style>

uni.request发起网络请求3种回调结果调用

<template>
	<view class="layout">
		<view class="row" v-for="item in arrs" :key="item.id">
			<view class="title">{{item.title}}</view>
			<view class="content">{{item.body}}</view>
		</view>
	</view>
	<button @click="request">获取</button>
</template>

<script setup>
import {ref} from "vue";
let arrs=ref([]);

// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts",
// 		success:res=>{
// 			console.log(res)
//            arrs.value=res.data
// 		}
// 	})
// }
// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts",
// 	}).then(res=>{
// 		arrs.value=res.data
// 	})
// }

async function request(){
	let res=await uni.request({
		url:"https://jsonplaceholder.typicode.com/posts",
	})
	arrs.value=res.data
}

request();
</script>

<style>
.layout{
	padding: 30rpx;
	background-color: aqua;
	.row{
		border-bottom: 1px solid #cfcfcf;
		padding: 20rpx 0;
		
		.title{
			font-size: 36rpx;
		}
		.content{
			font-size: 28rpx;
			color: #666;
		}
	}
}
</style>

request各种不同类型的参数详解

<template>
	<view class="layout">
		<view class="row" v-for="item in arrs" :key="item.id">
			<view class="title">{{item.title}}</view>
			<view class="content">{{item.body}}</view>
		</view>
	</view>
	<button @click="request">获取</button>
</template>

<script setup>
import {ref} from "vue";
let arrs=ref([]);

// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts",
// 		success:res=>{
// 			console.log(res)
//            arrs.value=res.data
// 		}
// 	})
// }
// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts",
// 	}).then(res=>{
// 		arrs.value=res.data
// 	})
// }

// async function request(){
// 	let res=await uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts",
// 	})
// 	arrs.value=res.data
// }

// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts/3",
// 		success: (res) => {
// 			console.log(res)
// 		}
// 	})
// }
// function request(){
// 	uni.request({
// 		url:"https://jsonplaceholder.typicode.com/posts?id=3&userId=1",
// 		success: (res) => {
// 			console.log(res)
// 			arrs.value=res.data
// 		}
// 	})
// }
function request(){
	uni.showLoading()
	uni.request({
		url:"https://jsonplaceholder.typicode.com/posts",
		data:{
		id:5,
		userId:1
		},
		header:{
			token:"44564",
			"content-type":"application/x-www-form-urlencode"
		},
		method:"GET",
		timeout:1000,
		success: (res) => {
			console.log(res)
			arrs.value=res.data
		},
		fail:err=> {
			console.log("超时");
			console.log(err);
		},
		complete() {
			uni.hideLoading();
		}
		
	})
}

request();
</script>

<style>
.layout{
	padding: 30rpx;
	background-color: aqua;
	.row{
		border-bottom: 1px solid #cfcfcf;
		padding: 20rpx 0;
		
		.title{
			font-size: 36rpx;
		}
		.content{
			font-size: 28rpx;
			color: #666;
		}
	}
}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值