20230720----重返学习-小程序页面的初步完成

文章详细介绍了微信小程序中使用vant-weappUI框架进行页面构建的过程,包括vant-weapp的安装、组件注册与使用,以及首页轮播图、列表、生命周期事件的处理。此外,还涉及到了小程序页面的动态尺寸调整、收藏功能、分享功能的实现,以及原生分享与自定义分享按钮的应用。
摘要由CSDN通过智能技术生成

day-116-one-hundred-and-sixteen-20230720-小程序页面的初步完成

UI框架

  1. weui - 微信小程序推荐的官方UI框架-很少人使用
  2. vant-weapp - 实际开发中常用的主流UI框架

vant-weapp安装

  1. 步骤一 通过 npm 安装

    # 通过 npm 安装
    npm i @vant/weapp -S --production
    
  2. 步骤二 修改 app.json

    • 将 app.json 中的 “style”: “v2” 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
  3. 步骤三 修改 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配置为’./'即可
  4. 步骤四 构建 npm包

    • 打开微信开发者工具,点击 工具 -> 构建 npm,并勾选 使用 npm 模块 选项,构建完成后,即可引入组件。
  5. 在需要使用的时候,在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相关组件

  1. 在安装之后直接在json中注册;

    • pages/mime/mime.json

      {
        "usingComponents": {
          "van-cell": "@vant/weapp/cell/index",
          "van-cell-group": "@vant/weapp/cell-group/index"
        },
      }
      
  2. 在注册好之后,直接在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>
      
  3. 如果在组件上绑定了一些方法,那么就在js中定义好。

    • pages/mime/mime.js

      Page({
        logout(){
          wx.clearStorageSync()
          wx.reLaunch({
            url: '/pages/mime/mime',
          })
        },
      })
      

首页轮播图

  • swiper - 微信小程序原生组件

  • 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;
    }
    

首页列表封装成组件

  1. 新建/components/article/,在/components/article/中右键打开菜单,点击新建Component,输入article会自动生成对应的四个文件。

    • 小程序中,默认所有组件类型的文件,都放在/components/中。
  2. 写代码:

    • 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;
      }
      
  3. 在需要用的地方导入并使用

    • 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>

顶部下拉刷新

  1. 小程序配置 /页面配置
  • 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,
    });
  },
});

分享功能

原生上方分享
  1. wx.showShareMenu()允许当前页面可以被用户分享。

    Page({
      onLoad(options) {
        wx.showShareMenu({
          withShareTicket: true,
          menus: ["shareAppMessage", "shareTimeline"],
        });
      },
    })
    
  2. 修改用户分享到朋友圈的标题

    Page({
      onShareTimeline(){
        return {
          title:"珠峰珠峰"
        }
      }
    })
    

自定义分享按钮

  1. 设置自定义分享按钮

    • pages/mime/mime.wxml

      <button type="info" open-type="share">分享小程序</button>
      
  2. 定义分享相关回调

    • pages/mime/mime.js

      Page({
        /**
        * 用户点击右上角分享
        */
        onShareAppMessage() {
          //分享结束后触发
          return {
            title: "珠峰学堂",
            path: "/page/index/index",
            success: function (res) {
              console.log("分享成功", res);
            },
            fall: function (res) {
              console.log("分享失败", res);
            },
          };
        },
      });
      
  3. 修改用户分享到朋友圈的标题

    • pages/mime/mime.js

      Page({
        onShareTimeline(){
          return {
            title:"珠峰珠峰"
          }
        }
      })
      

打包发到线上

微信小程序开发中主要使用的文档

  1. weui - 微信小程序推荐的官方UI框架-很少人使用
  2. vant-weapp - 实际开发中常用的主流UI框架
  3. swiper - 微信小程序原生组件-微信小程序中常用的

进阶参考

  1. weui - 微信小程序推荐的官方UI框架-很少人使用
  2. vant-weapp - 实际开发中常用的主流UI框架
  3. swiper - 微信小程序原生组件-微信小程序中常用的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值