1 条件编译
条件编译写法 | 说明 |
---|---|
#ifdef APP-PLUS 需条件编译的代码 #endif |
仅出现在 App 平台下的代码 |
#ifndef H5 需条件编译的代码 #endif |
除了 H5 平台,其他平台均存在的代码 |
ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif |
在 H5 平台或微信小程序平台存在的代码(这里只有|| , 不可能出现&& , 因为没有交集) |
2 App 端的 Nvue 开发
3 HTML5+
1 安装并运行HbuiderX
2 使用 vue-cli 的方式运行项目
node -v
# v14.15.4
npm install -g cnpm --registry=https://registry.npm.taobao.org
设置镜像然后再 npm install -g @vue/cli
装到全局的环境中sudo chown -R $USER /usr/local
之后再安装就好了.vue-cli
是否安装 vue --version
# 2.9.6
vue create -p dcloudio/uni-preset-vue test-uniapp
{ {title}}
绑定变量
v-bind:class="className"
绑定class,可以简写为:class="className"
v-on:click="open"
绑定事件,可以简写为@click="open"
动态数据绑定
this.title = "hello"
这个和小程序中不同. 小程序中是this.setData({xx: 'XX'})
①
v-if
条件判断, 为真的时候,才渲染. 为false
则不渲染.
<view v-if="true">hello uni-appview>
②
v-if
绑定变量, 为false
和0
的时候,不渲染
<view v-if="show">hello uni-appview>
...
data() {
return {
show: false
}
},
③
v-if
中可以接表达式例如v-if="show === 'hello'"
④
三元表达式
{ {show ? 'hello' : 'world'}}
⑤
v-if
v-else-if
v-else
, 根据参数来识别,这2个view要紧挨着.v-else-if
可以省略.
<view v-if="show === 1">uni-appview>
<view v-else-if="show === 2">vueview>
<view v-else>view>
①
v-for
通过一个数组来渲染我们的列表
<view v-for="(item,index) in arr" >{
{item}}view>
...
<script>
return {
arr : ['uni-app', 'vue', 'html']
}
script>
②
v-for
加上索引项index
写法如下
<view v-for="(item,index) in arr" >{
{(index+1) + ' ' +item}}view>
...
<script>
return {
arr : ['uni-app', 'vue', 'html']
}
script>
③
v-for
循环打印对象
<view v-for="(key,value) in arr" >{
{key + ' ' +value}}view>
...
<script>
return {
arr: {
name: 'LiMing',
age: 18,
type: 'eat'
}
}
script>
view
text
image
…
双向绑定
< input v-model="vlue" />
① 在根目录中建立
components
文件夹, 再建立一个/btn/btn.vue
btn.vue
源码如下,可以自己定义样式,行为.
<template>
<view class="btn-box" @click="clickBox">
点击
view>
template>
<script>
export default {
methods: {
clickBox() {
console.log('click');
}
}
}
script>
<style>
.btn-box {
width: 200px;
height: 100px;
text-align: center;
line-height: 100px;
}
style>
在需要的地方,进入,然后注册.
components
注册组件,然后就可以直接使用了.
<template>
<view class="content">
<btn>btn>
view>
template>
<script>
import btn from '@/components/btn/btn.vue'
export default {
components: {
btn
},
}
script>
② 给组件传值 关键词
props
, 然后标注参数类型.
- index.vue 中
<btn color="red">btn>
- 组件中,用
<template>
<view class="btn-box" :style="{
color: color}">
点击
view>
template>
<script>
export default {
props: {
color: {
type: String,
default: '#000'
}
}
}
script>
③ 页面上拿到组件中的返回值
index.vue
中注册监听事件<btn color="red" @change="change">btn>
...
methods: {
change(e) {
console.log("我是页面的事件,我返回了" + e);
}
}
$emit()
来返回. 接受2个参数, 第一个是 index.vue
的监听函数,第二个是参数methods: {
clickBox() {
console.log('click');
this.$emit('change', this.color)
}
}
$emit
把 this.color
传给 index.vue
的change
事件. 而 change
中的 e
就是组件中返回来的 this.color
④ 组件插槽
index.vue
中,使用 主页中的内容
这样的写法, 希望把文字也插入到组件中.
的方式来获取内容.文档:
https://uniapp.dcloud.io/api/README
① api的一个演示
<script>
export default {
onLoad() {
console.log(11);
uni.getSystemInfo({
success(res) {
console.log("success", res);
},
fail(err) {
console.log("error", err);
},
complete(res) {
console.log("不管成功失败都会返回: ", res);
}
})
},
}
script>
② 条件编译 用
#ifdef 平台标识符
来让代码在规定的平台里面编译.可以加上||
(或者).
<template>
<view class="content">
<button>我是一个按钮button>
view>
template>
#ifndef
加了一个n
表示在后面的平台上面,不显示.
条件编译写法 | 说明 |
---|---|
#ifdef APP-PLUS 需条件编译的代码 #endif |
仅出现在 App 平台下的代码 |
#ifndef H5 需条件编译的代码 #endif |
除了 H5 平台,其他平台均存在的代码 |
ifdef H5 || MP-WEIXIN 需条件编译的代码 #endif |
在 H5 平台或微信小程序平台存在的代码(这里只有|| , 不可能出现&& , 因为没有交集) |
文档
https://uniapp.dcloud.io/platform?id=%e8%b7%a8%e7%ab%af%e5%85%bc%e5%ae%b9
③ 在
style
中使用 条件编译
<style>
/* #ifdef H5 */
...
/* #endif */
style>
④ 在
style
中,page
表示这个页面
⑤ 尺寸单位
px
%
rpx
rem
vh
vw
⑥ 引入外部 css 文件
@import '@/static/index.css'
文档:
https://uniapp.dcloud.io/collocation/frame/lifecycle
① 生命周期的分类
应用生命周期, 在 App.vue
文件中
onLaunch
应用初始化完成触发一次, 全局只触发一次
onShow
应用启动的时候, 或者从后台进入前台会触发
onHide
应用从前台进入后台触发
页面生命周期
onLoad
监听页面加载
onShow
监听页面显示,每次切换到这个页面,都会执行
onReady
监听页面初次渲染完成 (如果渲染速度快, 会在页面进入动画完成前触发)
onHide
监听页面隐藏
onUnload
监听页面卸载,页面关闭
组件生命周期
beforeCreate
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用
created
实例创建完成之后立即调用, 挂载阶段还没有开始
mounted
挂载到实例上去之后调用
destroyed
vue 实例销毁后调用
大概顺序 App Launch
> App Show
> component beforeCreate
> component created
> page onload
> page onshow
> component mounted
> page onready
① 微信小程序
微信小程序 -> 设置 -> 安全设置 -> 服务端口 -> 开启
HBuilderX -> 配置 -> 运行配置 -> 把微信开发者工具路径 配置 起来
② app真机,模拟器
连接安卓设备
连接ios设备
ios 模拟器
③ h5, 如果直接运行到浏览器失效的话,可以按照下面操作
components
自定义组件的目录,自己创建的pages
页面存放目录static
静态文件资源目录unpackage
编译后的文件存放目录utils
公用的工具类,自己创建的common
公用的文件, 自己创建的App.vue
项目启动页main.js
应用入口,绑定全局变量,引用一些第三方库等manifest.json
项目配置page.json
页面配置,页面地址,页面名称等 文档: https://uniapp.dcloud.io/collocation/pages
uni.scss
scss配置pages.json
中的 globalStyle
中的配置,是所有页面的通用配置.pages.json
中的 pages
下面的配置,可以配置 单独终端(例如 微信小程序,h5,app等)的配置, 如下{
"pages": [
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "uni-app",
"app-plus":{
},
"mp-weixin":{
},
"h5":{
}
}
}
],
"globalStyle": {
...
}
}
tabbar
文档 https://uniapp.dcloud.io/collocation/pages?id=tabbar
, 写法如下,注意图片的路径写法.{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
...
],
"globalStyle": {
...
},
"tabBar": {
"color": "#666",
"selectedColor": "#ff5a5f",
"borderStyle": "black",
"list": [{
"pagePath": "pages/index/index",
"text": "首页",
// 本地图片, 大小 40kb, 尺寸建议 81*81px
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png"
}, {
"pagePath": "pages/about/about",
"text": "关于",
// 本地图片, 大小 40kb, 尺寸建议 81*81px
"iconPath": "static/follow.png",
"selectedIconPath": "static/follow-active.png"
}, {
"pagePath": "pages/my/my",
"text": "首页",
// 本地图片, 大小 40kb, 尺寸建议 81*81px
"iconPath": "static/my.png",
"selectedIconPath": "static/my-active.png"
}]
}
}
tabbar
会缓存每个页面,所以 onLoad
只会隐藏,不会重新加载.tabbar
中有一个新的生命周期 onTabItemTap(e)
, tabbar 点击就会触发, 这个e
返回例如 {index: 0, text: "首页", pagePath: "pages/index/index"}
scss/sass编译
, 支持嵌套
写法,如下例<style lang="scss">
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
.title {
font-size: 36rpx;
color: #8f8f94;
}
}
}
style>
<style lang="scss">
$width: 200rpx;
...
.content{
width: $width;
...
style>
&.box
, 不能有空格,要接在一起写.<style lang="scss">
$width: 200rpx;
.content {
display: flex;
// & 父级
&.box {
border:1px solid red;
}
style>
① 云函数 示例如下
'use strict';
exports.main = async (event, context) => {
// event 为客户端上传的参数
console.log('event:' + event)
// 返回数据给客户端
return event
};
② 云数据库 示例如下
'use strict'
//获取数据库引用
const db = uniCloud.database()
const collection = db.collection('user');
// 伪代码
exports.main = async (event, context) => {
//event 为客户端上传的参数
console.log('event: ' + event)
//将token写入数据库
collection.where({
name: event.data.name,
password: event.data.password
})
.update({
token: event.token,
token_time: event.timestamp
});
// 获取用户信息
const user_info = await collection.where({
name: event.data.name
}).get();
// 返回数据给客户端
return {
code: 200,
msg: '登录成功',
data: user_info.data
}
};
③ 云存储和CND
启动uniCloud(全端可用的云开发,使用js开发服务器逻辑.)
manifest.json
文件,查看`uni-app应用标识(AppID), 如果为空要重新获取.uniCloud
文件夹下新建 cloudfunctions
文件夹, 这个文件夹是存放云函数的, 可以点击新建云函数, 之后点击新建的云函数目录, 选择 上传部署
. 就可以上传到后台.uniCloud
文件夹, 选择 打开 uniCloud Web控制台...
, 就可以进入云开发控制台①
云函数
运行在云端(服务器端)的函数
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
console.log('event : ', event)
//返回数据给客户端
return event
};
event
为客户端上传的参数content
包含了调用信息和运行状态, 获取每次调用的 上下文②
uniCloud.callFunction
调用我们的云函数
...
methods: {
open() {
// 执行云函数
uniCloud.callFunction({
name: "get_list", //云函数的名字
data: {
// 参数
name: 'Liming',
age: 18
},
success(res) {
console.log(res)
},
fail(err) {
}
})
}
...
③ 在本地的
云函数
中如下return
返回,这个返回就是上面的success(res)
中的res
的值
'use strict';
exports.main = async (event, context) => {
//event为客户端上传的参数
console.log('event : ', event)
//返回数据给客户端
return {
content: '成功'
}
};
④ 注意: 如果修改了 本地的云函数,
一定要上传部署
,不然是不生效的.
云数据库
的添加和删除, 只能在 云函数
中运行① 云函数中如何连接数据库
'use strict';
// 连接到数据库
const db = uniCloud.database()
exports.main = async (event, context) => {
// 连接到 `user` 表
const collection = db.collection('user')
//返回数据给客户端
return {
}
};
const collection = db.collection('user')
// 连接到数据库const collection = db.collection('user')
// 连接到 user
表② 添加数据
add
方法
let res = await collection.add({
name: 'uni-app'
})
let res = await collection.add([
{
name: 'vue'
},
{
name: 'html',
type: '前端'
}
])
③ 删除数据
doc
选择数据 然后remove
删除
let res = await collection.doc('60092bbc6cb4fb0001f96b05').remove()
① 记录更新
doc
选择数据,update
或者set
2个方法使用是一样的,用来更新数据
//删除数据
let res = await collection.doc('60092bbc6cb4fb0001f96b04').update({
name: 'html'
})
②
update
和set
d的区别
update
只能更新存在的记录.set
如果记录存在就更新, 如果不存在就添加.③ 查找数据
get
where
doc
是查询条件, get
获取数据(并不是获取一条数据,是根据条件来获取,没有写条件就是获取全部)let res = await collection.doc('60091e078976a900010cf515').get()
doc
只能根据 id
来查询, where
可以根据条件来查询let res = await collection.where({
name: 'vue-test'
}).get()
④ 返回数据
//返回数据给客户端
return {
code: 200,
msg: '查询成功',
data: res.data
}
⑤ 如何根据前端提交的参数来获取数据?
event
就是前端提交过来的数据,就可以根据这个数据来做筛选, 如下let res = await collection.where({
name: event.name
}).get()
① 上传文件
uniCloud.uploadFile
methods: {
open() {
// 图片上传apis
uni.chooseImage({
count: 1,
success(res) {
const tempFilePath = res.tempFilePaths[0]
console.log(res)
uniCloud.uploadFile({
filePath: tempFilePath,
cloudPath: res.tempFiles[0].name,
success(res) {
console.log(res);
},
fail(err) {
console.log(err);
}
})
},
fail(err) {
console.log(err);
}
})
}
}
cloudPath
- 使用阿里云时,cloudPath为云端文件名,请勿使用非法字符
https://uniapp.dcloud.io/uniCloud/storage?id=uploadfile
② 删除文件
uniCloud.deleteFile
阿里云不支持此API,前端运行此API会报权限错误
uniCloud.deleteFile({
fileList:['59a0e604-79b9-4d58-9aae-53cc4eda7db5'],
success(res) {
console.log(res);
},
fail(err) {
console.log(err);
}
})
①
db_init.json初始化数据库
位置:uniCloud
->database
->db_init.json
如果没有就自己新建
文档:https://uniapp.dcloud.io/uniCloud/hellodb?id=db-init
{
"list": {
// 集合(表名)
"data": [ // 数据
{
"name": "tom"
},
{
"name": "liming"
}
]
}
}
初始化云数据库
, 控制台就可以看到这个数据已经同步到后台了初始化云数据库
, 同步到后台.1 取消原来的导航栏, 选用自定义导航栏
"navigationStyle":"custom",
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/tabbar/index/index",
"style": {
"navigationStyle":"custom",
...
}
}
...
2 把导航栏作为一个新的自定义组件来操作, 在根目录下新建
components
, 然后再新建组件并创建同名目录navbar
3 在需要调用的页面,
import
导入,然后在components
中注册,之后就可以使用了. 但是在uni-app
中有一个简单的方法easyCom
easyCom
是局部引入, 在需要调用的文件中, 直接使用即可.
<template>
<view class="content">
<navbar>navbar>
view>
template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
}
script>
navbar
,也没有在 components
中注册,但是由于 easyCom
的存在, 则可以直接使用.不会报错.① 顶部状态栏高度的动态赋值
<view :style="{
height: statusBarHeight+'px;'}">view>
...
<script>
//获取手机系统信息
const info = uni.getSystemInfoSync();
//设置状态栏高度
this.statusBarHeight = info.statusBarHeight;
script>
② 适配小程序和h5的解决方案
<template>
<view class="navbar">
<view class="navbar-fixed">
<view :style="{
height: statusBarHeight+'px'}">view>
<view class="navbar-content" :style="{
height:navBarHeight+'px',width:windowWidth+'px'}">
<view class="navbar-search">
<view class="navbar-search_icon">
<uni-icons type="search" size="16" color="#999">uni-icons>
view>
<view class="navbar-search_text">uni-app, vueview>
view>
view>
view>
<view :style="{
height: statusBarHeight+navBarHeight+'px'}">view>
view>
template>
<script>
export default {
data() {
return {
statusBarHeight: 20, //顶部状态栏的高度
navBarHeight: 40,
windowWidth: 375
};
},
created() {
//获取手机系统信息
const info = uni.getSystemInfoSync();
//设置状态栏高度
this.statusBarHeight = info.statusBarHeight;
this.windowWidth = info.windowWidth
// h5 app mp-alipay
// #ifndef H5 || APP-PLUS || MP-ALIPAY
//获取微信右上角胶囊的位置
const menuButtonInfo = uni.getMenuButtonBoundingClientRect()
console.log(menuButtonInfo)
// (胶囊底部高度 - 状态栏高度) + (胶囊顶部高度 - 状态栏内的高度) = 导航栏的高度
this.navBarHeight = (menuButtonInfo.bottom - info.statusBarHeight) + (menuButtonInfo.top - info.statusBarHeight)
this.windowWidth = menuButtonInfo.left
// #endif
}
}
script>
<style lang="scss">
.navbar {
.navbar-fixed {
position: fixed;
top: 0;
left: 0;
z-index: 99;
width: 100%;
background-color: $mk-base-color;
.navbar-content {
display: flex;
justify-content: center;
align-items: center;
height: 45px;
padding: 0 15px;
box-sizing: border-box;
.navbar-search {
display: flex;
align-items: center;
padding: 0 10px;
width: 100%;
height: 30px;
border-radius: 30px;
background-color: #fff;
.navbar-search_icon {
margin-right: 10px;
}
.navbar-search_text {
font-size: 12px;
color: #999;
}
}
}
}
}
style>
插件市场搜索
icons
然后下载到本地
引用
文档: https://hellouniapp.dcloud.net.cn/pages/extUI/icons/icons
组件
的形式来写scss
伪类写法.tab-icons{
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 45px;
&::after{
content: '';
position: absolute;
top: 12px;
bottom: 12px;
left: 0;
width: 1px;
background-color: #ddd;
}
const { result } = res;
和 .then() 写法
methods: {
getLabel() {
// 调用云函数
uniCloud.callFunction({
name: 'get_label',
}).then(res => {
const {
result } = res;
this.tabList = result.data;
})
}
}
// 调用云函数
uniCloud.callFunction({
name: 'get_label',
success(res) {
console.log(res.result);
},
fail(err) {
}
});
大概步骤
父页面
中, 获取数据, 然后赋给组件
组件
中, 通过 props
注册一下. 这里是 Array类型
<script>
export default {
props: {
list: {
type: Array,
default () {
return []
}
}
},
...
组件
中就可以使用 list
来做操作了.common
文件夹下面新建api
文件夹,再新建index.js
, 在其中封装一个 Promise(), 如下const get_label = (data) => {
return new Promise((reslove, reject) => {
uniCloud.callFunction({
name: 'get_label',
data
}).then(res => {
if (res.code === 200) {
// .then
reslove(res.result);
} else {
// catch
reject(res.result);
}
}).catch(err => {
reject(err);
})
})
}
export default {
get_label
}
main.js
中, import
然后再赋值, 如下import api from './common/api'
...
Vue.prototype.$api = api
methods: {
getLabel() {
this.$api.get_label({
name: 'get_label'
}).then(res => {
const {
data
} = res;
this.tabList = data;
})
}
}
common/api
下新建 list.js
文件, 把之前的 代码拷贝进入, 再 export
出来export const get_label = (data) => {
return new Promise((reslove, reject) => {
uniCloud.callFunction({
name: 'get_label',
data
}).then(res => {
if (res.result.code === 200) {
// .then
reslove(res.result);
} else {
// catch
reject(res.result);
}
}).catch(err => {
reject(err);
})
})
}
common/api
的 index.js
中,修改代码如下, 这样每个代码分开管理.import {
get_label} from './list.js'
export default {
get_label
}
return Promise..
, 可以在 common
文件夹下面 新进一个 http.js
export default function $http(options) {
const {
url,
data
} = options
return new Promise((reslove, reject) => {
uniCloud.callFunction({
name: url,
data
}).then(res => {
if (res.result.code === 200) {
// .then
reslove(res.result);
} else {
// catch
reject(res.result);
}
}).catch(err => {
reject(err);
})
})
}
common/api/list.js
中的内容优化如下import $http from '../http.js'
export const get_label = (data) => {
return $http({
url: 'get_label',
data
})
}
export const get_list = (data) => {
return $http({
url: 'get_list',
data
})
}
list.js
优化完毕, 但是在其中每加入一个函数,都需要在 index.js
中导入,然后注册. 如下,可以利用require.context
方法,实现自动导入, 之后, 在list.js
中写入新的函数,就不需要在index.js
中注册了, 已经自动帮我们注册了.之后直接写函数,直接调用即可.//批量导出文件
const requireApi = require.context(
// api 目录的相对路径
'.',
//是否查询子目录
false,
//查询文件的一个后缀
/.js$/
)
let module = {
};
requireApi.keys().forEach((key, index) => {
if (key === './index.js') return;
console.log(key);
Object.assign(module, requireApi(key));
})
export default module
加一个点击事件,绑定一个class :class="{active:activeIndex === index}" @click="clickTab(item,index)"
把事件返回给 父页面
methods: {
// 点击导航栏高亮
clickTab(item, index) {
this.activeIndex = index
//把事件传递到父页面去
this.$emit('tab', {
data: item,
index: index
})
}
}
tab
是自定义事件methods
里面注册一下tab(data, index) {
console.log(data, index);
}
list
组件, 如下 <swiper-item>
<list-scroll class="list-scroll">
<list-card mode="base">list-card>
<list-card mode="image">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
list-scroll>
swiper-item>
list-item.vue
, 把中间的部分拿出来<template>
<list-scroll class="list-scroll">
<list-card mode="base">list-card>
<list-card mode="image">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
<list-card mode="column">list-card>
list-scroll>
template>
<script>
script>
<style lang="scss">
.list-scroll {
height: 100%;
}
style>
easyCom
的规范,所以需要重新导入,然后注册一下.如下<template>
<swiper class="home-swiper">
<swiper-item>
<list-item>list-item>
swiper-item>
swiper>
template>
<script>
import listItem from './list-item.vue'
export default {
components: {
listItem
},
...
data
的值,这样就会出现闪烁的情况. 解决方法,就是将每一页的数据,放到缓存数据中,例如数组中. 把每一页的数据加到这个数组中,则可以保证,加载的时候,不会出现闪烁的情况.加载插件 loadmore
- LoadMore 加载更多 DCloudDCloud出品
https://ext.dcloud.net.cn/plugin?id=29
this.$set()
this.$forceUpdate()
this.$set(this.load, current, oldLoad)
// 强制渲染
this.$forceUpdate()
@click.native.stop
uni.showLoading()
uni.showLoading()
uni.showToast({
title: this.like ? '收藏成功' : '取消收藏',
icon: 'none'
})
uni.navigateTo({
url: '/pages/home-search/home-search'
})
store
store
目录下,新建 index.js
// vuex 状态管理
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state:{
}
})
export default store
main.js
中注册一下...
import store from './store'
...
const app = new Vue({
store,
...App
})
uni-load-more
<uni-load-more v-if="loading" status="loading" iconType="snow">uni-load-more>
// 执行
this.loading = true
//关闭
this.loading = false
uni.navigateBack()
uni.switchTab({
url: '/pages/tabbar/index/index'
})
vuex
并不是持久化的存储,这里改造下vuex
中的代码
historyLists: uni.getStorageSync("__hostory")
获取本地缓存uni.setStorageSync('__hostory', list)
设置本地缓存uni.removeStorageSync('__hostory')
清空本地缓存// vuex 状态管理
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 数据源
state: {
historyLists: uni.getStorageSync("__hostory") || []
},
//可以改变数据源中的数据
mutations: {
SET_HISTORY_LISTS(state, history) {
state.historyLists = history
},
CLEAR_HISTORY(state, history){
state.historyLists = []
}
},
actions: {
set_history({
commit, state}, history) {
let list = state.historyLists
list.unshift(history)
uni.setStorageSync('__hostory', list)
commit('SET_HISTORY_LISTS', list)
},
clear_history({
commit}){
uni.removeStorageSync('__hostory')
commit('CLEAR_HISTORY')
}
}
})
export default store
uni.$emit
步骤
uni.$emit('事件名', 参数[可省略])
onLoad()
中监听 uni.$on('事件名', 参数[可省略])
uni.$on('labelChange', (res) => {
this.getLabel();
})
onLoad
中接受, 再将字符串通过 JSON.parse(str)
解析成对象onLoad(query) {
console.log(JSON.parse(query.params));
},
预加载
的效果.步骤
JSON.stringify(object)
转为 字符串const params = {
_id: item._id,
title: item.title,
create_time: item.create_time,
thumbs_up_count: item.thumbs_up_count,
borwse_count: item.borwse_count
}
//...
uni.na
vigateTo({
url: '/pages/home-detail/home-detail?params=' + JSON.stringify(params)
})
gaoyia-parse
,拷贝到本地的 components
目录下, 注意:这个插件需要手动导入并注册!
import uParse from '@/components/gaoyia-parse/parse.vue'
<script>
import uParse from '@/components/gaoyia-parse/parse.vue'
export default {
components: {
uParse
},
//...
App.vue
中引入css
<style>
/*每个页面公共css */
@import 'components/gaoyia-parse/parse.css';
style>
uni-popup
, 下载下来,还有一个依赖的组件 uni-transition
https://ext.dcloud.net.cn/plugin?id=329
使用步骤
<uni-popup ref="popup" type="bottom">
<view class="popup-wrap">
弹出层
view>
uni-popup>
打开 this.$refs.popup.open()
注意, 如果一进入页面就要打开, 这个事件不可以直接放在 onLoad
中,因为 onLoad
时候,这个组件还没有渲染, 可以放在 onReady
中.
控制点击后面蒙版是否关闭弹窗 :maskClick="false"
<uni-popup ref="popup" type="bottom" :maskClick="false">
步骤
import
导入自身 import commentsBox from '@/components/comments-box/comments-box.vue'
<script>
import commentsBox from '@/components/comments-box/comments-box.vue'
export default {
name: "comments-box",
components: {
commentsBox
},
//...
name
例如 name: "comments-box",
onReachBottom
utils
的文件夹, 然后新建一个 index.js
文件index.js
中输入// 时间格式化
export const parseTime = (time) => {
console.log(time)
}
import {
parseTime} from '@/utils/index.js'
filters
filters: {
formatTime(time) {
return parseTime(time)
}
},
{ {comments.create_time | formatTime}}
过滤器使用, 如上
comments.create_time
是formatTime
的一个参数, 如果formatTime
有多个参数, 直接在后面写上,
例如, 这里的
{ {comments.create_time | formatTime(a, b)}} a
是第二个参数,b
是第三个参数.
vuex
的记录userinfo
用来保存用户信息的记录.store/index.js
中, 添加如下代码// vuex 状态管理
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
// 数据源
state: {
userinfo: uni.getStorageSync('USERINFO') || {
}
},
//可以改变数据源中的数据
mutations: {
SET_USER_INFO(state, userinfo) {
state.userinfo = userinfo
}
},
actions: {
set_userinfo({
commit}, userinfo) {
uni.setStorageSync('USERINFO', userinfo)
commit('SET_USER_INFO', userinfo)
}
}
})
export default store
app.vue
中调用,一开始获取到用户的信息,然后赋值给 vuex
onLaunch: function() {
console.log('App Launch')
this.$api.get_user({
user_id: '600966e08976a900010da78d'
}).then(res => {
const {
data
} = res
this.$store.dispatch('set_userinfo', data)
})
},
computed
中声明, 在其他地方就可以调用 this.userinfo
了, 如下<script>
import {
mapState } from 'vuex'
export default {
data() {
return {
}
},
computed: {
...mapState(['userinfo'])
},
onLoad() {
console.log(this.userinfo);
},
methods: {
}
}
script>
common/https.js
中用一个默认的id来获取数据,现在有了 vuex
中的数据, 则需要将 https.js
中的代码修改一下,如下, 先导入, 再使用import store from '../store/index.js'
export default function $http(options) {
const {
url,
data
} = options
const dataObj = {
user_id: store.state.userinfo._id,
...data
}
//...
描述: 在
app.vue
中,异步
获取到了用户信息,然后放到vuex
中,但是加载到首页的时候,在首页的onload
中,我们就已经用到了用户信息,但是由于异步
, 数据此时可能还没有传递过来.这个问题,要用过监听vuex
中的userinfo
, 让首页在识别到的情况下,在做操作.
步骤
vuex
import {
mapState } from 'vuex'
computed
中注册一下computed: {
...mapState(['userinfo'])
},
useinfo
的变化, 如果发生了变化,说明已经获取到了,没有变化则没有获取到watch: {
userinfo(newVal) {
// 获取 tab 导航栏的信息
this.getLabel();
}
},