type
status
date
slug
summary
tags
category
icon
password
这里写文章的前言:
一个简单的开头,简述这篇文章讨论的问题、目标、人物、背景是什么?并简述你给出的答案。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。
📝 毕设专项----uniapp Vue3组合式API版本到咸虾米壁纸项目
uni-app介绍
是一个使用Vue.js开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/QQ/百度/淘宝/飞书/头条等等)、快应用等多个平台
开源项目被打如何防守,咸虾米也有讲
项目目录介绍
pages
:业务页面文件存放目录static
:存放应用引用的本地静态资源(如图片、视频等)的目录,注意:静态资源都应存放在此目录App.vue
:应用配置,用来配置App全局样式以及监听 应用生命周期main.js
:Vue初始化入库文件uni.scss
:css预编译器pages.json
:配置页面路由、导航条、选项卡等页面信息manifest.json
:配置应用名称、appid、logo、版本等打包信息不同点
最常用标签不是
div
,而是 view
1.4.创建页面及vue页面内基本组成部分
template模板区
vue3可以放多个<view>在同一级,而vue2最外层只能有一个<view>,
view
和 div
类似,<template>
<view class="layout">
<view class="box1">box1</view>
<view class="box2">box2</view>
</view>
</template>
script逻辑区
vue2的逻辑区是选项式API
vue3的逻辑区是组合式API
<script setup>
</script>
styleCSS样式区
<style lang="scss">
.layout {
border: 1px solid red;
</style>
- 注意:样式区好像对顺序有要求,template中在后面的class名,在style中也要在后面
pages.json页面路由
要想新增页面,就在pages里面填写
2.1.view和text常用视图容器组件
view视图容器
类似于传统html的div,用于包裹各种元素内容
如果使用nvue,则需要注意,包裹文字应该使用<text>组件。
属性说明
hover-class:string类型,指定按下去的样式类,默认是hover-class="none"时,没有点击态效果
hover-stop-propagation:boolean类型,指定是否组织本节点的祖先节点出现点击态,默认是false
hover-start-time:number属性,按住多久后出现点击态,单位毫秒
hover-stay-time:number属性,手指松开后点击态保留时间,单位毫秒
text文本组件
类似span,用于包裹文本内容
在app-uvue和app-nvue中,文本只能写在text中,而不能写在view的text区域。
虽然app-uvue中写在view的text区域的文字,也会被编译器自动包裹一层text组件,看起来也可以使用,但这样会造成无法修改text文字的样式。
属性说明
selectable:boolean类型,文本是否可选,默认false
user-select:boolean类型,文本是否可选,默认false,微信小程序版
space:string类型,显示连续空格,space值说明:
- ensp,中文字符空格一半大小
- emsp,中文字符空格大小
- nbsp,根据字体设置的空格大小
decode:boolean类型,是否解码,默认false
2.2.scroll-view可滚动视图区域组件
scroll-view可滚动视图区域
用于区域滚动,需注意在webview渲染的页面中,区域滚动的性能不及页面滚动
属性说明
scroll-x:允许横向滚动,默认false
scroll-y:纵向
upper-threshold:距顶部/左边多远时,触发scrolltoupper事件,默认50px
lower-threshold:底部/右边
scroll-top:设置竖向滚动条位置
scroll-left:横向
...更多属性说明
2.3.swiper滑块视图容器的用法
一般用于左右滑动或上下滑动,如banner轮播图
注意滑块切换和滚动的区别,滑块切换是一屏一屏的切换,swiper下的每个swiper-item是一个滑动切换区域,不能停了在两个滑动区域之间
属性说明
indicator-dots,是否显示面板指示点(图片数量点点,到了第几张),默认false
indicator-color,指示点的颜色
indicator-active-color,当前选中的指示点颜色
active-class,swiper-item可见时的class
autoplay,是否自动切换,默认false
current,当前所在滑块的index,默认0
current-item-id,当前所在滑块的item-id,不能与current被同时指定
interval,自动切换时间间隔,默认5000ms
duration,滑动动画时长,默认500ms
cicular,是否衔接滑动,即播放到末尾后重新回到开头
vertical,滑动方向是否为纵向
...更多属性说明
视图单位
100,整个全屏
100vw,一整行
50vw,半行
100vh,屏幕可视区域的100%
50vh,屏幕可视区域的50%,高度上
2.4.image媒体组件属性配合swiper轮播
<image src="/static/pic1.jpg" mode="" class="pic1"></image>
src,图片地址,将图片放在static目录下可直接选取,也可直接使用网图(小程序限制打包的大小)
mode,裁剪、缩放模式(5种缩放,9种裁剪)
- scaleToFill,不保持纵横比缩放图片,是图片的宽高完全拉伸至填满image元素
- aspectFit,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来
- aspectFill,保持纵横比缩放坨,短边,会在水平或垂直方向是完整的,另一个方向发生截取,常用
- left,不缩放图片,只显示图片的左边区域
- center,只显示中间区域
- ...更多属性说明
lazy-load,图片懒加载,只针对page与scroll-view下的image有效,默认false
...更多属性说明
2.5.navigator与页面跳转
类似于<a>组件,但只能跳转本地也没,目标页面必须在pages.json中注册
除了 组件方式,API方式也可以实现页面跳转,详情见:https://uniapp.dcloud.io/api/router?id=navigateto
属性说明
url,跳转链接,值为相对路径或绝对路径,注意不能加
.vue
后缀open-type,跳转方式,默认navigate
- navigate,跳转后可返回上一页面
- redirect
- switchTab
- reLaunch,跳转后不可返回上一页面
- navigateBack
- exit
delta,当跳转方式为
navigateBack
时有效,表示回退层数animation-type,
navigate
时有效,窗口的显示/关闭是动画效果,默认效果:pop-in/outhover-class,指定点击时的样式效果
target,在哪个小程序目标上发生跳转(跳转到其他小程序),默认当前小程序,值域self/miniProgram
...更多属性说明
2.6.常用表单组件button和input
button
属性说明
size,按钮大小
type,按钮的样式类型
plain,按钮是否镂空,背景色透明
disabled,按钮是否禁用,可用于信息填写完成后解除禁用(属性绑定)
loading,名称前是否带loading图标,在提交等数据的时候会有一个小加载符号在名称前
input
手机可以通过与电脑连接同一网络后去访问启动时的HBuilder的network地址
15:55:10.311 - Local: http://localhost:5173/
15:55:10.311 * Network: http://192.168.10.35:5173/
15:55:10.311 * Network: http://169.254.105.78:5173/
15:55:10.311 - Network: http://169.254.233.253:5173/
属性说明
value,输入框的初始内容,要删
type,input的类型有效值,默认text,有idcard身份证类型,tel拨号类型,在小程序上点击框的时候弹出的键盘类型不一样
text-content-type,文本区域的语义,根据类型自动填充有效值
password,是否为密码类型
placeholder,输入框为空时的占位符,常用于提示,不用删
disabled,是否禁用
maxlength,最大长度,一般是要设置的,否则可能数据会爆
focus,获取焦点?
confirm-type,弹出软键盘后右下角按钮的文字
- send,右下角为发送
- search,右下角为搜索
- next,下一个
- go,前往
- done,完成
...更多属性说明
3.1.vue3的模板语法插值表达式用法
重点针对于script块,主要学习看vue官网
模板语法
插值表达式:{{}}
const是常量
let定义的变量
3.2.使用ref定义响应式数据变量
要先import {ref} from "vue"
()=>{}是什么?vue的特定语法?
3.3.v-bind指令配合图片轮播案例
双大括号不能再HTML的attributes中使用(<>里),想要响应式的绑定一个attribute,就要用
v-bind
,缩写是:v-bind
指令指示vue将元素id
attribute与组件的dynamicId属性保持一致。如果绑定的值是null
或者undefined
,那么该attribute将会从渲染的元素上移除。loading="false" 这个代码是添加加载图标的,但是这样子无法取消掉加载图标,因为这样相当于传的是一个字符串,而字符串默认是属于true的,因此需要在loading前面加上:,:loading = "false" 这样就可以关掉
3.4.class类和style内联样式的绑定
我们可以给
:class
传递一个对象来动态切换样式例子
isActive是在script里的可渲染值(用ref渲染, const isAction = ref(true) )
可以设定条件来更改isActive的值来使一个元素展示不同情况条件下的样式
- 注意,只要加了
:
,那么对应属性的值就是JS相关表达式了,有单位的话需要使用引号,双引号里面可以包裹单引号
<view class="box" :style="{width:'300px',height:high+'px',fontSize:fSize+'px'}" >内联样式</view>
- 在:style里面的传值要带上{},因为有样式对应值{样式名:属性名}
- 在其他情况例如:loading不需要带{},因为他是直接传真假值即可实现改变情况 :loading = "loadingChange",let loadingChange = ref(true)
权重等级?
- 级联样式 内联样式?
3.5.原生事件监听及组件内事件处理
监听事件
我们可以使用
v-on
指令(简写@
)来监听DOM事件,并在事件触发时执行对应的JavaScript。用法:v-on:click = "handler"
或 @click= "handler"
事件处理器(handler)的值可以是
- 内联事件处理器:事件被触发时执行的内联JacaScript语句(与
onclick
类似)
- 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。
事件处理
在对应@指令后指定函数名,去编写函数名的具体实现即可处理
3.6/7.v-if条件渲染与v-show
v-if(不能在if和else之间加任何元素)
用于条件性地渲染一块内容。这块内容只会在指令的表达式返回真值时才被渲染。
v-else
v-if的相反条件
组合式模板内容
scss
:CSS语言scoped
:CSS样式使用范围仅限当前vue文件,不会污染到其他组件也可以自定义模板,后续创建的话就都是模板的内容了
v-if 和 v-show 的区别
v-if
如果是 false
的话那么不会加载资源,直接在网页上显示一个v-if
(惰性渲染)v-show
是 false
也会加载资源,它相当于 style="display: none"
,对于图片类资源,不推荐使用 v-show
(始终渲染)view与template的区别
view
相当于div
,如果使用一次就会新建一个级别
template
适用于在同一级别下有多个元素的情况,使用 template
就会被打包在一个级别,与上一级同级别,且不显示 template
元素
template上的v-if
因为
v-if
是一个指令,他必须依附于某个元素,但如果我们想要切换不止一个元素呢?在这种情况下我们可以在一个 template
元素上使用 v-if
,这只是一个不可见的包装器元素,最后渲染的结果不会包含这个 template
元素,只展示其子元素3.8.v-for列表渲染
v-for
基于一个数组来渲染一个列表。需要使用 item in items
形式的特殊语法,其中 items
是源数据的数组,而 item
是迭代项的别名在
v-for
块中可以完整地访问父作用域内的属性和变量。v-for
也支持可选的第二个参数表示当前项的位置索引注意:小程序一般要求有一个key(唯一值),否则会有警告
template上的v-for
与模板上的
v-if
类似,我们也可以在 v-for
上渲染包含多个元素的块,同时不推荐 v-if
和 v-for
同时出现在一个元素里,可以在template先使用一种然后再使用另一种。(v-if的执行优先级高于v-for)【购物车案例】v-for为什么要用:key
代码
如果没有:key,那么你在删除值时对应操作不统一
goods.value.splice(e,1)
- goods.value是一个数组
- splice方法用于添加或删除数组中的元素
- e表示删除元素的索引
- 1表示删除一个元素
在 Vue.js 中,
v-for
指令用于渲染一个列表。为了确保列表在更新时能够高效地进行差异检测和重新渲染,Vue 要求在 v-for
中使用 :key
属性。key
的作用是为每个列表项提供一个唯一的标识符,这样 Vue 在更新列表时可以更准确地追踪每个列表项的变化。不使用 :key 的问题
如果不使用
:key
,Vue 在更新列表时会使用一种默认的算法来尝试追踪列表项的变化。这种算法可能会导致以下问题:- 列表项的更新不准确,可能会导致 DOM 元素的复用不当。
- 列表项的状态可能会混乱,导致操作不统一,例如删除、添加或更新列表项时出现意外行为。
【小鸡案例】表单focus和blur事件用法
表单输入绑定(v-model,:与@input组合实现的双向绑定)
在前端处理表单时,我们常常需要将表单输入框的内容同步给JavaScript中相应的变量。手动连接值绑定和更改事件监听器肯呢个会很麻烦;
v-model
指令帮我们简化了这一个步骤它支持各种不同类型的输入和根据所使用的元素自动使用对应的DOM属性和事件组合
- 文本类型的
<input>
和<textarea>
元素会绑定value
property并侦听input
事件;
<input type="checkbox">
和<input type="radio">
会绑定checked
property并侦听change
事件
<select>
会绑定value
property 并侦听change
事件
属性说明
@input,键盘输入时,触发input事件,event.detail = {value},在输入框输入的值会同时传给参数返回值
@focus,输入框聚焦时触发,点击百度一下网页进入后,默认就会focus聚焦在输入框
@blur,输入框失去焦点时触发,在京东注册时输入完整手机号后点击其他位置就会自动去校验手机号
代码
亮点:如果只有一行代码,不需要定义函数,直接写在元素的属性里,元素的属性不需要加value,直接属性名就可以改其对应值。在js里需要实现响应式就要加value
3.11.v-model双向绑定实现原理
基于响应式:和@input实现,在控制台打印@input对应的函数可以发现其detail会包含输入的内容,因此只需要在input的处理函数里增加赋值处理即可实现双向绑定
3.12.【热搜案例】知识点阶段性综合汇总
代码
涉及知识点
v-for ="(item,index) in lists" :key = item.id
v-for的使用,item是lists数组的元素,index下标从0开始 :key标识每一个元素,使操作统一
@click="removeC(index)"
点击事件的删除操作,由于点击后,点击事件的数据detail会包含对应元素的下表,因此可以通过
lists.value.splice(e,1)
来实现删除操作,e代表传入的参数(下标)(平时函数括号里的e可以代表传参也可以代表回调参数),1代表删除一个元素{{}}
插值表达式,对导入vue包后的
ref
变量进行响应传值:disabled="!iptValue.length
:响应数据,接收
ref
变量,元素的长度,0可以代表false,0以外的数字代表true,取反对应逻辑v-model="iptValue"
双向绑定,一般用于
<input>
元素,实现原理是基于响应式传值:和@input事件的detail.value,每次输入一个值,@input事件就会把它记录在detail里面3.13.computed计算属性
模板的表达式虽然方便,但也只能用来做简单的操作,如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。
模板层不加value,但是js层要加value
不使用computed
使用computed
()=> firstName.value + "-" + lastName.value
和 直接定义函数并设置返回值是一样的效果,只不过前者是单返回值,相当于一个属性和ref()
一样,调用的时候直接传属性名即可,而后者是一个方法(函数),调用的时候要使用括号()计算属性和方法的区别
计算属性会基于响应式依赖(等价于
ref()
变量)被缓存,在执行渲染一次后,只要数据不发生改变就不会再执行渲染,无论调用多少次方法是基于对象,只要调用一次就会执行渲染一遍逻辑,非常消耗性能
可写计算属性
计算属性默认是只读的,当尝试修改一个计算属性时,会受到一个运行时警告,只在某些特殊场景中你可能才需要用到"可写"的属性,可通过getter和setter来创建
最佳实践(最好把计算属性当成可读,不要去改动它)
计算属性的getter应该只做计算而没有其他任何的副作用,这一点非常重要,请务必牢记。举例来说,不要在getter中做异步请求或者更改DOM!一个计算属性的声明中描述的时如何根据其他值派生一个值。因此getter的职责应该仅为计算和返回该值。
3.14.【计价案例】计算属性配合循环遍历统计总价
代码
注意,checkbox的value值只能是字符串,拿到template里的值就要使用v-bind,绑定传参
涉及知识点
<checkbox-group name="" @change="itemChange">
只有用checkbox-group包裹checkbox并在checkbox添加value(并绑定字符串id)值才可以使用change事件(获取对应ref对象的选中情况true和false)
:checked="item.checked"
使用绑定传参来更改选中后的checkd值,后续再使用链式调用统计价格
v-for="(item,index) in goods" :key="item.id"
v-for的常用写法
@click="removeC(index)"
删除某个下标的元素声明
const totalNum = computed(() => selectGroup.value.length)
计算属性,等价于
const totalNum = ref("")
,也等价于const totalNum = computed(() => {
return selectGroup.value.length})
const totalPrice = computed(() =>
goods.value.filter(item => item.checked).reduce((prev, curr) => prev + curr.price, 0))
计算属性+链式调用(reduce((prev,curr)=> prev+curr.price,0))
- 使用
filter
方法遍历goods.value
数组,筛选出所有checked
属性为true
的商品。筛选出来的是一个数组
item => item.checked
是一个箭头函数,表示如果item.checked
为true
,则保留该item
。
- 对筛选后的数组使用
reduce
方法,计算这些商品的总价格。
prev
是累加器,curr
是当前遍历的商品。
prev + curr.price
表示将当前商品的价格加到累加器上。
0
是reduce
方法的初始值,表示累加器从 0 开始。
最终,这段代码会返回所有
checked
属性为 true
的商品的价格总和。3.15.watch和watchEffect监听的使用
vue3中computed计算属性和watch监听的异同点
computed和watch都是用于响应式处理数据变化的工具
异同点
计算属性(Computed),多对一,可以多个生成一个
- 计算属性是基于它们的依赖(ref())进行缓存的,只有在依赖发生变化时,计算属性才会重新计算,可以避免不必要的重复计算。
- 计算属性适用于派生出一些新的数据,比如对数据进行过滤、排序、格式化等操作。
- 计算属性可以像普通属性一样使用,而不需要在模板中调用方法
- 计算属性中的函数必须有return返回值
监听属性(Watch)一对多,可以由一个的改变去发散更多的东西
- 监听属性允许我们在数据变化时执行异步操作或复杂的逻辑
- 监听属性适用于对数据变化做出响应,比如在数据变化时发送数据,处理副作用等。
- 可监听一个或多个数据的变化,并在数据变化时执行相应的操作。
- 它的函数不是必须要用return返回值
相似之处
- 计算属性和监听属性都可以依赖于响应式数据
- 他们都可以用于监测数据的变化,并做出相应的处理
总的来说计算属性适用于派生出新的数据,而监听属性适用于在数据变化时执行一步操作或复杂逻辑。
监听器
watch
使用watch函数在每次响应式状态发生变化时触发回调函数
- watch的第一个参数可以是不同形式的数据源
- ref(包括计算属性)
import { ref, watch } from 'vue';const person = ref("")watch(person,(newValue,oldValue)=>{ console.log(newValue) console.log(oldValue)})
- person是一个计算属性,后面是一个回调函数,接收两个参数,一个是新值,另一个是老值
- 但这个监听只是一个浅层监听(字符串、数字直接使用属性名),无法监听响应式对象具体属性值的改变,
- const person = ref({ name:"张三", age:14 }) watch(()=>person.value.name,(newValue,oldValue)=>{ console.log(newValue) console.log(oldValue) })
- 可利用箭头函数去监听一个对象的具体内容改变,或开启深度监听,但深度监听会消耗性能,{deep:true}开启深度监听,immediate:true立即执行,启动后会在控制台打印出该对象的值
watch(person,(newValue)=>{ console.log(newValue) },{deep:true,immediate:true} )
- 适用于不知道这个对象的属性什么要发生改变时。
- 一个getter函数
- 多个来源组成的数组
- 一块监听
//多个数据,数组监听 watch([firstName,lastName],([nfirstName,nlastName],[ofirstName,olastName])=>{ console.log(nfirstName+'-'+nlastName) console.log(ofirstName+'-'+olastName) })
- watch([多个数据],([新数据组],[旧数据组])=>{逻辑处理})
- 分开监听,一样的效果,但是更易读
watch(firstName,(nf,of)=>{ console.log(nf)})watch(lastName,(nl,ol)=>{ console.log(nl)})
watchEffect()(与watch的区别主要是监听所有改变的数据,不用传源值)
监听器的毁掉使用与源完全相同的响应式状态是很常见的。例如下面的代码在每当
todoid
的引用发生变化时,使用监听器来加载一个远程资源;特别注意监听器是如何两次使用todoId的,一次是作为源,另一次是回调中。
我们可以用watchEffect函数来简化上面的代码。watchEffect()运行我们自动跟踪回调的响应式依赖,上面的监听器可以重写为:
这个例子中,回调会立即执行,不需要指定immediate:true。在执行期间,它会自动追踪todoId.value作为依赖(和计算属性类似)。每当todoId.value变化时,回调会再次执行。有了watchEffect(),我们不需要明确传递todoId作为源值
对于这种只有一个依赖项的例子,watchEffect() 的好处相对较小,但是对于有多个依赖项的例子就不一样了
4.1.uniapp创建组件和vue官网文档的差异对比
组件运行我们将UI划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。在实际应用中,组件常常被组织成层层嵌套的树状结构。(好处:改变一个组件,调用这个组件的显示区域也可以改动。)

概念
- 组件是视图层的基本组成单元
- 组件是一个单独且可复用的功能模块封装
- 一个组件包括开始标签和结束标签。标签上可以鞋属性,并对属性赋值。内容则写在两个标签之内
- 根节点为<template>,这个<template>下在App、H5可以有多个根<view>组件,在小程序只能有一个根<view>组件
- 一个组件的data选项必须是一个函数
局部组件
局部注册之前,在需要引用该组件单页面,导入你想使用的组件。
页面引入组件方式
如下通过两种方式导入一个角坐标的组件库,推荐使用 easycom方式引入
即直接在项目目录下创建
components
,然后新建组件名,在需要使用这个组件时,直接在页面需要的位置输入<组件名> </组件名>一般组件名的命名方式:前缀-业务逻辑
4.2.在组件中通过Props进行数据传递
传递props(父向子分配,像家产一样,defineProps在子组件声明)
子组件(渲染层,接数据,不能直接修改接收的数据,可以利用计算属性来创造一个新数据):
父页面(数据层,传数据):
效果:

如果我们正在构建一篇博客,我们可能需要一个表示博客文章的组件。我们希望所有的博客文章分享相同的视觉布局,但有不同的内容。要实现这样的效果自然必须向组件中传递数据,例如每篇文章标题和内容,这就会使用到props。
Props是一种特别的attributes,你可以在组件上声明注册。要传递给博客文章组件一个标题,我们必须在组件的props列表上声明他,这里要用到defineProps宏:
defineProps是一个仅<script setup>中可用的编译宏命令,并不需要显式得导入。声明的props会自动暴露给模板。defineProps会返回一个对象,其中包含了可以传递给组件的所有props;
4.3.Prop校验和prop默认值用法及循环遍历数组对象
props定义格式
简洁定义,不用加花括号
defineProps(['username','avatar'])
把props传给一个变量,要定义多个校验就要加花括号
const props = defineProps({
username:{
type:String,
default:"匿名用户"
},
avatar:String
})
- 这样限制了username和avatar是字符串类型和默认值
其他props加校验的格式

props传值格式
在元素里直接借助响应式绑定:传
<UserInfo :username="username" avatar=""></UserInfo>
传递一个数组对象
先定义一个对象,对象可以是数组,然后利用v-for循环遍历数组,item就是要传的一个对象,
接收方UserInfo,首先使用defineProps(),对象就要使用{},类型是对象类型,由于对象有多个属性,所以需要使用函数来设定默认值,直接return {对象属性1,对象属性2}
4.4.插槽Slots及具名插槽实现组件高度定制化
插槽Slots
在某些场景中,我们可能需要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段
在设置了slot标签的区域,父页面可自定义内容
具名插槽
如果slot元素上又name属性,那么就要使用template标签的v-slot(缩写
#
)属性,比如:<template v-slot:header>首页头部</template>
<template v-slot:header>功能页头部</template>
或
<template #header>首页头部</template>
<template #header>功能页头部</template>
注意要被组件包裹
4.5.组件中emit的声明触发事件
以往都是父传数据,子接收,像继承家产一样,那么子组件能否向父页面发送数据呢?答案是可以的,就是利用
$emit
利用emit从子组件往父页面传数据(直接在属性的元素里传,比较少用)
首先在子组件对相应监听的事件定义emit,如@click事件中传值:
@click = "$emit('randomC',Math.random())"
- 其中,$emit()是固定表达,'randomC'是后续在父页面引用子组件时,@的元素名,如@randomC,这样就可以拿到逗号后面的random值
- 也就是$emit('元素名',回调值)
在父页面中要接收子组件的值,就需要在引用子组件时@元素名,并定义相关函数来处理,如
利用emit从子组件往父页面传数据(在script里定义,常用)
父页面
子组件
对比可以看出,
emit
写在script
后不需要加$
符号,并且可以在使用多个emit监听多个点击事件- 主要在于利用defineEmits(["元素名1","元素名2"])
4.6.vue3组合式API中的组件的生命周期
生命周期函数(钩子函数)
代表在Vue实例创建、更新和销毁的不同阶段触发的一段钩子函数,这些生命周期函数允许开发者在不同阶段对Vue实例进行操作,以便执行特定的逻辑或清理工作
生命周期主要包含四个阶段:创建、挂载、更新、销毁
好比一款手机、创建(拿到全新一款手机)、挂载(安装各种软件)、更新(系统或软件升级)、销毁(丢弃手机)
Vue3中的生命周期函数
- setup() 是在beforeCreate和Created之前运行的,所以可以用setup代替这两个钩子函数。
- onBeforeMount():已经完成了模板的编译,但是组件还未挂载到DOM上的函数
- onMounted():组件挂载到DOM完成后执行的函数。
- onBeforeUpdate():组件更新之前执行的函数。
- onUpdated():由于数据更改导致的虚拟DOM重新渲染和打补丁
- onActivated():若组件实例是缓存树的一部分,当组件被插入到DOM中时调用
- onDeactivated():若组件实例是缓存树的一部分,当组件从DOM中被移除时调用
- 注意:在uniapp组件中 onBeforeUpdate、onUpdated、onActivated、onDeactivated,H5支持,小程序无法使用

Vue2.x的生命周期
new Vue(),创建一个Vue实例
Init Events & Lifecycle、beforeCreare,创建前
- DOM对象:el:undefined
- data对象:data:undefined
- 声明的变量:message:undefined
Init injections & reactivity、created,创建后
- DOM对象:el:undefined
- data对象:data:[object Object]
- 声明的变量:message:“Vue的生命周期”

整体阶段
- 开始编译模板,根据data中的数据和指令生成HTML,此时还未渲染,仅存在于内存中
beforeMount,挂载前,完成模板编译,还未挂载到页面
- DOM对象:el:undefined
- data对象:data:[object Object]
- 声明的变量:message:“Vue的生命周期”
Create vm.$el and replace "el" with it、mounted,挂载结束,已渲染到页面
- DOM对象:el:[object HTMLDiveElement]
- data对象:data:[object Object]
- 声明的变量:message:“Vue的生命周期”
Mounted、beforeUpdate,更新前状态,状态更新前执行,此时data的状态值是最新的,但界面还没有开始渲染,数据是旧的
- DOM对象:el:[object HTMLDiveElement]
- data对象:data:[object Object]
- 声明的变量:message:“被修改了”
Virtual DOM re-render and patch、updated,状态更新完成后执行,此时的数据是最新的,即界面一杯渲染
when vm.$destroy() is called、beforeDestroy,销毁前,实例准备销毁,但还没被销毁,实例属性方法还可以使用
- DOM对象:el:[object HTMLDiveElement]
- data对象:data:[object Object]
- 声明的变量:message:“Vue的生命周期”
Teardown watchers,child components and event listeners、destroyed,销毁完成,所有内容均不可使用
- DOM对象:el:[object HTMLDiveElement]
- data对象:data:[object Object]
- 声明的变量:message:“Vue的生命周期”
Vue3.x的生命周期

setup创建时无法获取模板层的组件,因为还未挂载渲染到DOM
一般onMounted、onUnMounted这个函数用到比较多,因为此时模板层的组件渲染到页面了
uniapp不支持响应数据修改时运行的函数
uniapp页面生命周期函数与 Vue.js 的生命周期函数有所不同,因为 uni-app 是基于 Vue.js 的跨平台应用框架,因此它具有自己特定的生命周期函数。
可以在这些生命周期函数中编写相应的逻辑代码,以便在不同阶段对页面进行初始化、展示、隐藏和卸载时执行特定的操作。
在开发uniapp Vue3版本的时候,不能像vue2的选项式API一样,可以直接使用onLoad、onShow等,在组合式API中需要先从“@dcloudio/uni-app”模块中导入才可以。
<script setup>
import {onLoad,onReady} from "@dcloudio/uni-app"
</script>
onLoad:页面加载时触发,可以在此生命周期函数中进行页面初始化操作。
onShow:页面显示时触发,可以在此生命周期函数中进行页面展示相关的操作。
onReady:页面初次渲染完成时触发,可以在此生命周期函数中进行页面渲染完成后的操作。
onHide:页面隐藏时触发,可以在此生命周期函数中进行页面隐藏相关的操作。
onUnload:页面卸载时触发,可以在此生命周期函数中进行页面卸载相关的操作。
其他常用的生命周期,可以看官方发文档,页面生命周期函数
uniapp中组件生命周期函数和页面生命周期函数的执行顺序
不包含组件的页面
onLoad > onShow > onReady
包含组件的页面
onLoad > onShow > onBeforeMount > onReady > onMounted
4.7.使用defineExpose暴露子组件的属性及方法
defineExpose的作用是把子组件的属性和方法暴露给父页面,和props很像?
使用步骤
现在子组件定义需要暴露的属性或方法
<template> <view class="out"> count:{{count}} </view></template><script setup> import {ref} from "vue" const count = ref(100) const updateCount = function(){ count.value++ } defineExpose({ count, str:"213", updateCount })</script>
- 其中,暴露的属性和方法有count,str,updateCount
在父页面引用
引用的话直接从value拿即可,很像java的继承,但这里有点相反,Java的继承是子类可以使用父类的所有属性和方法,defineExpose只能使用暴露给父类的属性和方法
4.8.页面生命周期onLoad和onReady在vue3组合式api中的使用
uniapp页面除支持Vue组件生命周期外还支持页面生命周期,且页面生命周期 用的更多
属性说明
onLoad,监听页面加载,该钩子被调用时,响应式数据、计算属性、方法、侦听器、props、slots已设置完成,其参数为上个页面传递的数据,参数类型为Object(用于页面传参),有回调函数e
onShow,监听页面显示,页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面
onReady,监听页面初次渲染完成,此时组件已挂载完成,DOM树($el)已可用,注意如果渲染速度快,会在页面进入动画完成前触发,无回调函数
执行顺序
onLoad -》 onShow -》 onReady
另外,应用App.vue的生命周期执行优先级高于页面.vue的生命周期
uniapp与Vue组件混合的页面
- onLoad -》 onShow - 》 onBeforeMount -》 onReady - 》 onMounted
区别
onLoad只在页面加载时渲染,(包括点击、跳转)
onReady监听页面初次渲染完成,(包括点击、跳转)
onShow会在页面每次显示时渲染,(包括点击、跳转、返回、切屏)
onHide会在页面隐藏时触发,(包括切屏)
4.9/10.onUnload页面卸载和onPageScroll监听页面滚动
onUnload页面卸载
onUnload搭配open-type="reLaunch"(跳转方式)使用,可以清除缓存了的页面,但无法返回了
onPageScroll监听页面滚动,参数为Object,有回调值
常用于导航栏(回到首页),当滚动往下到一定位置就出现
例子
5.1.响应式单位rpx及搭配使用UI产品工具
10px 像素单位,非响应
10% 百分比,响应
10vw 屏幕10%的水平占比,响应
10vh 屏幕10%的垂直占比,响应
10rpx 响应式像素单位,响应
UI工具:MasterGo、即时设计
一定要注意针对某款手机的屏幕比例,常见的就是750px(水平)
5.2.@import导入css样式及scss变量用法与static目录
lang
预编译器样式 如 scss
,scoped
样式仅在当前对象使用页面的样式权重大于App.vue的样式权重,也就是说页面.vue的style样式会覆盖App同名的样式
box-sizing: border-box
公共样式之一,防止像素外扩- 如果在公共样式设定了这个,那么对于内边距 padding,不会在外扩,而是固定宽度
非
static
目录下的文件(vue组件、js、css等)只有被引用时才会打包编译css
、less/scss
等资源不要放在 static
目录下,建议这些公用的资源放在自建的 common
目录下。5.3.pages.json页面路由globalStyle的属性
超多属性,如导航栏背景颜色、文字标题、样式、下拉显示出来的样式、是否开启下拉刷新等等,pages.json页面路由网页
pages设置页面路径及窗口表现
可设置首页全屏,其他页面带导航栏和下拉刷新等等
tapBar设置底部菜单及iconfont图标
同样在page.json里配置,list属性必不可缺,且元素至少2个
uniapp/vue如何解决跨域问题?
uniapp项目在浏览器运行,有可能调用某些接口会出现跨域问题,报错:
Access to XMLHttpRequest at 'xxxxxxxxxxxxxxx' from xxxxxxxx origin 'xxxxxxxxxxxx' has been blocked by CORS policy:No 'Access-Control-Allow-Origin' header is present on the requested resource
什么是跨域
在uniapp中出现跨域问题如何解决?
1.服务设置CORS
在后端的响应头设置Access-Control-Allow-Origin属性,允许前端访问:
如果条件允许,能给找到接口后端开发者,只要响应头添加如此设置,前端即可正常访问;
但是后端往往考虑安全问题,API接口只允许自己公司项目使用,如果开启了运行跨域那么所有人都可以来蹭你的接口,导致没必要的消耗或暴露存在的安全漏洞。
或者用了别人的开源接口根本找不到开发者,所以这个方案依赖于别人, 能不能解决跨域,就只能随缘了
2.在HBuilder编辑器中使用内置浏览器运行
如上图所示,uniapp项目使用内置浏览器预览调试,可以轻松解决接口在外部浏览器出现的跨域问题。
这种方案也是最简单方便的解决办法。
3.在vite.config.js中配置代理(vue3版本)
这种方案是开发Vue项目最普遍的用法,在uniapp项目中依然适用,也是重点给推荐的方式,
vue3是使用vite构建及打包的,所以在uniapp项目根目录下创建vite.config.js,拷贝下面的代码:
假设接口为http://jsonplaceholder.typicode.com/posts ,那么发送网络请求的时候就可以使用如下方式了:
5.8.uni-api交互反馈showToast的用法
通常使用的是error,显示错误图标和最多7个字,success一般不设置成功弹窗,成功就显示数据
通过调用uni.showToast(OBJECT)方法使用该弹窗,注意其属性mask的值最好设置false,因为如果卡死了的话哪里都点不了只能关闭程序了,或者
- 发生错误时隐藏加载框
uni.showLoading({ title:"加载中..." mask:true, fail:err=>{ uni.hideLoading() }}})
基本上很多方法的样式,字体,颜色都可以设置,记住核心功能和方法名,剩余根据英文名扩展,一般回调函数都是success,然后校验就可以通过success返回的结果来进行处理
例:
function remove(){ uni.showModal({ title:"是否删除", cancelText:"No", confirmText:"Yes", cancelColor:"#999", confirmColor:"#f00", success:res=>{ if(res.confirm) uni.showToast({title:"删除成功"}) } })}
6.1.【萌宠案例】
uniapp组件图片库
7-10.个人壁纸项目
常见问题
TypeError: Cannot read property 'score/_id' of null
- 加载顺序的问题,因为先执行的是setup语法糖里的语句(赋初试值是null),导致score或者_id的值可能是空的,对null值操作会出现问题,而到了下一个生命周期onLoad后dom体就挂载完毕,数据发生改变,模板层就发生改变,进行信的赋值,就可以渲染了,因此只需要在依赖或者操作这些个数据的语句总体元素处增加一个判断,只有currentInfo这个值有数据时才展示该元素(渲染),
- 例
<view class="content" v-if="currentInfo"> <view class="row"> <view class="label">壁纸id:</view> <text selectable class="value">{{currentInfo._id}}</text> </view></view>
- 生命周期
- 总结
- 原因:要么没赋初始值,要么是有代码在空值的时候进行渲染,要么一开始给了初始值是空,然后在另一个生命周期(onLoad挂载)后又重新给值
- 方法:给初始值,并在数据渲染完毕(涉及生命周期/执行顺序)后再进行展示,在模板层展示时在大元素里加一个v-if 等到目标渲染完毕有值后进行展示,也就是加一个
v-if="currentInfo"
即可
Now you can provide attr
wx:key
for a wx:for
to improve performance.- v-for处没给key赋值
- 直接加上:key="xxx"

- 作者:poze624
- 链接:https://poze624.top/notes/20241206155147
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。