uni-app小程序开发基础知识2
- 互联网
- 2025-08-25 09:30:01

目标:
构建一个文章发表平台。
我们先来写一个静态框架。
以下是
首页初代码+文章列表页代码: <template> <view class="content"> <!-- 轮播图 --> <swiper class="swiper-container" autoplay="true" interval="3000" circular="true"> <!-- 每个item里循环 --> <swiper-item > <!-- 这是自己的轮播内容 img --> <image src="" class="swiper-image"></image> </swiper-item> </swiper> <!-- 中间icon图标 --> <view class="icon-container"> <!-- 每个icon-row里循环 --> <view class="icon-row" > <view class="icon-item" > <!-- icon图标 --> <image src="" class="icon-image"></image> <!-- 底部文字 --> <text class="icon-text"></text> </view> </view> </view> <!-- 热门文章 --> <view class="article"> <view style="display: flex;justify-content: space-between;margin: 0 50rpx;"> <text style="font-weight: bold;">热门文章</text> <text style="font-size: 12px;color:#ccc">查看全部></text> </view> <!-- 文章内容 --> <view class="article-img" > <!-- 文章图片 --> <img src="" alt="" class="img"/> <!-- 文章标题 --> <view class="hot-word"> </view> </view> </view> </view> </template> <script> export default { data() { return { // 轮播图内容 swiperItems: [ { id:1, url:" img-blog.csdnimg /2021051521244130.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81MzQ0Nzc3Ng==,size_16,color_FFFFFF,t_70" }, { id:2, url:" ts1 .mm.bing.net/th/id/R-C.9881613a29f26488b40938427aa585e4?rik=fim4XvDejjHE%2fQ&riu=http%3a%2f%2fn.sinaimg %2fsinakd20220516ac%2f797%2fw2048h1149%2f20220516%2fb0aa-5aca29fe2dfa69c385118bbc74d039de.jpg&ehk=tzq%2bJP6uMipI0aIHY3bMSVO7lS7ZQM6TKMlwZ5CFP4s%3d&risl=&pid=ImgRaw&r=0" }, { id:3, url:" ts1 .mm.bing.net/th/id/R-C.1ba7730f131b89278f37af053abd305c?rik=4ZdRDx%2bBrDRsgA&riu=http%3a%2f%2fpic.bizhi360 %2fbbpic%2f90%2f10190.jpg&ehk=BEPnflW%2bZdQGggy286CG%2bpJrPop%2b92UEVILUX%2bnbV18%3d&risl=&pid=ImgRaw&r=0" } ], // 字体图标内容 iconRows: [ { id:1, url: '/static/icon1.png', text: '添加文章', path:'/pages/article/article' }, { id:2, url: '/static/icon.png', text: '代码帮助' }, { id:3, url: '/static/call.png', text: '联系我们' }, { id:4, url: '/static/liuyan.png', text: '我要留言' } ], // 热门文章内容 hotWord:{ text:"标题", img:"http://contentcms-bj.cdn.bcebos /cmspic/96bfd5a4a25940d636812bae6737697d.jpeg?x-bce-process=image/crop,x_0,y_0,w_1597,h_877" }, hot_list:[] } }, onLoad() { }, methods: { } } </script> <style> .content { display: flex; flex-direction: column; align-items: center; justify-content: center; } .swiper-container { width: 90%; /* 针对于移动端小程序专门用的单位 */ height: 300rpx; margin: 0 auto; /* 根据需要调整高度 */ } .swiper-image { width: 100%; height: 100%; object-fit: cover; } .icon-container { width: 100%; margin: 50rpx 0; display: flex; align-items: center; } .icon-row { flex: 1; margin-bottom: 20rpx; } .icon-item { display: flex; flex-direction: column; align-items: center; } .icon-image { width: 80rpx; height: 80rpx; } .icon-text { margin-top: 10rpx; font-size: 24rpx; color: #8f8f94; } .text-area { display: flex; justify-content: center; } .title { font-size: 36rpx; color: #8f8f94; } .article { width: 100%; } .article-img{ width: 100%; } .img{ margin:50rpx 50rpx 10rpx 50rpx; width: 650rpx; height: 400rpx; } .hot-word{ margin-left: 50rpx; } </style>文章列表页初代码,静态图片自己加入。:
<template> <view class="content"> <!-- 每一个文章卡片,在这里循环 --> <view class="index-card" > <!-- 封面 --> <image class="index-img" src="" mode=""></image> <view class="ellipsis"> <!-- 文章标题 --> <text> </text> </view> <!-- 文章时间 --> <view class="index-small"> </view> </view> </view> </template> <script> export default { data() { return { listData: [{ title: "暴走萝莉·金克丝,是MOBA竞技网游《英雄联盟》中的英雄角色,定位为射手。", img: "/static/img1.jpg", id: 1, content: '是英雄联盟历史上第一个拥有宣传视频的英雄。\n金克丝在团战初期就能输出大量伤害。金克丝的攻击距离以及伤害使得她能够与远距离poke型阵容融合。\n 神经狂躁、冲动任性、劣迹斑斑……金克丝出身自祖安,生来就爱不计后果地大搞破坏。她就是一座人形自走军火库,所经之处必定会留下夺目的火光和震耳的爆炸。金克丝最讨厌无聊,所以不管她去到哪里,混乱和骚动就会如期而至,这就是她留下的“到此一游”。' }, { title: "逆羽·霞,是MOBA竞技网游《英雄联盟》中的一位英雄角色,是一个极具输出与收割能力的射手英雄", img: "/static/img2.jpg", id: 2, content: '她能凭借着具有穿刺效果的羽毛,同时对敌方前排与后排造成大量伤害。霞最擅长的就是使用羽毛,合理的运用羽毛的停留,能让她收获出乎意料的效果。 \n 身为瓦斯塔亚的志士,霞要掀起一场革命来拯救她的族群。她身法敏捷又慧心独具,凭借锋芒逼人的羽刃,扫除任何异己。霞与她的灵魂伴侣洛并肩作战,共同守护他们日渐衰落的部族,同时韬光养晦,希望终有一天能率领全族重夺昔日荣光.' }, { title: "封魔剑魂·永恩,是MOBA竞技网游《英雄联盟》中第150位登场的英雄角色,英雄定位为战士、刺客", img: "/static/img3.jpg", id: 3, content: '生前的永恩,恪守着忠义师道。从很小的时候,他就开始为心爱的家庭扮演保护者的角色,不得不说这很大程度上是因为幼年丧父对他的影响。与他形成鲜明对比的,是他同母异父的弟弟——亚索。与亚索的冲动、鲁莽相反,永恩充满了耐心和自律。\n 生前,他是永恩,是亚索同母异父的哥哥,是故乡剑术道场的知名弟子。但当他死在弟弟手下以后,却发现自己被精神领域中的恶毒灵体所侵扰,不得不用它自己的刀剑将它弑杀。如今,被诅咒的永恩戴上了它的恶魔面具,开始了不懈的追猎,他要猎尽所有同种的恶魔,从而查清自己究竟成为了什么。' }, { title: "刀锋舞者·艾瑞莉娅,是MOBA竞技网游《英雄联盟》中的英雄角色,定位为战士。", img: "/static/img4.jpg", id: 4, content: '时而似平静的海面,时而似汹涌的风暴。艾瑞莉娅是艾欧尼亚勇猛的捍卫者,她接受过祖辈传承的舞蹈训练,并将舞艺化为战斗的技法。伴随着她优雅的动作,锋利的刀刃在空中组成夺命的阵列翩翩起舞,这位刀锋舞者将斩除任何想要扮演征服者的蠢货。\n 诺克萨斯对艾欧尼亚的占领催生了许多英雄,但没有谁像纳沃利的艾瑞莉娅一般令人意外。她将家乡的古老舞艺化为战技,以精心修习的优雅身姿操控着致命的刀丛。在她证明了自己的战斗实力后,被众人推举为反抗军的领袖和首脑,为了守卫家园而奋斗至今。' }, { title: "探险家·伊泽瑞尔,是MOBA竞技网游《英雄联盟》中的一名英雄角色,定位为射手、法师", img: "/static/img5.jpg", id: 5, content: '伊泽瑞尔是一名非常灵活飘逸的英雄,双加成的技能使他不但可以走AD路线,也能作为法师走AP路线。\n 神采奕奕的冒险家伊泽瑞尔拥有自己不知道的魔法天赋,他搜刮失落已久的古墓,触碰古老的诅咒,还举重若轻地挑战常人不可能完成的极限。他的勇气和壮举无边无际,总是喜欢随机应变地解决任何情况,一定程度上依赖他的小聪明,但更主要是依赖他神秘的恕瑞玛护手,在他的操控下释放出破坏性的奥术爆弹。有一件事可以肯定——只要伊泽瑞尔出现,那么麻烦一定接踵而至。或是还没走远。范围大概是随时随地。' } ] } }, onLoad() { }, methods: { } } </script> <style> .content { width: 90%; margin: 0 auto; } .index-card { width: 100%; height: 500rpx; margin-bottom: 10rpx; } .index-img { width: 100%; height: 400rpx; border-radius: 15rpx 15rpx 0rpx 0rpx; } .ellipsis { padding: 0 10rpx; white-space: nowrap; /*超出的空白区域不换行*/ overflow: hidden; /*超出隐藏*/ text-overflow: ellipsis; /*文本超出显示省略号*/ margin-bottom: 5rpx; } .index-small { text-align: right; font-size: 14px; color: #cfccc9; } </style>首先是我们的
轮播图:相关代码我们可以从官网的swipe中找到案例:
我们的每一个相片都是一个swipe-item。
我们所有的相片地址都写在了export default里面了,所以我们接下来使用v-for来调用我们数组里面的元素。
接下来是我们下面的
功能图标:是我们的数组里嵌套对象,我们接着用v-for调用元素。
然后是
热门文章:因为我们先写的是假数据(死数据),我们渲染的话是用我们渲染对象的方式
假数据:就是提前写好的,一般于我们的用户没有交互的数据内容。
我们接下来给我们的查看全部设置点击事件:
<text style="font-size: 12px;color:#ccc" @click="toText">查看全部></text>
toText(){ uni.navigateTo({ url: '/pages/text/text', }); }然后利用v-for调死数据就可以完成我们的文章列表页的渲染(时间函数暂时未写):
动态数据
与后端的交互模式,一般是我们向后端发送请求,然后后端给我们返还相应的指令,我们再检查指令是否是我们想要的,如果是我们就使用。
我们的网络请求如下,我们使用的是Axios,其是Ajax的二次开发。
首先需要
安装的俩个库:pip install flask
pip install flask_cors
request.js和api.js源码首先我们的Ajax请求封装在了,request.js里面,代码如下:
// const baseUrl = 'http://127.0.0.1:5005' /* 根域名 */ // const baseUrl = 'http://192.168.1.167:5005' // 动态配置根域名 main.js const baseUrl = uni.getStorageSync('rootDomain5000') // const baseUrl = uni.getStorageSync('rootDomain5005') // const baseUrl = uni.getStorageSync('rootDomain') const request = (url = '', options = {}, contentType = 'application/json') => { return new Promise((resolve, reject) => { uni.showLoading({ title: '加载中', mask: true, }) // let baseUrl = url.includes('/login') ? rootDomain5005 : rootDomain5000 // console.log(rootDomain5005,'111') uni .request({ method: options.method, url: baseUrl + url, data: options.data, header: { 'Content-Type': contentType, Authorization: uni.getStorageSync('token'), }, dataType: 'json', }) .then((response) => { uni.hideLoading() let { statusCode, data, errMsg } = response if (statusCode === 200) { resolve(data) } else { uni.showToast({ title: errMsg, icon: 'none', }) reject(errMsg) } }) .catch((error) => { reject(error) }) }) } const get = (url, data) => { return request(url, { method: 'GET', data: data, }) } const post = (url, data) => { return request(url, { method: 'POST', data: data, }) } const postQuery = (url, data) => { return request( url, { method: 'POST', data: data, }, 'application/x- -form-urlencoded' ) } const put = (url, data) => { return request(url, { method: 'PUT', data: data, }) } module.exports = { get, post, postQuery, put, }然后api.js里面装着我们的接口。
代码如下:
const requests = require('@/utils/request.js') // 登录接口 export const loginGet = (param) => { return requests.get('/loginxcx', param) } // 首页轮播图 export const home_switch = () =>{ return requests.get('/switch',) } // 文章列表 export const listShow = (param) => { return requests.get('/article_list', param) } // 获取文章详情 export const article_details = (id) => { return requests.get(`/article_details?id=${id}`) } // 添加文章 export const add_article = (data) => { return requests.post(`/add_article`,data) }我们所有的Ajax请求全部写在我们的request.js里面,所以在接口文件里面,我们仅需要去调用request里面的Ajax请求就可以了。
小知识:如果另一个文件需要调用该文件,该文件需要导出,另一个文件需要导入。
然后我们来介绍
api的结构:request先不用管,因为大多数小程序,该后端代码依旧适用。
const是定义变量的关键词。
箭头函数导出的固定形式:
export const 函数名 = (形参)=> {
return requests.get(导出的文件地址,形参)
注意:我们的请求方式,参数等都是需要严格和后端代码相对于,否则会报错。
在app.py中我们可以看到我们的后端代码:
现在我们来启动一下后端代码:直接运行app.py,然后它就在后台运行了。
1,用后端代码运行轮播图。所以,我们现在index里面导入该文件
@/表示在根目录,及我文件的my_Blog,这样会方便写我们的相对路径。
先导入我们的函数:import { home_switch } from '@/pages/apis/api.js'
注意:该导入位置与我们的export default平行。
我们的下方去调用它:
getSwiper() { home_switch().then((res)=>{ console.log(res); }) } 注意我们的写法,home_switch().then()语法,是说当我们调用了前者函数,就执行我们then后面括号里面的内容,然后上面是我们then后面又写了一个箭头函数。注意,我们res如果只有一个参数,括号可以省略。
然后我们操作一下
非手动点击的函数调用。(进入则调用)我们的onLoad函数就是这样的功能:
一进入页面就执行onLoad函数,所以我们在onLoad函数里面调用 getSwiper(),就可以打印出来res里面的信息了。(调用要用this哦!!!)
调用后,我们的res内容是: 而我们需要其中的data里面的数据,这个data里面的内容也恰好与我们的轮播图数组里面的内容结构一致,那么我们就可以直接使用res.data去调用我们的后端活数据(来源于数据库),不去用死数据了。
2,后端代码导入文章列表页。与上述同样的方式,我们在文章列表页重新操作一次: 便可得到我们想要的结果。
我们可以等于(第9行)的原因是俩者结构完全相同。
time的实时化{{ item.time}}调用即可。
3,添加文章事件的点击事件。因为我们的图标是以循环的方式添加的,所以我们添加点击事件就是给每一个图标都添加点击事件。而且我们也不能跳转到同一个页面。
我的的图标结构如下: 所以我们的uni.navigateto中的url不能写死,需要往函数里面传参,就是path
函数的构建: -------->点击事件的创建。
然后就完成了点击事件。
那现在我们的任务就是给我们的添加文章页面添加功能,使其能够将数据传输到我们的后端接口,完成文章的添加。
先设置容器,保存我们的数据:
然后再去设置点击事件。
(1)表单控件的数据绑定:
指令:v-model 双向数据绑定:在输入框里面修改的内容在下方里面的title等里面的内容也会跟着进行改变。 写在input里面.
比如:
我们给title和content绑定了数据后: 再去考虑选择图片按钮。使其能够打开本地图片并且选择
(2)选择本地图片并上传 步骤一:打开相册,选择图片。关于相关代码,可以在官网寻找:
相关的属性:
我们对示例进行修改后,便可进行修改。其中res的内容是:
“0”:是我们的本地临时路径,只能在本地访问,浏览器无法访问。这也是我们上传的文件的本地路径。但我们需要把这个图片理由后端存到某个地方(一般是服务器),我们没有服务器,所以我们目前操作是把我们的本地图片传给后端文件,然后将该图片文件存储到我们的本地数据库里。
步骤二:上传图片我们仿照如下示例进行操作:
真实后端接口= 后端启动IP + 上传图片的接口名 。这里我们后端的接口名是upload_img
打印一下我们的success回调函数后,可以发现,我们的图片地址在后端发生了地址的拼接,这个拼接后的地址,就是我们将文件存入后,所在的后端服务器地址,我们需要获得他
打印回调函数里面的data后发现其是一个字符串(如果是对象,则是可折叠的)
我们需要对其进行进行转化,
语法JSON.parse(转换的对象)
转换成功:
我们需要的地址是其中的data。
所以我们写 let realpath = data.data 就可以了。
步骤三:图片回显注意:如果我们想要在函数里面使用this ,我们的函数必须是箭头函数,否则我们的下面无法访问this里面的对象。
整体函数如下。
handleImg(){ uni.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album'], //从相册选择 success: res =>{ const path = res.tempFilePaths[0] uni.uploadFile({ url: 'http://127.0.0.1:5000/upload_img', //仅为示例,非真实的接口地址 filePath: path, name: 'file', success: (uploadFileRes) => { // uploadFileRes.data是一个json字符串,我们需要进行转换 let data = JSON.parse(uploadFileRes.data) this.img=data.data let real_path = data.data // 将图片回显 this.img = real_path } }); } }); 步骤四:完成文章的添加在我们导入函数后调用时,出现了以下的报错。
原因是:我们的后端代码是带参数的,所以我们需要给我们的函数传参。
----》 文章添加成功
我们的参数也可以在外面用变量包括,然后参数写对象就行了。
现在我们设置点击添加文章后返回首页就可以了。
但是我们的首页在tab-bar里面,所以,我们需要更改跳转方式:
因为我们的页面值更改了一次,所以我们可以选择:
将其处理好之后,我们就完成了文章的添加。
uni-app小程序开发基础知识2由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“uni-app小程序开发基础知识2”