生命周期函数执行顺序
进入某一个页面
- onLoad:页面加载
- onShow:页面显示
- onReady:页面渲染
由该页面跳转进入下一页面
- onHide:隐藏页面
- onLoad:加载页面
- onShow:显示页面
- onReady:渲染页面
下一页面返回该页面
- onUnload:卸载页面
- onShow:显示页面
知识点
- 模板语法:v-bind–: v-on–@
- 数据绑定
- 条件判断:v-if v-if-else v-else
- 列表渲染
- 基础组件的使用
- 自定义组件的使用
- 基础api的用法
- 条件编译
- 页面布局
- 跳转详情页面: uni.navigateTo({
url:’/pages/home-detail/home-detail’
})
uniapp中不建议用data:{},因为这样关闭再打开会保留上次的变量值,不会初始化,需要用data(){return{}}
input中的value属性:<input type="text" :value="value" />
这个value是动态绑定,value值相当于一个变量,可以去data中取数据,如果data中没有则不显示
<input type="text" value="value" />
这个没有绑定,页面中默认就是显示value,data中绑定了数据也不会显示
父->子传递参数
// 父组件
<template>
<btn color="pink" @change="btn"></btn>
</template>
methods:{
btn(){
console.log('我是父组件点击')
}
}
// 子组件
<template>
<view class="btn-box" :style="{color:color}" @click="onClick">
点击
</view>
</template>
props: {
color:{
type: String,
default: '#000'
}
}
methods:{
onClick() {
console.log('我是子组件点击')
this.$emit("change",color)
}
}
子->父传递数据,通过方法
//tab.vue子组件
methods: {//参数一:自定义事件,父组件接收的 参数二:需要传递的数据
this.$emit('tab',{
data:item,
index:index
})
}
//index.vue父组件 @子组件自定义="父组件点击事件"
<tab @tab="tab"></tab>
methods:{
tab(item,index){//这里的tab,父组件点击事件
console.log(tab)
}
}
生命周期uin-app
应用生命周期:只在app.vue中
app常见的三种生命周期:
- onLaunch:初始化完成触发一次,全局只触发一次–>登录、全局变量
- onShow:应用启动的时候,或者从后台进入前台会触发
- onHide:应用从前台进入后台会触发
页面生命周期:只在index.vue中
page常见的几种生命周期:
- onLoad:监听页面加载
- onReady:监听页面的初次渲染完成
- onShow:监听页面显示
- onHide:监听页面隐藏
- onUnload:监听页面卸载
组件生命周期:在子组件中使用,跟vue 的生命周期一样
components常用的4种:
- beforeCreate:在实例初始化之后,数据观测和事件配置之前调用
- Created:实例创建完成之后立即调用,挂载阶段还没开始
- mounted:挂载到实例上之后调用
- destroyed:实例销毁后调用
生命周期执行顺序:App Launch --> App Show --component beforeCreate->component Created -->page onload -->page onshow --> component mounted–>page onready
目录结构
- components:自定义组件的目录
- pages:页面存放目录
- static:静态文件资源目录
- unpackage:编译后的文件存放目录
- utils:公用的工具类
- common:公用的文件
- app.vue:app.js
- main.js:应用入口
- manifest.json:项目配置
- pages.json:页面配置
在pages.json中设置tabbar,会导致页只加载一次
页面生命周期只会onLoad一次,下一次就不会渲染数据,因此需要在其他的生命周期中调用,onTabItemTap(e){console.log('继续出现')}
+onShow(){console.log('继续出现')}
在page中添加了页面组件,需要在pages.json中添加tabbar,
scss基本使用
-
$width : 200rpx; 替换200rpx
-
一个标签有2个class,
<view class="btn1 btn2"></view>
,使用&符号<style lang='scss'> $width:200rpx; .btn1{ diaplay: flex; flex-direction:column; width: $width; &.btn2{ color: pink } } </style>
云数据库的添加与删除
添加
exports.main = async (event,context) =>{
const collection = db.collection('user')
let res = await collection.add([
{name:'vue'},
{name:'html',type:'前端'}
])
console.log(JSON.stringify(res))
return{}
}
删除
exports.main = async (event,context) =>{
const collection = db.collection('user')
const res = await collection.doc('id').remove
console.log(JSON.stringify(res))
return{}
}
更新
// set如果记录存在就更新,不存在就添加
// update如果记录存在就更新,不存在就不更新
exports.main = async (event,context) =>{
const collection = db.collection('user')
//const res = await collection.doc('id').set({}) 2个都可以
const res = await collection.doc('id').update({
naem:'vue'
})
console.log(JSON.stringify(res))
return{}
}
查询
// 1. 这样只能根据id进行查找
exports.main = async (event, context) => {
const collection = db.collection('user')
const res = await collection.doc('id').get()
console.log(JSON.stringify(res))
}
// 2. 这样可以根据name进行查找
const res = await collection.where({
name: 'vue'
}).get()
项目过程
-
配置tabbar
在pages.json中,配置tabbar
-
"tabbar":{ "color":"#666", "selectedColor":"#f07373", "backgroundColor":"#fff", "list":[{ "pagePath":"pages/tabbar/index/index", "iconPath":"static/home.png", "selectedIconPath":"static/home-active.png", "text":"首页" },{ "pagePath":"pages/tabbar/follow/follow", "iconPath":"static/follow.png", "selectedIconPath":"static/follow-active.png" },{ "pagePath":"pages/tabbar/my/my", "iconPath":"static/my.png", "selectedIconPath":"static/my-active.png" }] }
-
-
实现自定义组件搜索栏
-
先创建组件,然后在首页组件中,引用、注册、使用
-
在搜索栏中注意点:需要添加一个高度为45px的view,这样就不会搜索条挡住内容
<template> <view class="navbar"> <view class="navbar-flxed"> <view class="navbar-search"> <view class="navbar-search-icon"> </view> <view class="navbar-search-text"> hello uniapp </view> </view> </view> <view style="height: 45px;"> </view> </view> </template>
-
-
配置字体图标库:https://www.cnblogs.com/qiu-Ann/p/11354095.html
配置字体图标简易方法:在components目录下放uni-icons,这样就可以直接引用
<uni-icons type="contact" size="18"></uni-icons>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MxPYPX90-1616508387083)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210220235505300.png)]
-
给导航栏头部设置:导航栏上面设置一个状态栏
<!-- 状态栏 动态设置状态栏高度 --> <view :style="{height: statusBarHeight+'px'}"> </view> data(){ return{statusBarHeight:20,navBarHeight: 45,windowWidth:375,} } created() { //获取手机的系统信息-得到状态栏的高度 const info = uni.getSystemInfoSync() this.statusBarHeight = info.statusBarHeight }
-
给导航栏中的胶囊设置位置
<!-- 导航栏内容 --> <view class="navbar-content" :style="{height:navBarHeight+'px',width:windowWidth+'px'}"> <view class="navbar-search"> <view class="navbar-search-icon"> <!-- <text class="iconfont icon-search"></text> --> <!-- <uni-icons type="search"></uni-icons> --> <!-- <text class="iconfont icon-search" color="#00ffff"></text> --> <uni-icons type="search" size="18"></uni-icons> </view> <view class="navbar-search-text"> hello uniapp </view> </view> </view> created(){ this.windowWidth = info.windowWidth //获取胶囊的位置,h5不支持 //#ifndef H5 || APP-PLUS ||MP-ALIPAY const menuButtonInfo = uni.getMenuButtonBoundingClientRect() //导航栏高度 = (胶囊底部-状态栏高度)+(胶囊顶部-状态栏高度) this.navBarHeight = (menuButtonInfo.bottom-info.statusBarHeight)+(menuButtonInfo.top-info.statusBarHeight) this.windowWidth = menuButtonInfo.left //#endif }
-
给某个元素前面添加一个竖线,给该元素添加相对定位,再给其对应的伪元素添加对应的属性
<view class="tab"> </view> .tab{ position: relative &::after{ //下面的都是必要属性 content: ''; position:absolute; top:12px; bottom:12px; left:0; width:2px; background-color: pink } }
uniapp获取数据
-
建立云数据库,cloudfunction、新建云函数
-
在uniCloud–>cloudfunctions–>get_label–>index.js中获取label数据
//get_label-index.js 'use strict'; //获取label数据 const db = uniCloud.database() exports.main = async (event, comtext) => { let label = await db.collection('label').get() // 返回客户端 return { code:200, msg:'数据请求', data:label.data } }
-
首页通过unicloud.callFunction方式调取云函数,找到cloudFunction(云函数)中的get_label下的index.js,然后查找云函数中的 db.collection(‘label’)中的label,读取到数据后通过return返回给客户端,客户端通过promise的回调方式(.then方法)接收,在data中定义数组,用来接收获取的label数组,传递给子组件,最后通过props方法将值传给子组件中,在子组件中完成渲染
// index.vue
// 传递给子组件 子组件通过list接收,父组件通过tabList传递
<tab :list="tabList"></tab>
data(){
return{tabList:[]}
}
//在onLoad()中自动调用,在页面渲染之前
onLoad(){
this.getLabel()
}
methods: {
getLabel() {
uniCloud.callFunction({
name:'get_label'
}).then(res=>{
const {result} = res
this.tabList = result.data
})
}
}
// tab.vue props绑定、v-for渲染
<view v-for="(item,index) in list" :key="index">{{item.name}}</view>
props: {
list:{
type:Array,
default() {
return []
}
}
}
iconfont的使用
方法一:在线使用
- 在static文件下创建==>fonts==>icons.css[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpClIgKw-1616508435718)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307163750447.png)]
- 在阿里巴巴图标库找到 font class,复制css代码到浏览器,打开[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CP1JnXTY-1616508435729)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307163724874.png)]
- 将浏览器得到的代码保存到 icons.css文件中,src中只需要woff2的url,注意不要逗号[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S5FAmuFl-1616508435732)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307164140633.png)]
- 在需要使用的组件中引用,使用@import url(“相对路径”)[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZmuj1yV-1616508435734)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307164235022.png)]
- 在组件中引入 iconfont icon-tupian[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SBgzC64G-1616508435736)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307164316064.png)]
方法二:离线使用
- 下载 iconfont的离线包,解压放置在static文件下[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SANICkyY-1616508435738)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307165932451.png)]
- 打开iconfont.css文件,修改里面的配置,除了woff2url之外,其他的都要添加
~@/static/fonts/
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nI3vqAhw-1616508435739)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307170147426.png)] - 在需要使用的组件中引用 在style中引入路径 添加标签
<text class="iconfont icon-jigou"></text>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D92vZlVB-1616508435742)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210307170232871.png)]
请求的封装
//util.js
const baseUrl = 'http://localhost:8002'
export const myRequest = (options)=>{
return new Promise((resolve,reject)=>{
uni.request({
url:baseUrl+options.url,
method:options.method,
data:options.data || {},
success:(res)=>{
if(res.data.status !== 200){
uni.showToast({
title:'获取数据失败'
})
}
resolve(res)
},
fail:(err)=>{
uni.showToast({
title:'获取数据失败'
})
reject(err)
}
})
})
}
//main.js
import {myRequest} from './util.js'
Vue.prototype.$myRequest = myRequest
//页面.vue
async getSwiper(){
const res = await this.$myRequest({
url:'/api/detail'
})
this.swiper = res.data.message
}
点击高亮
-
通过v-for遍历获取的item,点击其中的某个item让它选中并且颜色变化,先绑定点击事件,需要传入参数item与index,通过点击就能获取
activeIndex===index:让点击元素的下标=index methods中动态获取了点击某个的元素的下标,点击之后让它选中,并且active变颜色
<view v-for="(item,index) in list" :key="index" @click="clickTab(item,index)" :class="{active:activeIndex===index}" >{{item.name}}</view>
-
通过点击方法,将获取到点击的下标进行传值
//获取点击方法 export default { methods: { clickTab(item,index){ this.activeIndex = index } }, data() { return {avtiveIndex:0, title: 'Hello', tabList:[], tabIndex:0, } } } //点击之后进行颜色的传递 &.active{ color:pink }
点击tab主体内容list跟随跳转
-
因为list的滑动数量是跟tab选项卡的个数一致,所以在index.js中传递tablist到子组件list.vue中,写一个props接收数据,接收到后,直接v-for循环遍历接收的list
//index.vue 父组件传入数据到子组件通过props <tab :list="tabList" :tabindex="tabIndex" @tab="tab"></tab> <view class="home-list"> <list :tab="tabList" :activeIndex="activeIndex" @change="change"></list> </view> data() { return { tabList:[], tabIndex:0, activeIndex:0 } } //list.vue <template> <!-- 左右滚动 current表示当前要跳转到第几项--> <swiper class="home" :current="activeIndex" @change="change"> <swiper-item v-for="(item,index) in tab" :key="index" class="swiper-item"> <list-item></list-item> </swiper-item> </swiper> </template> props:{ tab:{//数组类型 type:Array, default(){return []} } }
-
在list.vue中有一个事件能够监听事件的滚动,@change=“change”,对滑动的监听,获取监听的current第几个索引,将current传给tab这样联动就完成了
//list.vue 子组件传入父组件通过方法 methods:{ change(e){ const {current} = e.detail this.$emit('change',current) } } //index.vue <tab :list="tabList" :tabindex="tabIndex" @tab="tab"></tab> <view class="home-list"> <list :tab="tabList" :activeIndex="activeIndex" @change="change"></list> </view> data(){ return{tabIndex:0} } methods:{ change(current) { //current就是当前翻转页面的索引 this.tabIndex = current } }
vuex的使用
-
先在store中的index.js中引用
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex({ }) export default store
-
然后在main.js中声明定义
import store from './store'
,...store,
import Vue from 'vue' import App from './App' import api from './common/api' import store from './store' Vue.config.productionTip = false Vue.prototype.$api = api App.mpType = 'app' const app = new Vue({ store, ...App }) app.$mount()
-