生命周期函数执行顺序
进入某一个页面
- 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属性:这个value是动态绑定,value值相当于一个变量,可以去data中取数据,如果data中没有则不显示
这个没有绑定,页面中默认就是显示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,
,使用&符号
云数据库的添加与删除
添加
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').removeconsole.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,这样就可以直接引用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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-ALIPAYconst 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} = resthis.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中引入路径 添加标签
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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.detailthis.$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()
-