day-116-one-hundred-and-sixteen-20230720-小程序页面的初步完成
UI框架
vant-weapp安装
-
步骤一 通过 npm 安装
# 通过 npm 安装 npm i @vant/weapp -S --production -
步骤二 修改 app.json
- 将 app.json 中的 “style”: “v2” 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
-
步骤三 修改 project.config.json ,新版本可能不用了.
- 开发者工具创建的项目,miniprogramRoot 默认为 miniprogram,package.json 在其外部,npm 构建无法正常工作。
- 需要手动在 project.config.json 内添加如下配置,使开发者工具可以正确索引到 npm 依赖的位置。
{ ... "setting": { ... "packNpmManually": true, "packNpmRelationList": [ { "packageJsonPath": "./package.json", "miniprogramNpmDistDir": "./miniprogram/" } ] } }- 注意: 由于目前新版开发者工具创建的小程序目录文件结构问题,npm构建的文件目录为miniprogram_npm,并且开发工具会默认在当前目录下创建miniprogram_npm的文件名,所以新版本的miniprogramNpmDistDir配置为’./'即可
-
步骤四 构建 npm包
- 打开微信开发者工具,点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件。
-
在需要使用的时候,在
pages/xxx/xxxx.json中注册一个组件。-
如:van-rate。
-
pages/interview/interview.json
{ "usingComponents": { "van-rate": "@vant/weapp/rate/index" } } -
pages/interview/interview.wxml
<van-rate custom-class="rate" value="44444444" color="#ffd21e" void-icon="star" void-color="#eee" bind:change="onChange" /> -
pages/interview/interview.js
Page({ onChange(e){ console.log('onChange') }, })
-
-
使用vant-weapp组件-van-cell相关组件
-
在安装之后直接在json中注册;
-
pages/mime/mime.json
{ "usingComponents": { "van-cell": "@vant/weapp/cell/index", "van-cell-group": "@vant/weapp/cell-group/index" }, }
-
-
在注册好之后,直接在wxml调用就好了。
-
pages/mime/mime.wxml
<van-cell-group inset> <van-cell title="退出" bind:tap="logout" is-link /> <van-cell title="收藏" is-link link-type="navigateTo" url="/pages/collect-list/collect-list" /> </van-cell-group>
-
-
如果在组件上绑定了一些方法,那么就在js中定义好。
-
pages/mime/mime.js
Page({ logout(){ wx.clearStorageSync() wx.reLaunch({ url: '/pages/mime/mime', }) }, })
-
首页轮播图
-
pages/index/index.wxml
<!--pages/index/index.wxml--> <swiper indicator-dots autoplay interval="{{3000}}" > <swiper-item wx:for="{{bannerList}}" wx:for-item="banner" wx:key="index"> <image src="{{banner.url}}" mode="aspectFill"/> </swiper-item> </swiper> -
pages/index/index.js
import { get } from "../../utils/request"; //这个是请求列表数据的. // pages/index/index.js Page({ /** * 页面的初始数据 */ data: { bannerList: [], }, async getBannerList() { let { bannerList } = await get("/bannerList"); this.setData({ bannerList }); }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getBannerList();//获取banner列表 }, });
首页列表
-
pages/index/index.js
import { get } from "../../utils/request";//这个是请求列表数据的. // pages/index/index.js Page({ /** * 页面的初始数据 */ data: { articles: [], page: 1, total: 0, }, async getArticleList() { let { articles, total } = await get("/articleList", { data: { limit: 5, page:this.data.page, }, }); console.log(articles, total); this.setData({ articles, }); }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getArticleList(); }, }); -
pages/index/index.wxml
<view class="article" wx:for="{{articles}}" wx:for-item="article" wx:key="index"> <text class="title">{{article.title}}</text> <view class="author"> <text>{{article.author}} | {{article.createTime}}</text> </view> <image class="poster" src="{{article.poster}}" mode="aspectFill" /> <text class="content">{{article.content}}</text> <view class="other"> <text>点赞:{{article.support}} | 观看:{{article.look}}</text> </view> </view> -
pages/index/index.wxss
.article { border: 1px solid #ccc; border-radius: 30rpx; padding: 15rpx; margin-bottom: 10px; } .title { padding-top: 10px; font-size: 35rpx; font-weight: bold; line-height: 50rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; display: inline-block; } .author { font-size: 25rpx; line-height: 45rpx; } .content { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 20rpx 0; font-size: 30rpx; } .poster { width: 100%; height: 300rpx; } .other { color: #777; font-size: 25rpx; }
首页列表封装成组件
-
新建
/components/article/,在/components/article/中右键打开菜单,点击新建Component,输入article会自动生成对应的四个文件。- 小程序中,默认所有组件类型的文件,都放在
/components/中。
- 小程序中,默认所有组件类型的文件,都放在
-
写代码:
-
components\article\article.js
// components/article/article.js Component({ /** * 组件的属性列表 */ properties: { article: { type: Object, default: {}, }, }, /** * 组件的初始数据 */ data: {}, /** * 组件的方法列表 */ methods: {}, }); -
components\article\article.json
{ "component": true, "usingComponents": {} } -
components\article\article.wxml
<view class="article"> <text class="title">{{article.title}}</text> <view class="author"> <text>{{article.author}} | {{article.createTime}}</text> </view> <image class="poster" src="{{article.poster}}" mode="aspectFill" /> <text class="content">{{article.content}}</text> <view class="other"> <text>点赞:{{article.support}} | 观看:{{article.look}}</text> </view> </view> -
components\article\article.wxss
/* components/article/article.wxss */ .article { border: 1px solid #ccc; border-radius: 30rpx; padding: 15rpx; margin-bottom: 10px; } .title { padding-top: 10px; font-size: 35rpx; font-weight: bold; line-height: 50rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; display: inline-block; } .author { font-size: 25rpx; line-height: 45rpx; } .content { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; margin: 20rpx 0; font-size: 30rpx; } .poster { width: 100%; height: 300rpx; } .other { color: #777; font-size: 25rpx; }
-
-
在需要用的地方导入并使用
-
pages/index/index.js
import { get } from "../../utils/request"; //这个是请求列表数据的. // pages/index/index.js Page({ /** * 页面的初始数据 */ data: { articles: [], page: 1, total: 0, }, async getArticleList() { let { articles, total } = await get("/articleList", { data: { limit: 5, page: this.data.page, }, }); console.log(articles, total); this.setData({ articles, }); }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.getArticleList();//获取文章列表 }, }); -
pages/index/index.json 注册组件,以便在wxml中调用。
{ "usingComponents": { "article": "/components/article/article" }, "navigationBarTitleText": "首页" } -
pages/index/index.wxml
<article wx:for="{{articles}}" wx:for-item="article" wx:key="index" article="{{article}}"></article> -
pages/index/index.wxss
/* 之前的列表样式移除了。 */
-
点击跳转详情
-
/pages/index/index.wxml 页面的html结构,用于承载点击事件等。
<div wx:for="{{articles}}" wx:for-item="article" wx:key="index" article="{{article}}" bind:tap="toDetail" > <span>{{article}}</span> </div> -
pages/index/index.js 页面的点击事件,用于处理跳转逻辑的。
Page({ /** * 页面的初始数据 */ data: { articles: [ { _id: "6452633132c176fbe7ecd1ce", title: "1.闭包?什么是闭包?--JavaScript前端", author: "abc", createTime: "2022-1-20", content: "闭包的背景 由于js中只有两种作用域,全局作用域和函数作用域, 闭包的使用 函数柯里化 使用call实现bind 矩阵点击应用", poster: "https://static.zhufengpeixun.com/2_1689731480602.png", detail: "为了便于理解,我们将外部函数比喻为妈妈本体,里面保存着总钱数这个变量和消费这个行为,通过创建为儿子消费的这个行为对象,然后执行这个行为花费5元,返回剩余的95元。\n这个就是为了将变量money保存在mother本体内而避免暴露在外部的全局环境作用域中,只能通过mother()创建消费行为来影响money这个变量。\n 由此可以归纳总结使用闭包的三个步骤\n用外层函数包裹变量,函数;\n 外层函数返回内层函数;\n 外部用变量保存外部函数返回的内层函数\n目的是为了形成一个专属的变量,只在专属的作用域中操作。\n 上述的闭包代码示例中,有一个缺陷的场景是,在后续不需要money变量的情况下,没有释放该变量,造成内存泄露。原因是payForSon这个函数的作用域链引用着money对象,解决的办法是将payForSon = null就可以释放方法作用域,进而解除对money的引用,最后释放money变量。\n ", support: 40, look: 1100, __v: 0, }, { _id: "6452633132c176fbe7ecd1cf", title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~", author: "abc", createTime: "2022-2-20", content: "虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。", poster: "https://static.zhufengpeixun.com/6_1689731504176.webp", detail: "其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n", support: 60, look: 200, __v: 0, }, ], }, toDetail(e) { // console.log(e.detail._id); wx.navigateTo({ url: "/pages/article-detail/article-detail?id=" + e.detail._id, }); }, }); -
pages/article-detail/article-detail.js 拿到传递过来的id,并用这个id会做一些事。如语法接口数据等。
Page({ data: { article: {}, }, async onLoad(options) { console.log(options.id) if (!options.id) return; let { article } = await get("/article", { data: { id: options.id, }, }); console.log(article); this.setData({ article, }); }, });
点击详情编译小技巧-加参数
预览图片
- pages/article-detail/article-detail.wxml 用于承载图片的点击事件。
<view class="article-detail container">
<image
src="{{article.poster}}"
bind:tap="toPreviewImage"
data-url="{{article.poster}}"
></image>
</view>
- pages/article-detail/article-detail.js 用于定义页面要展示的图片,以及图片默认展示列表的调用接口。
Page({
data: {
article: {
_id: "6452633132c176fbe7ecd1cf",
title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~",
author: "abc",
createTime: "2022-2-20",
content:
"虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。",
poster: "https://static.zhufengpeixun.com/6_1689731504176.webp",
detail:
"其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n",
support: 60,
look: 200,
__v: 0,
},
},
toPreviewImage(e) {
const url = e.currentTarget.dataset.url;
wx.previewImage({
urls: [url, url, url], // 需要预览的图片http链接列表
});
},
});
生命周期
-
pages/life-cycle/life-cycle.js
// pages/life-cycle/life-cycle.js Page({ onLoad(options) { console.log(`onLoad - 监听页面加载`); }, onReady() { console.log(`onReady - 监听页面初次渲染完成`); }, onShow() { console.log(`onShow - 监听页面显示`); }, onHide() { console.log(`onHide - 监听页面隐藏`); }, onUnload() { console.log(`onUnload - 监听页面卸载`); }, onPullDownRefresh() { console.log(`onPullDownRefresh - 监听用户下拉动作`); }, onReachBottom() { console.log(`onReachBottom - 页面上拉触底事件的处理函数`); }, })
触底加载
- pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
articles: [
{
_id: "6452633132c176fbe7ecd1ce",
title: "1.闭包?什么是闭包?--JavaScript前端",
author: "abc",
createTime: "2022-1-20",
content:
"闭包的背景 由于js中只有两种作用域,全局作用域和函数作用域, 闭包的使用 函数柯里化 使用call实现bind 矩阵点击应用",
poster: "https://static.zhufengpeixun.com/2_1689731480602.png",
detail:
"为了便于理解,我们将外部函数比喻为妈妈本体,里面保存着总钱数这个变量和消费这个行为,通过创建为儿子消费的这个行为对象,然后执行这个行为花费5元,返回剩余的95元。\n这个就是为了将变量money保存在mother本体内而避免暴露在外部的全局环境作用域中,只能通过mother()创建消费行为来影响money这个变量。\n 由此可以归纳总结使用闭包的三个步骤\n用外层函数包裹变量,函数;\n 外层函数返回内层函数;\n 外部用变量保存外部函数返回的内层函数\n目的是为了形成一个专属的变量,只在专属的作用域中操作。\n 上述的闭包代码示例中,有一个缺陷的场景是,在后续不需要money变量的情况下,没有释放该变量,造成内存泄露。原因是payForSon这个函数的作用域链引用着money对象,解决的办法是将payForSon = null就可以释放方法作用域,进而解除对money的引用,最后释放money变量。\n ",
support: 40,
look: 1100,
__v: 0,
},
{
_id: "6452633132c176fbe7ecd1cf",
title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~",
author: "abc",
createTime: "2022-2-20",
content:
"虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。",
poster: "https://static.zhufengpeixun.com/6_1689731504176.webp",
detail:
"其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n",
support: 60,
look: 200,
__v: 0,
},
],
page: 1,
},
async getArticleList() {
wx.showNavigationBarLoading(); //更新时加loading
let { articles } = {
articles: [
{
_id: "6452633132c176fbe7ecd1cf" + this.data.page,
title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~",
author: "abc",
createTime: "2022-2-20",
content:
"虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。",
poster: "https://static.zhufengpeixun.com/6_1689731504176.webp",
detail:
"其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n",
support: 60,
look: 200,
__v: 0,
},
],
};
this.setData({
articles: [...this.data.articles, ...articles],
page: this.data.page + 1,
});
wx.hideNavigationBarLoading(); //加载后去掉loading
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.getArticleList(); //获取文章列表
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
// console.log("reachBottom")
this.getArticleList();
},
});
- pages/index/index.wxml
<view
wx:for="{{articles}}"
wx:for-item="article"
wx:key="index"
article="{{article}}"
>
<view style="height:700px">{{article.title}}</view>
</view>
顶部下拉刷新
- pages/index/index.json
{
"enablePullDownRefresh": true
}
- pages/index/index.js
Page({
/**
* 页面的初始数据
*/
data: {
articles: [
{
_id: "6452633132c176fbe7ecd1ce",
title: "1.闭包?什么是闭包?--JavaScript前端",
author: "abc",
createTime: "2022-1-20",
content:
"闭包的背景 由于js中只有两种作用域,全局作用域和函数作用域, 闭包的使用 函数柯里化 使用call实现bind 矩阵点击应用",
poster: "https://static.zhufengpeixun.com/2_1689731480602.png",
detail:
"为了便于理解,我们将外部函数比喻为妈妈本体,里面保存着总钱数这个变量和消费这个行为,通过创建为儿子消费的这个行为对象,然后执行这个行为花费5元,返回剩余的95元。\n这个就是为了将变量money保存在mother本体内而避免暴露在外部的全局环境作用域中,只能通过mother()创建消费行为来影响money这个变量。\n 由此可以归纳总结使用闭包的三个步骤\n用外层函数包裹变量,函数;\n 外层函数返回内层函数;\n 外部用变量保存外部函数返回的内层函数\n目的是为了形成一个专属的变量,只在专属的作用域中操作。\n 上述的闭包代码示例中,有一个缺陷的场景是,在后续不需要money变量的情况下,没有释放该变量,造成内存泄露。原因是payForSon这个函数的作用域链引用着money对象,解决的办法是将payForSon = null就可以释放方法作用域,进而解除对money的引用,最后释放money变量。\n ",
support: 40,
look: 1100,
__v: 0,
},
{
_id: "6452633132c176fbe7ecd1cf",
title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~",
author: "abc",
createTime: "2022-2-20",
content:
"虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。",
poster: "https://static.zhufengpeixun.com/6_1689731504176.webp",
detail:
"其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n",
support: 60,
look: 200,
__v: 0,
},
],
page: 1,
},
async getArticleList() {
wx.showNavigationBarLoading(); //更新时加loading
let { articles } = {
articles: [
{
_id: "6452633132c176fbe7ecd1cf" + this.data.page,
title: "2.GPT-4 炸裂成那样,前端真的还有机会吗?我是这么看的~",
author: "abc",
createTime: "2022-2-20",
content:
"虽然在短期内,ChatGPT将使开发人员能够更快地完成开发工作,而不是取代他们。但技术的发展日新月异,很难想象 ChatGPT及其他的大模型在 10 到 20 年后会是什么样子。",
poster: "https://static.zhufengpeixun.com/6_1689731504176.webp",
detail:
"其实这背后的逻辑并不难理解,chatGPT 所训练的数据来源于互联网,它目前还具备自我生成、左右手互博的能力,也就意味着,答案的最终来源仍然是网页背后千千万万的开发者。如果他们被一瞬间干掉了,chatGPT 的数据从哪来?答案的保真度、新鲜度从何而来?你敢说 2 年、3年、5年后的React写法、功能和现在一样?还有那千千万万不断迭代的 npm 包!\n更有甚的可能会是一些严重的社会民生问题,比如,你司的医疗APP接入 chatGPT,作为24小时人工智能客服机器人给病人问诊开药,你能保证机器人不会将感冒错误地诊断为XinGuan?你能保证机器人不会给病人开错药?\n因此,准确性可能会逐渐提高,但永远不会完美,因为互联网上的数据本身准确性就非常有问题。在庞大的用户群面前,哪怕一两个典型的事件就足可能杀死一家公司,更别说几十上百件。\n",
support: 60,
look: 200,
__v: 0,
},
],
};
this.setData({
articles: [...this.data.articles, ...articles],
page: this.data.page + 1,
});
wx.hideNavigationBarLoading(); //加载后去掉loading
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
this.getArticleList(); //获取文章列表
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
async onPullDownRefresh() {
console.log("pullRefresh");
this.data.page = 1;
this.data.articles = [];
await this.getArticleList();
wx.stopPullDownRefresh(); //关闭下拉
},
});
- pages/index/index.wxml
<view
wx:for="{{articles}}"
wx:for-item="article"
wx:key="index"
article="{{article}}"
>
<view style="height:700px">{{article.title}}</view>
</view>
tab切换
- pages/interview/interview.json
{
"usingComponents": {
"van-rate": "@vant/weapp/rate/index"
},
"navigationBarTitleText": "面试题"
}
- pages/interview/interview.wxml
<view class="container">
<scroll-view style="white-space: nowrap;">
<view
class='tab {{index==currentIndex?"active":""}}'
wx:for="{{tabs}}"
wx:for-item="tab"
wx:key="index"
data-index="{{index}}"
bind:tap="switchTab"
>
{{tab}}
</view>
</scroll-view>
</view>
<swiper current="{{currentIndex}}">
<swiper-item
wx:for="{{tabs}}"
wx:for-item="tab"
wx:key="index"
>
{{tab}}
</swiper-item>
</swiper>
- pages/interview/interview.js
Page({
/**
* 页面的初始数据
*/
data: {
tabs: ["css", "js", "html", "vue", "react", "typescript", "node"],
currentIndex: -1,
lists: [],
computedHeight: 0,
},
async swipe(currentIndex) {
console.log(currentIndex);
if (currentIndex == this.data.currentIndex) return;
this.setData({
currentIndex,
});
},
switchTab(e) {
this.swipe(e.currentTarget.dataset.index);
},
});
动态获取DOM并得到尺寸
- pages/interview/interview.json
{
"usingComponents": {
"van-rate": "@vant/weapp/rate/index"
},
"navigationBarTitleText": "面试题"
}
- pages/interview/interview.wxml
<swiper
current="{{currentIndex}}"
bindchange="switchSwiper"
style="height:{{computedHeight}}px"
>
<swiper-item
wx:for="{{tabs}}"
wx:for-item="tab"
wx:key="index"
>
<view class="swiper-item-{{index}}">
<block
wx:for="{{lists}}"
wx:for-item="list"
wx:key="index"
>
<text>{{list.title}}</text>
55555
</block>
</view>
</swiper-item>
</swiper>
- pages/interview/interview.js
Page({
data: {
tabs: ["css", "js", "html", "vue", "react", "typescript", "node"],
currentIndex: -1,
lists: [],
computedHeight: 0,
},
async swipe(currentIndex) {
//动态获取swiper-item的高度
let selector = wx.createSelectorQuery();
selector.select(`.swiper-item-${currentIndex}`).boundingClientRect();
selector.exec((res) => {
console.log(`res-->`, res);
});
},
onLoad(options) {
this.swipe(0); // 解决第一个不显示问题
},
});
应用的动态尺寸
- pages/interview/interview.json
{
"usingComponents": {
"van-rate": "@vant/weapp/rate/index"
},
"navigationBarTitleText": "面试题"
}
- pages/interview/interview.wxml
<view class="container">
<scroll-view style="white-space: nowrap;">
<view
class='tab {{index==currentIndex?"active":""}}'
wx:for="{{tabs}}"
wx:for-item="tab"
wx:key="index"
data-index="{{index}}"
bind:tap="switchTab"
>
{{tab}}
</view>
</scroll-view>
</view>
<swiper
current="{{currentIndex}}"
bindchange="switchSwiper"
style="height:{{computedHeight}}px"
>
<swiper-item
wx:for="{{tabs}}"
wx:for-item="tab"
wx:key="index"
>
<view class="swiper-item-{{index}}">
<block
wx:for="{{lists}}"
wx:for-item="list"
wx:key="index"
>
<text>{{list.title}}</text>
<view class="interview-oprater">
<van-rate
custom-class="rate"
value="{{ list.hard }}"
color="#ffd21e"
void-icon="star"
void-color="#eee"
bind:change="onChange"
/>
</view>
</block>
</view>
</swiper-item>
</swiper>
- pages/interview/interview.js
import { get } from "../../utils/request";
// pages/interview/interview.js
Page({
/**
* 页面的初始数据
*/
data: {
tabs: ["css", "js", "html", "vue", "react", "typescript", "node"],
currentIndex: null,
lists: [],
coumputedHeight: 0,
},
async swipe(currentIndex) {
if (currentIndex === this.data.currentIndex) {
return;
}
this.setData({
currentIndex,
});
//
const type = this.data.tabs[this.data.currentIndex];
// console.log("type", type);
const { interview: lists } = await get("/interview", {
data: {
type,
},
});
console.log("lists", lists);
this.setData({ lists });
//动态获取swiper-item的高度
let selector = wx.createSelectorQuery();
selector.select(`.swiper-item-${currentIndex}`).boundingClientRect();
selector.exec((res) => {
console.log("res", res);
let height = res?.[0]?.height;
if (height == null) {
return;
}
this.setData({
coumputedHeight: height,
});
});
},
switchTab(e) {
this.swipe(e.currentTarget.dataset.index);
},
switchSwiper(e) {
this.swipe(e.detail.current);
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
this.swipe(0);
},
});
收藏课程
- pages/lesson/lesson.json
{
"usingComponents": {
"van-search": "@vant/weapp/search/index",
"van-button": "@vant/weapp/button/index"
},
"navigationBarTitleText": "课程中心"
}
- pages/lesson/lesson.wxml 收藏按钮的展示。
<view
class="lesson"
wx:for="{{lessonLists}}"
wx:for-item="list"
wx:key="index"
>
<image src="{{list.poster}}" mode="aspectFill"></image>
<view class="lesson-info">
<text>{{list.title}}</text>
<view class="btn-list">
<van-button
type="warning"
bind:tap="toCollect"
data-lesson="{{list}}"
>收藏
</van-button>
</view>
</view>
</view>
- pages/lesson/lesson.js 收藏的逻辑。
Page({
data: {
lessonLists: [
{
_id: "64536367a5d86043a3d99d67",
title: "谈谈你对SPA单页应用的理解,它的优缺点是是什么",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/2.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d6b",
title: "Vue生命周期的理解",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/4.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d68",
title: "谈谈你对vue的理解",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/1.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d69",
title: "v-if和v-for哪个优先级更高",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/3.mp4",
__v: 0,
desc: "常见vue面试题",
},
],
collectLesson: {},
},
toCollect(e) {
const lesson = e.currentTarget.dataset.lesson;
this.data.collectLesson[lesson._id] = lesson;
wx.setStorageSync("collect", this.data.collectLesson);
},
});
- pages/collect-list/collect-list.wxml 已收藏页面的展示。
<van-cell
is-link
wx:for="{{lists}}"
wx:key="index"
title="{{item.title}}"
bind:tap="redirect"
/>
- pages/collect-list/collect-list.js 已收藏页面的逻辑
Page({
data: {
lists: [],
},
onLoad(options) {
let lists = wx.getStorageSync("collect");
if (!lists) return;
this.setData({
lists: Object.values(lists),
});
},
redirect() {
wx.switchTab({
url: "/pages/lesson/lesson",
});
},
});
- pages/collect-list/collect-list.json
{
"usingComponents": {
"van-cell": "@vant/weapp/cell/index",
"van-cell-group": "@vant/weapp/cell-group/index"
}
}
课程的筛选
- pages/lesson/lesson.json
{
"usingComponents": {
"van-search": "@vant/weapp/search/index",
"van-button": "@vant/weapp/button/index"
},
"navigationBarTitleText": "课程中心"
}
- pages/lesson/lesson.wxml
<van-search
value="{{ value }}"
placeholder="请输入搜索的内容"
bind:search="onSearch"
/>
<view
class="lesson"
wx:for="{{computeLists}}"
wx:for-item="list"
wx:key="index"
>
<image src="{{list.poster}}" mode="aspectFill"></image>
<view class="lesson-info">
<text>{{list.title}}</text>
</view>
</view>
- pages/lesson/lesson.js
Page({
data: {
value: "",
url: "",
lessonLists: [
{
_id: "64536367a5d86043a3d99d67",
title: "谈谈你对SPA单页应用的理解,它的优缺点是是什么",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/2.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d6b",
title: "Vue生命周期的理解",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/4.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d68",
title: "谈谈你对vue的理解",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/1.mp4",
__v: 0,
desc: "常见vue面试题",
},
{
_id: "64536367a5d86043a3d99d69",
title: "v-if和v-for哪个优先级更高",
poster: "https://static.zhufengpeixun.com/1_1689731473030.webp",
url: "https://zishui.oss-cn-beijing.aliyuncs.com/3.mp4",
__v: 0,
desc: "常见vue面试题",
},
],
collectLesson: {},
computeLists: [],
},
onSearch(e) {
//console.log(e.detail) 搜索框里输入的内容
let lessonLists = this.data.lessonLists;
if (e.detail == "") {
this.setData({
computeLists: lessonLists,
});
}
//lessonLists [{title:""},{title:"123"}]
this.setData({
computeLists: lessonLists.filter((item) => item.title.includes(e.detail)),
});
},
onLoad(options) {
this.setData({
computeLists: this.data.lessonLists,
});
},
});
分享功能
原生上方分享
-
wx.showShareMenu()允许当前页面可以被用户分享。
Page({ onLoad(options) { wx.showShareMenu({ withShareTicket: true, menus: ["shareAppMessage", "shareTimeline"], }); }, }) -
修改用户分享到朋友圈的标题
Page({ onShareTimeline(){ return { title:"珠峰珠峰" } } })
自定义分享按钮
-
设置自定义分享按钮
-
pages/mime/mime.wxml
<button type="info" open-type="share">分享小程序</button>
-
-
定义分享相关回调
-
pages/mime/mime.js
Page({ /** * 用户点击右上角分享 */ onShareAppMessage() { //分享结束后触发 return { title: "珠峰学堂", path: "/page/index/index", success: function (res) { console.log("分享成功", res); }, fall: function (res) { console.log("分享失败", res); }, }; }, });
-
-
修改用户分享到朋友圈的标题
-
pages/mime/mime.js
Page({ onShareTimeline(){ return { title:"珠峰珠峰" } } })
-