uni-app 快速入门 从零开始实现新闻资讯类跨端应用(更新中)

文章目录

  • uni-app 快速入门 从零开始实现新闻资讯类跨端应用(更新中)
  • 一、微信小程序基础
    • 1.初始化文件目录结构
    • 2.数据绑定,条件判断、列表渲染
  • 二、uni-app基础
    • 1.uni-app核心知识点概况
    • 2.uni-app环境搭建
    • 3.uni-app模板语法和数据绑定
    • 4.uni-app条件判断
    • 5.uni-app列表渲染
    • 6.uni-app基础组件使用
    • 7.uni-app自定义组件
    • 8.uni-app基础api使用
    • 9.uni-app条件编译
    • 10.uni-app页面布局
    • 10.uni-app生命周期
  • 三、项目基础配置
    • 1.uni-app项目配置
    • 2.uni-app目录结构了解
    • 3.配置项目底部选项卡
    • 4.在uni-app中使用sass
  • 四、uniCloud (云开发平台)的基础用法
    • 1.认识 uniCloud开发
    • 2.HBuilderX 中配置 uniCloud 环境
    • 3. 使用 uniCloud web 控制台
    • 4. 开始使用云函数
    • 5.云数据库的添加和删除
    • 6.数据库的更新和查找
    • 7.使用云储存上传文件
  • 五、首页功能模块
    • 1.项目初始化
    • 2. 自定义导航栏
    • 3.导航栏适配小程序
    • 4 .使用字体图标
    • 5.选项卡展示
    • 6.选项卡数据初始化
    • 7.封装数据请求
    • 8.选项卡切换
    • 9.基础卡片实现
    • 10.更多卡片视图实现
    • 11.实现内容切换
    • 12.选项卡与内容联动
    • 13.内容卡片数据初始化

一、微信小程序基础

1.初始化文件目录结构

1、utils文件夹主要存放工具类pages目录存放所有页面代码app.js是文件入口app.jasn是项目配置app.wxss是全局样式表
2、index目录  index.js当前页面的业务逻辑index.json当前页面的配置文件index.wxml当前页面模板index.wxss当前页面的样式

2.数据绑定,条件判断、列表渲染

index.js

