uni-app全栈仿开源项⽬系列(⼀)
叮咚项⽬参考⽂档 v1.0
项⽬技术栈:
前端:uni-app + nvue 实现原⽣页⾯渲染、同时兼容多端。
后端:Egg.js + MySQL + Redis 实现后端API服务。
不使⽤第三⽅组件库,⾃⼰写⼀套。
NVUE需要注意的点
在NVUE中引⼊字体图标需要参考Weex的引⼊规则
NVUE模式下的页⾯默认是Flex布局
iconfont图标应该放在text标签中包裹,不能直接使⽤view标签包裹
NVUE中的屏幕都是以750像素为基准
text组件换⾏问题,text组件中的内容如果有换⾏,显⽰的效果也会换⾏
Weex是从上到下进⾏渲染的,如果你的元素有定位之类的脱离⽂档流的需求,元素最好按顺序写,否则z-index可能也救不了你。
⽬前仅 iOS ⽀持 box-shadow 属性,Android 暂不⽀持,可以使⽤图⽚代替。每个元素只⽀持设置⼀个阴影效果,不⽀持多个阴影同时作⽤于⼀个元素。
uni-app中 vue 和 nvue 的区别:
uni-app是逻辑和渲染分离的。渲染层,在app端提供了两套排版引擎:⼩程序⽅式的webview渲染,和weex⽅式的原⽣渲染。
两种渲染引擎可以⾃⼰根据需要选。vue⽂件⾛的webview渲染,nvue⾛的原⽣渲染。
组件和js写法是⼀样的,css不⼀样,原⽣排版的能⽤的css必须是flex布局,这是web的css的⼦集。当然什么界⾯都可以⽤flex布出来。不懂flex布局就⾃⼰学。
⼀般情况下⽤vue就可以了。如果是app且有部分场景vue页⾯的性能不满⾜你的需求时,这个页⾯可以改⽤nvue页⾯。如果app⾥同时存在同名的vue和nvue页⾯,在app端会优先执⾏nvue页⾯,⽽其他端仍然优先vue页⾯。
区别和适⽤场景这⽂档⾥写的很清楚:
记录⼀些踩过的坑
1.环境搭建和项⽬创建
需要安装的插件:
内置浏览器
App真机运⾏
uni-app App调试
less编译
scss/sass编译
stylus编译
es6编译
创建项⽬:
项⽬类型为:uni-app,使⽤默认模版。
开启原⽣渲染:
uni-app在App端,⽀持vue页⾯和nvue页⾯混搭、互相跳转。也⽀持纯nvue原⽣渲染。
启⽤纯原⽣渲染模式,可以减少App端的包体积、减少使⽤时的内存占⽤。因为webview渲染模式的相关模块将被移除。
在manifest.json源码视图的"app-plus"下配置"renderer":"native",即代表App端启⽤纯原⽣渲染模式。此时pages.json注册的vue页⾯将被忽略,vue组件也将被原⽣渲染引擎来渲染。
如果不指定该值,默认是不启动纯原⽣渲染的。
// manifest.json
{
// ...
/* App平台特有配置 */
"app-plus": {
"renderer": "native", //App端纯原⽣渲染模式
}
}
使⽤uni-app编译模式:
// manifest.json
{
// ...
/* App平台特有配置 */
"app-plus": {
"renderer": "native", //App端纯原⽣渲染模式
"nvueCompiler" : "uni-app",
}
}
2.全局配置
2.1 引⼊全局样式
将封装好的free.css库引⼊到项⽬中。
2.2 引⼊⾃定义图标库
全局加载⾃⼰的字体图标库并且做多端适配:
<script>
export default {
onLaunch: function() {
// #ifdef APP-NVUE
// 加载公共图标库只有在NVUE环境下才加载
const domModule = quireModule('dom')
domModule.addRule('fontFace', {
'fontFamily': "iconfont",
src: "url('at.alicdn/t/font_f')"
});
// #endif
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页⾯公共css */
@import url("./common/free.css");
@import url("./common/common.css");
/
* #ifndef APP-PLUS */
@import url("./common/free-icon.css");
/* #endif */
</style>
如果对跨端兼容和条件编译语法不熟悉,可以参考
2.3 配置tabbar底部导航
修改package.json配置⽂件、添加tabbar配置。
这⾥的 tabbar 的 icon 图标⼤⼩为 81*81。
{
"pages": [ //pages数组中第⼀项表⽰应⽤启动页,参考:uniapp.dcloud.io/collocation/pages
{
"path": "pages/tabbar/index/index",
"style": {}
},
{
"path": "pages/tabbar/mail/mail",
"style": {}
},
{
"path": "pages/tabbar/find/find",
"style": {}
},
{
"path": "pages/tabbar/my/my",
"style": {}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "叮咚",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#000000",
"selectedColor": "#08C261",
"borderStyle": "black",
"backgroundColor": "#F7F7F7",
"list": [{
"iconPath": "static/tabbar/index.png",
"selectedIconPath": "static/tabbar/index-select.png",
"pagePath": "pages/tabbar/index/index",
"text": "⾸页"
},
{
"iconPath": "static/tabbar/mail.png",
"selectedIconPath": "static/tabbar/mail-select.png",
"pagePath": "pages/tabbar/mail/mail",
"text": "通讯录"
},
{
"iconPath": "static/tabbar/find.png",
"selectedIconPath": "static/tabbar/find-select.png",
"pagePath": "pages/tabbar/find/find",
"text": "发现"
},
{
"iconPath": "static/tabbar/my.png",
"selectedIconPath": "static/tabbar/my-select.png",
"pagePath": "pages/tabbar/my/my",
"text": "我的"
}
]
}
}
配置细节参考
2.4 配置globalStyle
取消APP端下的原⽣导航栏、滚动条。
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "叮咚",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"app-plus":{
"titleNView":false,
"scrollIndicator":"none"
}
}
3.聊天列表页开发
3.1 头部导航栏组件开发
<template>
<view>
<!-- 导航栏 -->
<view class="bg-light">
<!-- 状态栏 -->
<view :></view>
<!-- 导航 -->
<view class="w-100 flex align-center justify-between border" >
<!-- 左边标题部分 -->
<view class="flex align-center">
<text class="font-md ml-3">叮咚(10)</text>
</view>
<!-- 右边图标部分 -->
<view class="flex align-center">
<view class="flex align-center justify-center border" >      <text class="iconfont font-md"></text>
</view>
<view class="flex align-center justify-center border" >      <text class="iconfont font-md"></text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
statusBarHeight: 0 // 状态栏⾼度
}
},
onLoad() {
this.statusBarHeight = StatusbarHeight()
},
methods: {
}
}
</script>
<style lang="less">
</style>
3.2 [*]图标按钮组件封装
selectediconpath什么意思这个地⽅有⼀个坑:
NVUE 中如果使⽤ iconfont 的话就必须使⽤text标签进⾏包裹,如果要封装成组件,通过slot动态传递iconfont 的 16 进制值的话就会报错,因为 slot 会转换成text标签,⼜因为text标签⾥⾯不能再次嵌套text标签,所以报错,这个也是近期才发现的,以前看别⼈写没有问题,怎么解决呢?通过 props 传参。
封装的组件: free-icon-button.vue
<template>
<view
class="flex align-center justify-center"
hover-class="bg-hover-light" @click="$emit('click')"
>
<text class="iconfont font-md">{{iconValue}}</text>
</view>
</template>
<script>
export default {
name: '',
components: {},
props: {
iconValue: {
required: true
}
},
data () {
return {}
},
computed: {},
watch: {},
created () {
console.log(this.iconValue)
},
mounted () {},
methods: {}
}
</script>
<style scoped lang="less"></style>
调⽤组件的⽂件 index/index.nvue
<free-icon-button @click="handleIconButtonClick" :iconValue="'\ue682'"/>
这⾥⾯还有⼀个细节:
通过props⽅式传参的话 iconfont 的 16 进制值就不能写成 ,必须写成\ue682
这个问题通过查资料 + 反复实践⼤约耗时 30 分钟,因此记录⼀下这个坑。
3.3 封转头部导航组件
uni-app的普通组件中使⽤onLoad、onShow不⽣效?,要⽤created、mounted,为什么?
这个就要从uni-app的⽣命周期说起了。。。
uni-app有 3 类⽣命周期:
应⽤⽣命周期
页⾯⽣命周期
组件⽣命周期
应⽤⽣命周期:
重点是应⽤⽣命周期只能在App.vue中监听,其他页⾯监听⽆效,所以不要⽤错了。
页⾯⽣命周期:
需要注意的是:onLoad和onReady只会触发⼀次,这是官⽅没有说的,所以还是要多实践!
以上是常⽤的⼏个,想了解全部的参考
组件⽣命周期:
uni-app 组件⽀持的⽣命周期,与vue标准组件的⽣命周期相同。这⾥没有页⾯级的onLoad等⽣命周期:
以后编写组件的时候就要细⼼点,页⾯组件就⽤页⾯的⽣命周期,普通组件就⽤组件的⽣命周期,别乱搞给⾃⼰挖坑。index/index.nvue 页⾯代码
<template>
<view>
<!-- 导航栏 -->
<free-nav-bar title titleValue="叮咚(99+)" fixed />
<!-- 列表 -->
<view >
<text>好好学习,天天向上!</text>
</view>
</view>
</template>
<script>
import FreeNavBar from '@/components/free-ui/free-nav-bar.vue'
export default {
name: "IndexPage",
components: {
FreeNavBar
},
data() {
return {}
},
methods: {}
}
</script>
<style lang="less">
</style>
free-nav-bar.vue 组件代码
<template>
<view>
<!-- 导航栏 -->
<view class="bg-light" :class="fixed?'fixed-top':''">
<!-- 状态栏 -->
<view :></view>
<!-- 导航 -->
<view class="w-100 flex align-center justify-between border" >
<!-- 左边标题部分 -->
<view class="flex align-center">
<text v-if="title" class="font-md ml-3">{{titleValue}}</text>
</view>
<!-- 右边图标部分 -->
<view class="flex align-center">
<free-icon-button :iconValue="'\ue6e3'" />
<free-icon-button :iconValue="'\ue682'"/>
</view>
</view>
</view>
<!-- 占位 -->
<view v-if="fixed" :></view>
</view>
</template>
<script>
import FreeIconButton from '@/components/free-ui/free-icon-button.vue'
export default {
name: 'FreeNavBar',
components: {
FreeIconButton,
},
props: {
// 是否显⽰标题
title: {
type: Boolean,
default: false

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。