//必须使用Page构造器来构造页面
Page({/*** 页面的初始数据*/data: {name:'hzy',is_ok:false,list:['1','2','3','4']},/*** 生命周期函数--监听页面加载*/onLoad: function (options) {//改变数据的方法this.setData(obj)//this是指当前对象的实例,指向PagesetTimeout(()=>{this.setData({name:'wwj',is_ok:true})},2000)},/*** 生命周期函数--监听页面初次渲染完成*/onReady: function () {},/*** 生命周期函数--监听页面显示*/onShow: function () {},/*** 生命周期函数--监听页面隐藏*/onHide: function () {},/*** 生命周期函数--监听页面卸载*/onUnload: function () {},/*** 页面相关事件处理函数--监听用户下拉动作*/onPullDownRefresh: function () {},/*** 页面上拉触底事件的处理函数*/onReachBottom: function () {},/*** 用户点击右上角分享*/onShareAppMessage: function () {}
})

index.wxml

<!--pages/index/index.wxml-->
<text wx:if="{{is_ok}}">{{name}}</text>
<!--text 是行级元素,相当于span-->
<!--wx:if 控制标签是否渲染-->
<view wx:for="{{list}}">{{item}}</view>
<!--view 是块级元素,相当于div-->
<!--wx:for 控制标签循环渲染-->
<!--item 是指当前变量默认值index 是指当前下标默认值-->
<!--<view wx:for="{{list}}" wx:for-item="list">{{list}}</view> 等价于<view wx:for="{{list}}">{{item}}</view>
-->

二、uni-app基础

1.uni-app核心知识点概况

1.1 uni-app规范

①页面文件遵循Vue单文件组件(SFC)规范

②组件标签接近小程序规范

③接口能力(JS API)靠近小程序规范

④数据绑定及事件处理同Vue.js规范
⑤为兼容多端运行,建议使用flex布局进行开发

1.2 uni-app特色

①条件编译

②App端的Nvue开发法
③HTML5+

1.2 uni-app特色

2.uni-app环境搭建

①HBuilder直接创建
②vue-cli命令行创建

1、npm install -g @vue/cli 安装vue-cli
2、 vue -V  查看vue-cli版本,是否安装成功
3、 vue create -p dcloudio/uni-preset-vue 名称  安装uni-app项目

3.uni-app模板语法和数据绑定

<template><view v-bind:class="className" v-on:click="open">{{title}}</view><!-- v-bind:表示class的值为动态 --><!-- 与小程序不同的是这里的v-bind:class,直接赋值,而不用{{}} --><!-- :是v-bind:简写 --><!-- @是v-on:简写 -->
</template><script>export default {//初始化数据data() {return {title: '两秒之前',className:'bul'}},onLoad() {},//自定义的事件方法写到methods里面methods: {//两秒之后修改title和classNameopen(){setTimeout(()=>{this.title="两秒之后"this.className="gre"//this指向view实例,赋值方便,不用setstate和setData},2000)}}}
</script><style>.bul {color: #007AFF;}.gre{color: #4CD964;}
</style>

4.uni-app条件判断

<template><view><view>这是一直显示的内容</view><view><view v-if="show==='vue'">{{show}}</view><view v-else-if="show==='react'">{{show}}</view><view v-else>uni-app</view></view><!-- v-if: 指令的表达式返回true才会渲染 --><button @click="isShow()">点击</button></view>
</template><script>export default {data() {return {show: 'vue'}},onLoad() {},methods: {isShow() {this.show = this.show === 'vue' ? 'react' : 'vue'}}}
</script><style>
</style>

5.uni-app列表渲染

<template><view><!-- 列表渲染,通过数组来渲染列表 --><view v-for="(item,index) in arr">{{index+1+' '+item}}</view><!-- item:被迭代的数组元素的别名 --><!-- index:被迭代的数组元素的下标 --><view v-for="(value,key) in obj">{{key+' : '+value}}</view><!-- 同时也可以遍历对象 可以获取value和key, 顺序不要弄错--></view>
</template><script>export default {data() {return {arr:['uni-app','vue','react'],obj:{name:'hzy',age:18,type:'man',}}},onLoad() {},methods: {}}
</script><style>
</style>

6.uni-app基础组件使用

<template><!-- uni-app基础组件使用,view也是基础组件,相当于html的div标签 --><view><view>view标签:</view><view hover-class="redd">vue</view><!-- hover-class指定点击下去的样式类 --><view>react</view><view>text标签:</view><text>vue</text><text>react</text><!-- text标签相当于html的span,行内元素--><scroll-view scroll-y="true" class="height" @scroll="scroll"><view v-for="item in 20">{{item}}</view></scroll-view><!-- 可滚动视图区域,必须设置高度 --><!-- @scroll触发滚动时候的响应事件 --><button type="default" @click="input">点击</button><!-- <input type="text" v-bind:value="value"> --><input type="text" v-model="value"><view>{{value}}</view><!-- value前面得加上v-bind:表示他是个动态绑定的值,或者使用v-model,指的是双向绑定 --></view>
</template><script>export default {data() {return {value: 'vue'}},onLoad() {},methods: {scroll(e) {console.log(e)},input() {this.value = this.value === 'vue' ? 'react' : 'vue'}}}
</script><style>.redd {border: 1px red solid;}.height {height: 50px;border: 1px red solid;}
</style>

7.uni-app自定义组件

index.vue 主页面

<template><view><hzyBtn color="blue" @change="change"></hzyBtn><!-- 让组件去接收一个名为change的事件 --></view>
</template><script>//在script标签下引用自定义组件,@表示的事根目录import but from '@/components/hzyBtn/hzyBtn.vue'export default {data() {return {}},onLoad() {},methods: {change(e) {console.log('页面的事件被触发,组件返回了:' + e)}}}
</script><style>
</style>

hzyBtn.vue 自定义按钮组件

<template><view class="btn-box" :style="{color:color}" @click="butClick">点击</view>
</template><script>export default {props: {color: {type: String,default: '#000'},// color接受一个类型为String的对象,默认值为'#000'},// props接收属性data() {return {};},methods: {butClick() {console.log('组件内事件触发')this.$emit('change', this.color)//触发页面传来的‘change’事件}}}
</script><style>.btn-box {width: 200px;height: 100px;text-align: center;line-height: 100px;border: 1px red solid;}
</style>

页面

点击之后控制台打印

8.uni-app基础api使用

<template><view></view>
</template>
<script>export default {data() {return {}},onLoad() {uni.getSystemInfo({success(res) {console.log('成功的回调', res)},fail(err) {console.log('失败的回调', err)},complete(res) {console.log('不管成功失败都会返回')}})//uni.getSystemInfo(obj)获取系统信息的api,异步的},// onLoad()只加载一次,监听页面加载,其参数为上个页面传递的数据,参数类型为Objectmethods: {}}
</script>
<style>
</style>

9.uni-app条件编译

<template><view><!-- 条件编译写在对应的注释里 --><!-- 表示在h5和app端才进行这段代码的编译 --><!-- #ifdef H5 || APP-PLUS--><view>h5和app平台才显示</view><!-- #endif --><!-- #ifndef MP-WEIXIN --><view>微信小程序不显示,其他都显示</view><!-- #endif --></view>
</template><script>export default {data() {return {}},onLoad() {},methods: {// #ifdef// #endif}}
</script><style>/* #ifdef *//* #endif */
</style>

10.uni-app页面布局

<template><view class="content color">uni-app</view>
</template>
<script>export default {data() {return {}},onLoad() {},methods: {}}
</script>
<style>@import 'index.css';/* 引入外部css方式 *//* page{}等价于body{} */page {background-color: #007AFF;}/* 尺寸单位*/.content {/* px rpx rem vh vx*/font-size: 50px;}
</style>

10.uni-app生命周期

①应用生命周期(定义在app.vue页面中)

<script>// 生命周期分为三种:// 应用生命周期:定义在app.vue页面中// 页面生命周期// 组件生命周期export default {//应用初始化完成触发一次,全局只触发一次//可以做一些登录的事情,或者拿一些全局变量onLaunch: function() {console.log('App Launch')},//应用启动的时候,或者从后台进入前台会触发onShow: function() {console.log('App Show')},//应用从前台进入后台触发onHide: function() {console.log('App Hide')}}
</script><style>/*每个页面公共css */
</style>

②页面生命周期

<template><view><view>生命周期</view><hzyText></hzyText></view>
</template>
<script>import hzyText from '@/components/hzyText/hzyText.vue'export default {data() {return {}},//监听页面加载(页面加载之后执行,再次加载时候不执行,浏览器有缓存)onLoad() {console.log('page onLoad')},//监听页面初次渲染完成onReady() {//如果渲染速度快,会在页面进入动画完成前触发console.log('page onReady')},//监听页面显示,页面每次出现在屏幕上都会触发onShow(){console.log('page onShow')},//监听页面隐藏onHide(){console.log('page onHide')},//监听页面卸载onUnload(){console.log('page onUnload')},methods: {}}
</script>
<style>
</style>

③组件生命周期

<template><view>hzyText组件</view>
</template><script>export default {data() {return {};},//在实例初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用beforeCreate() {console.log('beforeCreate')},//实例创建完成之后立即调用,挂载阶段还没开始created() {console.log('created')},//挂载到实例上去之后调用mounted() {console.log('mounted')},//Vue实例销毁后调用destroyed() {console.log('destroyed')}}
</script><style></style>

三、项目基础配置

1.uni-app项目配置

①微信小程序,微信开发者工具要在设置的安全中打开服务端口,Hx才能启用
②安卓真机,手机连接电脑后,点击关于手机,点击五次版本号,进入开发者模式,开启usb调试,打开传输文件
③H5

2.uni-app目录结构了解

目录结构
1、componens - 自定义组件目录
2、pages - 页面存放目录 (里面页面的目录和文件需同名 例如:logon中的logon.vue)
3、static - 静态文件资源目录(图片和字体可以放在该目录)
4、unpackage - 编译后的文件存放目录
5、utils - 自定义存放工具类的目录
6、common - 自定义存放公用东西的目录
7、App.vue - 页面入口(可以做用户登录、项目初始话、全局样式更改等)
8、main.js - 应用入口
9、manifest.json - 项目配置
10、pages.json - 页面配置
11、readme.md - 项目基本情况
12、uni.scss - uni-app内置的常用样式变量

3.配置项目底部选项卡

pages.json

{//"pages":注册页面文件,页面窗口表现形式"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages{"path": "pages/index/index","style": {"navigationBarTitleText": "uni-app",//app平台下特有窗口表现样式"app-plus": {},//微信小程序平台下特有窗口表现样式"mp-weixin": {},//h5平台下特有窗口表现样式"h5": {}}},{"path" : "pages/about/about","style" :                                                                                    {"navigationBarTitleText": "","enablePullDownRefresh": false}},{"path" : "pages/my/my","style" :                                                                                    {"navigationBarTitleText": "","enablePullDownRefresh": false}}],//"globalStyle"所有页面的默认配置,当"pages"下配置了和"globalStyle"一样的属性,就会将 "globalStyle"中的属性覆盖"globalStyle": {"navigationBarTextStyle": "black","navigationBarTitleText": "uni-app","navigationBarBackgroundColor": "#F8F8F8","backgroundColor": "#F8F8F8"},//"tabBar"指得是tab栏的表现"tabBar":{"color":"#666","selectedColor":"#ff5a5f",//选中时候的颜色"borderStyle":"black",//tabBar关联页面"list":[{"pagePath":"pages/index/index","text":"首页","iconPath":"static/home.png",//本地图片,大小40kb,尺寸81*81px"selectedIconPath":"static/home-active.png"//选中后图片},{"pagePath":"pages/about/about","text":"关于","iconPath":"static/follow.png",//本地图片,大小40kb,尺寸81*81px"selectedIconPath":"static/follow-active.png"//选中后图片},{"pagePath":"pages/my/my","text":"我的","iconPath":"static/my.png",//本地图片,大小40kb,尺寸81*81px"selectedIconPath":"static/my-active.png"//选中后图片}]}
}

总结:页面有个可以写onTabItemTap(e) { },这个生命周期函数是点击tebbar时候触发

4.在uni-app中使用sass

1、安装scss插件

<template><view class="content box"><image class="logo" src="/static/logo.png"></image><view class="text-area"><text class="title">{{title}}</text></view></view>
</template><script>export default {data() {return {title: 'Hello'}},onLoad() {},//tabbar点击触发的钩子onTabItemTap(e) {console.log(e)},methods: {}}
</script><style lang="scss">// scss可以写样式可以一层套一层$width : 200rpx; //变量定义用$.content {display: flex;flex-direction: column;align-items: center;justify-content: center;//&表示父级 box和content是同级的样式&.box{border: 1px red solid;}.logo {height: $width;width: $width;margin-top: $width;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"来引用scss

四、uniCloud (云开发平台)的基础用法

1.认识 uniCloud开发

①uniCloud是基于serverless模式和js编程的云开发平台
②用javascript开发前后台真题业务,开发成本大幅下降,只需专注业务
③非H5,免域名使用服务器
④uniCloud开发流程

⑤uniCloud构成
云函数:

云数据库
云储存和CDN3

2.HBuilderX 中配置 uniCloud 环境

第一步:确保uni-app应用标识处于获取状态

第二步:右键cloudfunctions创建云服务空间,回来后再次右键选择关联云服务空间

!!! 注意:创建云函数后要点击右键部署到云开发平台

3. 使用 uniCloud web 控制台

方式:右键cloudfunctions就可以打开uniCloud web控制台

注意:①在云数据库中,所有字段和值都要用双引号。②localhost在uni-app中已经自动解决了跨域问题,如果要通过本机的ip访问云服务器就得在云控制台中进行跨域配置

③项目可以直接使用云存储的图片,视频的链接,也可以直接上传文件到云存储

4. 开始使用云函数

云函数 get_list/index.js

'use strict';
exports.main = async (event, context) => {//event为客户端上传的参数//context 包含了调用信息和运行状态,每次调用的上下文console.log('event : ', event)//返回数据给客户端return {"content":"成功","event":event}
};

页面index.vue

 uniCloud.callFunction({//调用云函数name: "get_list",//传的参数data: {"name":"hzy"},//成功回调success(res) {console.log('云函数调用成功',res.result);},//失败回调fail(res) {console.log('云函数调用失败',res);}})

点击调用之后

5.云数据库的添加和删除

'use strict';
const db = uniCloud.database(); //1、获取数据库的引用
// 获取 `user` 集合的引用
exports.main = async (event, context) => {const collection = db.collection('user'); //2、获取集合的引用//给集合添加一条记录,就是添加一个json对象//添加await 之后数据才能同步let res = await collection.add([{"name": "angular","age": 60},{"name": "gofa","age": 100}])//删除云数据库中的记录,要传入ID,先用doc()找到,再用remove()删除let res = await collection.doc('5fd8e308fb0f850001897146').remove()return {}
};

6.数据库的更新和查找

①更新数据

'use strict';
const db = uniCloud.database(); //1、获取数据库的引用
// 获取 `user` 集合的引用
exports.main = async (event, context) => {const collection = db.collection('user'); //2、获取集合的引用//更新数据库记录,先用doc()找到,再用update()更新,也可以用set()来更新//可以增加字段,减少字段,修改字段//update() 只能更新存在的记录//set 如果记录存在就更新,如果不存在就添加const res = await collection.doc('5fd8e308fb0f850001897146').update(name:"likeReact")return {}
};

②查找数据

'use strict';
const db = uniCloud.database(); //1、获取数据库的引用
// 获取 `user` 集合的引用
exports.main = async (event, context) => {const collection = db.collection('user'); //2、获取集合的引用//查询,先通过doc()找到这条记录,再用get()把记录拿到//doc()只能应用id,不能应用其他字段const docRes = await collection.doc("5fd8e308fb0f850001897146").get()//where(),可以通过字段名称来找到记录,注意,需要传对象const whereRes = await collection.where({name:"vue"}).get()console.log(JSON.stringify(whereRes))return {}
};

7.使用云储存上传文件

//选择图片的apiuni.chooseImage({count: 1, //只允许上传一张图片success(res) {const tempFilePath = res.tempFilePaths[0] //获取第一张图片的地址//上传到云储存中console.log(tempFilePath)uniCloud.uploadFile({filePath: tempFilePath,cloudPath:"123456.jpg",//名称必须和上传的图片名称一致success(res) {console.log('success', res)//返回的filePath和fileID都可以直接拿来使用},fail() {console.log('fail', res)}})},fail(res) {console.log(res)}})

五、首页功能模块

1.项目初始化

1、创建db_init_json,初始化云数据库
2、配置tabbar
创建tabbar目录,将首页,关注,我的,三个页面放到tabbar文件目录下

在pages.json文件中配置tabbar

 "tabBar": {"color": "#666","selectedColor": "#f07373","backgroundColor": "#fff","list": [{"pagePath": "pages/tabbar/index/index","iconPath": "static/home.png","selectedIconPath": "static/home.png","text": "首页"}, {"pagePath": "pages/tabbar/follow/follow","iconPath": "static/follow.png","selectedIconPath": "static/follow-active.png","text": "关注"}, {"pagePath": "pages/tabbar/my/my","iconPath": "static/my.png","selectedIconPath": "static/my-active.png","text": "我的"}]}

2. 自定义导航栏

navbar.vue

<template><view class="navbar"><view class="navbar-fixed"><view class="navbar-serach"><view class="navbar-serach_icon"></view><view class="navbar-serach_text">请输入...</view></view></view><view style="height: 45px;"></view></view>
</template><script>export default {data() {return {};}}
</script><style lang="scss">.navbar{.navbar-fixed{position: fixed;//固定在顶部top:0px;left: 0px;z-index: 99;display: flex;justify-content: center;//水平居中align-items: center;width: 100%;height: 45px;//常见导航栏都是45pxbackground-color: $mk-base-color;padding: 0 15px;box-sizing: border-box;//只在盒内显示.navbar-serach{display: flex;//flex布局,横排align-items: center;//垂直居中height: 30px;border-radius: 30px;//和高度一样就能实现圆角width: 100%;padding: 0 10px;background-color: #fff;.navbar-serach_icon{width: 10px;height: 10px;border: 1px red solid;margin-right: 10px;}.navbar-serach_text{font-size: 12px;color: #999;}}}}
</style>


注意:①
一些常用的样式变量可以写到uni.scss中,方便以后直接通过名字引用

②uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用,而且还是局部引用,非常点赞

3.导航栏适配小程序

在小程序中是有一个状态栏的,所以做完H5之后还要添加一个状态栏,在navbar中做一下适配,在不同设配上小程序状态栏的高度不一样,导航栏的高度就等于胶囊的buttom减去状态栏高度在加top减去状态栏高度

<template><view class="navbar"><view class="navbar-fixed"><!-- 状态栏 --><view :style="{height:statusBarHeight+'px'}"></view><!-- 导航栏内容 --><view class="navbar-conten" :style="{height:navBarHeight+'px',width:navBarWidth+'px'}"><view class="navbar-serach"><view class="navbar-serach_icon"><uni-icons type="search" size="16px" color="#999"></uni-icons><!-- <text class="iconfont iconicon-test"></text> --></view><view class="navbar-serach_text">请输入...</view></view></view></view><view :style="{height:navBarHeight+statusBarHeight+'px'}"></view></view>
</template><script>export default {data() {return {statusBarHeight: 20, //状态栏高度navBarHeight: 45, //导航栏高度navBarWidth: 375, //内容宽度};},//组件加载的时候执行created() {//同步获取手机系统信息const info = uni.getSystemInfoSync()//设置状态栏高度(H5的状态栏高度是0)this.statusBarHeight = info.statusBarHeightthis.navBarWidth = info.windowWidth// #ifndef H5 || APP-PLUS || MP-ALIPAY//H5 app mp-alipay 不支持uni.getMenuButtonBoundingClientRect()这个api//获取胶囊的位置信息const menuButtonInfo = uni.getMenuButtonBoundingClientRect()//(胶囊底部高度-状态栏高度)+(胶囊顶部高度-状态栏高度)=导航栏高度this.navBarHeight = (menuButtonInfo.bottom - info.statusBarHeight) + (menuButtonInfo.top - info.statusBarHeight) + 4//内容宽度this.navBarWidth = menuButtonInfo.left// #endif}}
</script><style lang="scss">@import "../../common/icons/css/icons.css";.navbar {.navbar-fixed {position: fixed; //固定在顶部top: 0px;left: 0px;z-index: 99;width: 100%;background-color: $mk-base-color;.navbar-conten {display: flex;justify-content: center; //水平居中align-items: center;padding: 0 15px;box-sizing: border-box; //只在盒内显示.navbar-serach {display: flex; //flex布局,横排align-items: center; //垂直居中height: 30px;border-radius: 30px; //和高度一样就能实现圆角width: 100%;padding: 0 10px;background-color: #fff;.navbar-serach_icon {margin-right: 10px;}.navbar-serach_text {font-size: 12px;color: #999;}}}}}
</style>

微信状态栏的前景色是黑色的,如果要改成白色,则需要在pages.json中配置

4 .使用字体图标

①复制阿里图标库的icon代码

直接在text中通过类名引用

<text class="iconfont iconicon-test"></text>

②在插件市场安装icons图标插件
直接通过组件去引用

<uni-icons type="search" size="16px" color="#999"></uni-icons>

5.选项卡展示

<template><view class="tab"><scroll-view class="tab-scroll" scroll-x><view class="tab-scroll_box"><view v-for="item in list" :key="index" class="tab-scroll_item">{{item.name}}</view></view></scroll-view><view class="tab-icons"><uni-icons type="gear" size="26" color="#666"></uni-icons></view></view>
</template><script>export default {data() {return {list: [{name: 'uni-app'}, {name: 'uni-app'}, {name: 'uni-app'}, {name: 'uni-app'}, {name: 'uni-app'}, {name: 'uni-app'}, {name: 'uni-app'}]};}}
</script><style lang="scss">.tab {display: flex;width: 100%;border-bottom: 1px #f5f5f5 solid;background-color: #fff;box-sizing: border-box; //盒内元素.tab-scroll_box {display: flex;flex-wrap: nowrap; //不换行align-items: center; //垂直居中box-sizing: border-box; //盒内元素height: 45px;.tab-scroll_item {flex-shrink: 0; //不挤压padding: 0 10px;color: #333;font-size: 14px;}}.tab-icons {position: relative;display: flex;justify-content: center; //水平居中align-items: center; //垂直居中width: 45px;&::after{// &::after指的是该元素后面的内容content: '';position: absolute;top:12px;bottom:12px;left: 0;width: 1px;background-color: #ddd;}}}
</style>

6.选项卡数据初始化

云函数get_label

'use strict';
const db = uniCloud.database()//创建数据库的引用
exports.main = async (event, context) => {let label = await db.collection('label').get()//获取label表数据// await 意思是等一下,等着db.collection('label').get()这个函数执行完毕,得到值后再赋值给label//返回数据给客户端return {code:200,msg:'数据请求成功',data:label.data}
};

首页index.vue

<template><view class="content"><navbar></navbar><tab :list="tabList"></tab><!-- <view v-for="item in 100">{{item}}</view> --></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel()},methods: {getLabel() {uniCloud.callFunction({name: 'get_label',}).then((res) => {this.tabList = res.result.data})}}}
</script><style lang="scss"></style>

tab.vue

<template><view class="tab"><scroll-view class="tab-scroll" scroll-x><view class="tab-scroll_box"><view v-for="(item,index) in list" :key="index" class="tab-scroll_item">{{item.name}}</view></view></scroll-view><view class="tab-icons"><uni-icons type="gear" size="26" color="#666"></uni-icons></view></view>
</template><script>export default {props:{//接受一个list属性,类型是数组,默认值是空数组list: {type: Array,default:[]}},data() {return {};}}
</script><style lang="scss">.tab {display: flex;width: 100%;border-bottom: 1px #f5f5f5 solid;background-color: #fff;box-sizing: border-box; //盒内元素.tab-scroll_box {display: flex;flex-wrap: nowrap; //不换行align-items: center; //垂直居中box-sizing: border-box; //盒内元素height: 45px;.tab-scroll_item {flex-shrink: 0; //不挤压padding: 0 10px;color: #333;font-size: 14px;}}.tab-icons {position: relative;display: flex;justify-content: center; //水平居中align-items: center; //垂直居中width: 45px;&::after {// &::after指的是该元素后面的内容content: '';position: absolute;top: 12px;bottom: 12px;left: 0;width: 1px;background-color: #ddd;}}}
</style>

7.封装数据请求

api/index.js

//批量导出文件(自动导出)const requireApi = require.context(//参数:读取文件的路径,是否遍历文件的子目录,匹配文件的正则//api目录的相对路径'.',//是否查询子目录false,//查询文件的一个后缀,只匹配.js后缀/.js$/
)
let module = {}
requireApi.keys().forEach((key, index) => {//requireApi.keys() 匹配好的文件列表 [./index.js,./list.js,...]//forEach相当于mapif (key === './index.js') returnObject.assign(module, requireApi(key)) //对象合并
})
export default module

api/list.js

/* 存放所有接口请求的api */
import $http from '../http.js'
export const get_label = (data) => {return $http({url:'get_label',data})
}

http.js

/* 封装网络请求 */
export default function $http(options){const {url,data} = options //url接口名称,data传给接口的数据return new Promise((reslove, reject) => {uniCloud.callFunction({name: url,data}).then((res)=>{if(res.result.code===200){reslove(res.result)}else{reject(res.result)}}).catch((err)=>{reject(err)})})
}

main.js

import Vue from 'vue'
import App from './App'
import api from './common/api'
Vue.config.productionTip = false
Vue.prototype.$api = api //绑定到vue实例中,之后就可以直接通过this.$api调用(方便)
App.mpType = 'app'const app = new Vue({...App
})
app.$mount()

tabbar/index.vue

<template><view class="content"><navbar></navbar><tab :list="tabList"></tab><!-- <view v-for="item in 100">{{item}}</view> --></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel()//获取选项卡数据},methods: {getLabel() {this.$api.get_label({name:'get_label'}).then((res)=>{const {data} = resthis.tabList = dataconsole.log(res)})}}}
</script><style lang="scss"></style>

8.选项卡切换

tab.vue

<template><view class="tab"><scroll-view class="tab-scroll" scroll-x><view class="tab-scroll_box"><view v-for="(item,index) in list" :class="{active:activeIndex===index}" :key="index" class="tab-scroll_item" @click="clickTab(item,index)">{{item.name}}</view></view></scroll-view><view class="tab-icons"><uni-icons type="gear" size="26" color="#666"></uni-icons></view></view>
</template><script>export default {props: {//接受一个list属性,类型是数组,默认值是空数组list: {type: Array,default: []}},data() {return {activeIndex:0};},methods: {//点击tabclickTab(item, index) {this.activeIndex = indexthis.$emit('tab',{data:item,index})//调用父组件的方法,将当前tab的内容和下标传给父组件}}}
</script><style lang="scss">.tab {display: flex;width: 100%;border-bottom: 1px #f5f5f5 solid;background-color: #fff;box-sizing: border-box; //盒内元素.tab-scroll_box {display: flex;flex-wrap: nowrap; //不换行align-items: center; //垂直居中box-sizing: border-box; //盒内元素height: 45px;.tab-scroll_item {flex-shrink: 0; //不挤压padding: 0 10px;color: #333;font-size: 14px;&.active{color: $mk-base-color;}}}.tab-icons {position: relative;display: flex;justify-content: center; //水平居中align-items: center; //垂直居中width: 45px;&::after {// &::after指的是该元素后面的内容content: '';position: absolute;top: 12px;bottom: 12px;left: 0;width: 1px;background-color: #ddd;}}}
</style>

:class="{active:activeIndex===index}" 动态类的定义,当activeIndex等于index,该标签就会多一个active的类
tabbar/index.vue

<template><view class="content"><navbar></navbar><tab :list="tabList" @tab='tab'></tab><!-- <view v-for="item in 100">{{item}}</view> --></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel()//获取选项卡数据},methods: {//获取选项卡数据方法getLabel() {this.$api.get_label({name:'get_label'}).then((res)=>{const {data} = resthis.tabList = dataconsole.log(res)})},//tab切换时候触发的方法tab({data,index}){console.log(data,index)}}}
</script><style lang="scss"></style>

9.基础卡片实现

components/list-scroll.vue

<template><view class="scroll"><scroll-view scroll-y class="list-scroll"><view><!-- slot 插槽 --><slot></slot></view></scroll-view></view>
</template><script>export default {data() {return {};}}
</script><style lang="scss">.scroll {flex: 1;overflow: hidden; //溢出隐藏box-sizing: border-box; // 盒内元素.list-scroll {height: 100%;display: flex;flex-direction: column; //垂直排列}}
</style>

list-card.vue

<template><view><!-- 基础卡片 --><view class="listcard"><view class="listcard-image"><image src="../../static/logo.png" mode="aspectFill"></image></view><view class="listcard-content"><view class="listcard-content__title"><text>uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架</text></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">前端</view></view><view class="listcard-content__des-browse">120浏览</view></view></view></view></view>
</template><script>export default {data() {return {};}}
</script><style lang="scss">.listcard {display: flex;padding: 10px;margin: 10px;border-radius: 5px;box-shadow: 0 0 5px 1px rgba($color:#000000, $alpha:0.1);//5px模糊效果,1px扩散box-sizing: border-box;.listcard-image {flex-shrink: 0;//防止挤压,正常显示width: 60px;height: 60px;border-radius: 5px;overflow: hidden;image {//使图片全部正常显示width: 100%;height: 100%;}}.listcard-content {display: flex;flex-direction: column; //垂直排列justify-content: space-between;//垂直上下对齐padding-left: 10px;width: 100%;.listcard-content__title{font-size: 14px;color: #333;font-weight: 400;line-height: 1.2;text{overflow: hidden;//溢出隐藏text-overflow: ellipsis;//当文本溢出包含元素省略符号显示display: -webkit-box;// 将对象作为弹性伸缩盒子模型显示-webkit-line-clamp:2;//只显示两行-webkit-box-orient:vertical; // 从上到下垂直排列子元素}}.listcard-content__des{display: flex;justify-content: space-between;//左右两边对齐font-size: 12px;.listcard-content__des-label{display: flex;.listcard-content__des-label-item{padding: 0 5px;margin-right: 5px;border-radius: 15px;color: $mk-base-color;border: 1px $mk-base-color solid;}}.listcard-content__des-browse{color: #999;line-height: 1.5;}}}}
</style>

tabbar/index.vue

<template><view class="home"><navbar></navbar><tab :list="tabList" @tab='tab'></tab><list-scroll><list-card v-for="item in 5"></list-card></list-scroll></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel()//获取选项卡数据},methods: {//获取选项卡数据方法getLabel() {this.$api.get_label({name:'get_label'}).then((res)=>{const {data} = resthis.tabList = dataconsole.log(res)})},//tab切换时候触发的方法tab({data,index}){console.log(data,index)}}}
</script><style lang="scss">page{height: 100%;display: flex;}.home{display: flex;flex-direction: column;//垂直排列flex:1;//等价于flex-grow: 1;flex-shrink: 1;flex-basis: 0%;overflow: hidden;//溢出隐藏// border: 1px red solid;}
</style>

10.更多卡片视图实现

components/list-card.vue

<template><view><!-- 基础卡片 --><view v-if="mode==='base'" class="listcard"><view class="listcard-image"><image src="../../static/logo.png" mode="aspectFill"></image></view><view class="listcard-content"><view class="listcard-content__title"><text>uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架uni-app开发框架</text></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">前端</view></view><view class="listcard-content__des-browse">120浏览</view></view></view></view><!-- 多图模式卡片 --><view v-if="mode==='column'" class="listcard mode-column"><view class="listcard-content"><view class="listcard-content__title"><text>uni-app开发框架</text></view><view class="listcard-image"><view v-for="item in 3" :key="item" class="listcard-image__item"><image src="../../static/logo.png" mode="aspectFill"></image></view></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">前端</view></view><view class="listcard-content__des-browse">120浏览</view></view></view></view><!-- 大图模式卡片 --><view v-if="mode==='image'" class="listcard mode-image"><view class="listcard-image"><image src="../../static/logo.png" mode="aspectFill"></image></view><view class="listcard-content"><view class="listcard-content__title"><text>uni-app开发框架</text></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">前端</view></view><view class="listcard-content__des-browse">120浏览</view></view></view></view></view>
</template><script>export default {props:{//通过接受mode来判断,显示什么模式的卡片,mode是String类型的字符串,默认值是base//base基础卡片,column多图卡片,image,大图卡片mode:{type:String,default:'base'}},data() {return {};}}
</script><style lang="scss">.listcard {display: flex;padding: 10px;margin: 10px;border-radius: 5px;box-shadow: 0 0 5px 1px rgba($color:#000000, $alpha:0.1);//5px模糊效果,1px扩散box-sizing: border-box;.listcard-image {flex-shrink: 0; //防止挤压,正常显示width: 60px;height: 60px;border-radius: 5px;overflow: hidden;image {//使图片全部正常显示width: 100%;height: 100%;}}.listcard-content {display: flex;flex-direction: column; //垂直排列justify-content: space-between; //垂直上下对齐padding-left: 10px;width: 100%;.listcard-content__title {font-size: 14px;color: #333;font-weight: 400;line-height: 1.2;text {overflow: hidden; //溢出隐藏text-overflow: ellipsis; //当文本溢出包含元素省略符号显示display: -webkit-box; // 将对象作为弹性伸缩盒子模型显示-webkit-line-clamp: 2; //只显示两行-webkit-box-orient: vertical; // 从上到下垂直排列子元素}}.listcard-content__des {display: flex;justify-content: space-between; //左右两边对齐font-size: 12px;.listcard-content__des-label {display: flex;.listcard-content__des-label-item {padding: 0 5px;margin-right: 5px;border-radius: 15px;color: $mk-base-color;border: 1px $mk-base-color solid;}}.listcard-content__des-browse {color: #999;line-height: 1.5;}}}&.mode-column{.listcard-content{width: 100%;padding-left: 0px;}.listcard-image{display: flex;margin-top: 10px;width: 100%;height: 70px;.listcard-image__item{margin-left: 10px;width: 100%;border-radius: 5px;overflow: hidden;&:first-child{margin-left: 0px;}image{width: 100%;height: 100%;}}}.listcard-content__des{margin-top: 10px;}}&.mode-image{flex-direction: column;//垂直排列.listcard-image{width: 100%;height: 100px;}.listcard-content{padding-left: 0;margin-top: 10px;.listcard-content__des{display: flex;align-items: center;//垂直居中margin-top: 10px;}}}}
</style>

tabbar/index.vue

<template><view class="home"><navbar></navbar><tab :list="tabList" @tab='tab'></tab><list-scroll><list-card mode="base"></list-card><list-card mode="column"></list-card><list-card mode="image"></list-card></list-scroll></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel()//获取选项卡数据},methods: {//获取选项卡数据方法getLabel() {this.$api.get_label({name:'get_label'}).then((res)=>{const {data} = resthis.tabList = dataconsole.log(res)})},//tab切换时候触发的方法tab({data,index}){console.log(data,index)}}}
</script><style lang="scss">page{height: 100%;display: flex;}.home{display: flex;flex-direction: column;//垂直排列flex:1;//等价于flex-grow: 1;flex-shrink: 1;flex-basis: 0%;overflow: hidden;//溢出隐藏// border: 1px red solid;}
</style>

11.实现内容切换

tabbar/index.vue

<template><view class="home"><navbar></navbar><tab :list="tabList" @tab='tab'></tab><view class="home-list"><list :list="tabList"></list></view></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: []}},onLoad() {this.getLabel() //获取选项卡数据},methods: {//获取选项卡数据方法getLabel() {this.$api.get_label({name: 'get_label'}).then((res) => {const {data} = resthis.tabList = dataconsole.log(res)})},//tab切换时候触发的方法tab({data,index}) {console.log(data, index)}}}
</script><style lang="scss">page {height: 100%;display: flex;}.home {display: flex;flex-direction: column; //垂直排列flex: 1; //等价于flex-grow: 1;flex-shrink: 1;flex-basis: 0%;overflow: hidden; //溢出隐藏.home-list{flex: 1;//撑开box-sizing: border-box;//盒内显示}}
</style>

components/list.vue

<template><swiper class="home-swiper"><swiper-item v-for="(item,index) in list" :key="index" class="swiper-item"><listItem></listItem></swiper-item></swiper>
</template><script>import listItem from './listItem.vue' //引入list-item组件export default {//引入组件必须要注册,习惯components: {listItem},props: {//list是父组件传来的选项卡的数据list: {type: Array,default: []}},data() {return {};},}
</script><style lang="scss">.home-swiper {height: 100%;.swiper-item {height: 100%;overflow: hidden;.list-scroll {height: 100%;}}}
</style>

components/listItem.vue

<template><list-scroll class="list-scroll"><list-card mode="base"></list-card><list-card mode="base"></list-card><list-card mode="base"></list-card><list-card mode="base"></list-card><list-card mode="base"></list-card><list-card mode="base"></list-card></list-scroll>
</template><script>
</script><style lang="scss">.list-scroll{height: 100%;}
</style>

12.选项卡与内容联动

components/list.vue

<template><swiper class="home-swiper" :current="activeIndex" @change="change"><swiper-item v-for="(item,index) in list" :key="index" class="swiper-item"><listItem></listItem></swiper-item></swiper>
</template><script>import listItem from './listItem.vue' //引入list-item组件export default {//引入组件必须要注册,习惯components: {listItem},props: {//list是父组件传来的选项卡的数据list: {type: Array,default: []},//activeIndex是父组件传来的当前tab得位置activeIndex:{type: Number,default: 0}},data() {return {};},methods: {change(e) {const {current} = e.detail //e.detail.current是当前swiper的第几项this.$emit('change', current) //调用父组件传来的change方法,把current传给父组件}}}
</script><style lang="scss">.home-swiper {height: 100%;.swiper-item {height: 100%;overflow: hidden;.list-scroll {height: 100%;}}}
</style>

components/tab.vue

<template><view class="tab"><scroll-view class="tab-scroll" scroll-x><view class="tab-scroll_box"><view v-for="(item,index) in list" :class="{active:activeIndex===index}" :key="index" class="tab-scroll_item"@click="clickTab(item,index)">{{item.name}}</view></view></scroll-view><view class="tab-icons"><uni-icons type="gear" size="26" color="#666"></uni-icons></view></view>
</template><script>export default {props: {//接收父组件传来的一个list,类型是数组,默认值是空数组list: {type: Array,default: []},//接收父组件传来的一个tabIndex,类型是number,默认值是0tabIndex:{type:Number,default: 0,}},//watch事件,监听data和props里面值的变化watch:{//监听tabIndex值的变化,一旦改变,立即触发//方法名字与值得名字一样,接受两个参数,改变后和改变前的值tabIndex(newVal,oldVal){this.activeIndex=newValconsole.log('newVal==>',newVal,'oldVal==>',oldVal)}},data() {return {activeIndex: 0};},methods: {//点击tabclickTab(item, index) {this.activeIndex = indexthis.$emit('tab', {data: item,index}) //调用父组件的方法,将当前tab的内容和下标传给父组件}}}
</script><style lang="scss">.tab {display: flex;width: 100%;border-bottom: 1px #f5f5f5 solid;background-color: #fff;box-sizing: border-box; //盒内元素.tab-scroll_box {display: flex;flex-wrap: nowrap; //不换行align-items: center; //垂直居中box-sizing: border-box; //盒内元素height: 45px;.tab-scroll_item {flex-shrink: 0; //不挤压padding: 0 10px;color: #333;font-size: 14px;&.active {color: $mk-base-color;}}}.tab-icons {position: relative;display: flex;justify-content: center; //水平居中align-items: center; //垂直居中width: 45px;&::after {// &::after指的是该元素后面的内容content: '';position: absolute;top: 12px;bottom: 12px;left: 0;width: 1px;background-color: #ddd;}}}
</style>

tabbar/index.vue

<template><view class="home"><navbar></navbar><tab :list="tabList" :tabIndex="tabIndex" @tab='tab'></tab><view class="home-list"><list :list="tabList" @change="change" :activeIndex="activeIndex"></list></view></view>
</template><script>//uni-app有个easyCom模式,只要组件的存放位置是"@/components/组件名/组件名.vue",就可以无需引用,直接使用//而且还是局部引用// import navbar from "@/components/navbar/navbar.vue"export default {data() {return {tabList: [],//tab列表tabIndex:0,//当前swiper的位置activeIndex:0,//当前tab的位置}},onLoad() {this.getLabel() //获取选项卡数据},methods: {//获取选项卡数据方法getLabel() {this.$api.get_label({name: 'get_label'}).then((res) => {const {data} = resthis.tabList = dataconsole.log(res)})},//tab切换时候触发的方法tab({data,index}) {this.activeIndex=index //将切换后得位置赋值给activeIndex,让swiper去接收console.log(data, index)},//切换swiper触发的方法,获得当前swiper是第几项,再传给tab,实现tab和swiper联动change(current){this.tabIndex = currentconsole.log('当前swiper的位置',current)}}}
</script><style lang="scss">page {height: 100%;display: flex;}.home {display: flex;flex-direction: column; //垂直排列flex: 1; //等价于flex-grow: 1;flex-shrink: 1;flex-basis: 0%;overflow: hidden; //溢出隐藏.home-list{flex: 1;//撑开box-sizing: border-box;//盒内显示}}
</style>

13.内容卡片数据初始化

cloudfunctions-aliyun/get_list.js

'use strict';
const db = uniCloud.database()//创建数据库的引用
exports.main = async (event, context) => {let list = await db.collection('article').field({content:false})//field()指定返回字段,不要content;false表示不返回,true表示只返回.get()//获取article表数据//返回数据给客户端return {code:200,msg:'数据请求成功',data:list.data}
};

common/api/list.js

/* 存放所有接口请求的api */
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})
}

components/list/list.vue

<template><swiper class="home-swiper" :current="activeIndex" @change="change"><swiper-item v-for="(item,index) in list" :key="index" class="swiper-item"><listItem :articleList="articleList"></listItem></swiper-item></swiper>
</template><script>import listItem from './listItem.vue' //引入list-item组件export default {//引入组件必须要注册,习惯components: {listItem},props: {//list是父组件传来的选项卡的数据list: {type: Array,default: []},//activeIndex是父组件传来的当前tab得位置activeIndex:{type: Number,default: 0}},data() {return {articleList:[]//文章列表,需要传给子组件};},created() {this.getList()//调用get_list接口},methods: {change(e) {const {current} = e.detail //e.detail.current是当前swiper的第几项this.$emit('change', current) //调用父组件传来的change方法,把current传给父组件},//调用get_list接口的方法getList(){this.$api.get_list().then(res=>{const {data} = resthis.articleList=dataconsole.log(res)})}}}
</script><style lang="scss">.home-swiper {height: 100%;.swiper-item {height: 100%;overflow: hidden;.list-scroll {height: 100%;}}}
</style>

components/list/listItem.vue

<template><list-scroll class="list-scroll"><list-card mode="base" v-for="item in articleList" :key="item._id" :item="item"></list-card></list-scroll>
</template><script>export default {props: {//articleList是父组件传来的文章列表articleList:{type:Array,default:[]}}}
</script><style lang="scss">.list-scroll {height: 100%;}
</style>

components/list-card.vue

<template><view><!-- 基础卡片 --><view v-if="item.mode==='base'" class="listcard"><view class="listcard-image"><image :src="item.cover[0]" mode="aspectFill"></image></view><view class="listcard-content"><view class="listcard-content__title"><text>{{item.title}}</text></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">{{item.classify}}</view></view><view class="listcard-content__des-browse">{{item.browse_count}}浏览</view></view></view></view><!-- 多图模式卡片 --><view v-if="item.mode==='column'" class="listcard mode-column"><view class="listcard-content"><view class="listcard-content__title"><text>{{item.title}}</text></view><view class="listcard-image"><view v-if="index < 3" v-for="(item,index) in item.cover" :key="index" class="listcard-image__item"><image :src="item" mode="aspectFill"></image></view></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">{{item.classify}}</view></view><view class="listcard-content__des-browse">{{item.browse_count}}浏览</view></view></view></view><!-- 大图模式卡片 --><view v-if="item.mode==='image'" class="listcard mode-image"><view class="listcard-image"><image :src="item.cover[0]" mode="aspectFill"></image></view><view class="listcard-content"><view class="listcard-content__title"><text>{{item.title}}</text></view><view class="listcard-content__des"><view class="listcard-content__des-label"><view class="listcard-content__des-label-item">{{item.classify}}</view></view><view class="listcard-content__des-browse">{{item.browse_count}}浏览</view></view></view></view></view>
</template><script>export default {props:{//通过接受mode来判断,显示什么模式的卡片,mode是String类型的字符串,默认值是base//base基础卡片,column多图卡片,image,大图卡片// mode:{//   type:String,//  default:'base'// },//item是父组件传来的文章列表里面的信息item:{type:Object,default:{},}},data() {return {};}}
</script><style lang="scss">.listcard {display: flex;padding: 10px;margin: 10px;border-radius: 5px;box-shadow: 0 0 5px 1px rgba($color:#000000, $alpha:0.1);//5px模糊效果,1px扩散box-sizing: border-box;.listcard-image {flex-shrink: 0; //防止挤压,正常显示width: 60px;height: 60px;border-radius: 5px;overflow: hidden;image {//使图片全部正常显示width: 100%;height: 100%;}}.listcard-content {display: flex;flex-direction: column; //垂直排列justify-content: space-between; //垂直上下对齐padding-left: 10px;width: 100%;.listcard-content__title {font-size: 14px;color: #333;font-weight: 400;line-height: 1.2;text {overflow: hidden; //溢出隐藏text-overflow: ellipsis; //当文本溢出包含元素省略符号显示display: -webkit-box; // 将对象作为弹性伸缩盒子模型显示-webkit-line-clamp: 2; //只显示两行-webkit-box-orient: vertical; // 从上到下垂直排列子元素}}.listcard-content__des {display: flex;justify-content: space-between; //左右两边对齐font-size: 12px;.listcard-content__des-label {display: flex;.listcard-content__des-label-item {padding: 0 5px;margin-right: 5px;border-radius: 15px;color: $mk-base-color;border: 1px $mk-base-color solid;}}.listcard-content__des-browse {color: #999;line-height: 1.5;}}}&.mode-column{.listcard-content{width: 100%;padding-left: 0px;}.listcard-image{display: flex;margin-top: 10px;width: 100%;height: 70px;.listcard-image__item{margin-left: 10px;width: 100%;border-radius: 5px;overflow: hidden;&:first-child{margin-left: 0px;}image{width: 100%;height: 100%;}}}.listcard-content__des{margin-top: 10px;}}&.mode-image{flex-direction: column;//垂直排列.listcard-image{width: 100%;height: 100px;}.listcard-content{padding-left: 0;margin-top: 10px;.listcard-content__des{display: flex;align-items: center;//垂直居中margin-top: 10px;}}}}
</style>

uni-app 快速入门 从零开始实现新闻资讯类跨端应用(更新中)相关推荐

  1. 【笔记-uni app】《uni-app 快速入门 从零开始实现新闻资讯类跨端应用》

    uni-app 快速入门 从零开始实现新闻资讯类跨端应用 第12章 项目发行与打包 12-03 App端发行打包 一.发行,原生app-云打包 把包提交给dcloud的服务器,通过dcloud打包完后 ...

  2. uni-app开发从入门到新闻资讯类跨端应用项目

    1.开发流程与规划.mp4 2.应用效果展示与分析.mp4 3.微信小程序入门1.mp4 4.微信小程序入门2.mp4 5.uni-app 核心知识点概览.mp4 6.搭建uni-app开发环境.mp ...

  3. 移动互联网时代,怎样打造一款新闻资讯类产品?

    公众号后台回复"图书",了解更多号主新书内容 作者:啊庄 来源:晓庄同学产品 新闻资讯获取一直是人们必不可少的一项重要生活活动. 从最开始的纸媒体时代,到各大门户并立的网站时代,再 ...

  4. ios appstore 审核 Guideline 5.2.2 - Legal ios新闻资讯类APP5.2.2被拒

    新闻资讯类APP5.2.2被拒. 新闻资讯类APP5.2.2被拒,说是上传什么资质 Guideline 5.2.2 - Legal Your app contains content or featu ...

  5. 新闻资讯类网站的PC端前台模板分享

    PC端新闻资讯模板 背景 效果图 技术方案选型过程 方案敲定 结语 背景 我同学公司需要开发一个pc端的新闻咨询网址,后端和app端都有了,具体一点就是已经有了后台监控和发布系统,并且实现了手机app ...

  6. 移动端点击保存图片_财经理财新闻资讯类网站织梦模板(带手机端)

    模板名称:财经理财新闻资讯类网站织梦模板(带手机端)+PC+移动端+利于SEO优化模板介绍: 织梦最新内核开发的模板,该模板属于财经.理财.投资.新闻.资讯料类企业使用, 自带最新的手机移动端,同一个 ...

  7. (PC+WAP)织梦模板财经新闻资讯类网站

    模板介绍: 织梦内核开发的模板,该模板属于社会财经新闻资讯类企业使用, 自带最新的手机移动端,同一个后台,数据即时同步,简单适用! 原创设计.手工书写DIV+CSS, 完美兼容IE7+.Firefox ...

  8. JDBC 快速入门JDBC 抽取JDBC工具类:JDBCUtils

    文章目录 JDBC 快速入门JDBC 抽取JDBC工具类:JDBCUtils JDBC 概念:java database Connectivity java 数据库连接,java语言操作数据库 JDB ...

  9. 使用Cloud DB构建APP 快速入门 - Android篇

    概述 此示例应用演示了如何快速的使用Cloud DB构建简单的图书管理服务.通过快速入门和示例应用,您将会了解到如下信息: 如何使用Cloud DB进行应用开发. 应用数据如何写入到Cloud DB. ...

  10. 推荐系统应用---新闻资讯类

    很久很久以前,大家获取信息的渠道可能就是读书,听广播,看报纸,看电视等等,可以获得的信息也非常少.然而当今的社会,我们整天都会发愁从无数的巨大的永远都不可能看完的信息中很轻松地找到需要的信息,也就是说 ...

最新文章

  1. OneFlow 并行特色
  2. go语言和java并发_彻底搞清楚Java并发 (一) 基础
  3. 计算机怎样选定硬盘,如何给电脑分盘
  4. JS与OC中的方法相互调用
  5. Struts2中OGNL,valueStack,stackContext的学习
  6. linux服务chm,linux系统服务 chm
  7. pytorch —— 模型容器与AlexNet构建
  8. 最近录制了一些视频,搭建和测试了一下视频平台
  9. MSN Messenger协议
  10. pe系统如何读取手机_五分钟教会你pe系统制作
  11. 一个二本本科生如何才能进入腾讯,阿里,百度这些大厂?
  12. php下载Excel背景颜色设置,phpExcel生成的Excel背景填充色变黑
  13. [YOLOv7]基于YOLOv7的反光衣检测系统(源码&部署教程&数据集)
  14. buzz fizz 翻译_【Oxford-2】The Fizz-Buzz
  15. NIVIDIA 硬解码学习2
  16. [个人笔记] ssh-keygen和openssl工具的使用
  17. 【泛函分析】巴拿赫空间
  18. 一款小程序软件开发报价包含哪些费用呢?
  19. 聚类分析(cluster analysis)
  20. 访问者模式(JAVA)

热门文章

  1. 韦东山freeRTOS系列教程之【第一章】FreeRTOS概述与体验
  2. 冷高轮时间王思聪吃热狗电脑屏幕保护下载
  3. 软件项目总结报告范文
  4. 【WORD】01 多级标题自动编号
  5. 黑莓手机用desktop manager安装了一些软件后重启出现erro523无法进入桌面
  6. 2020.07.01-07.15学习小结
  7. UART、RS232、RS485协议
  8. android contacts 源码分析,MTK Contacts代码分析
  9. ISL22326WFR16Z-TK 2 电路 I²C 接口 双数字电位器
  10. html表格自动变色,让考勤表实现自动变色