preface

Every programmer, at the beginning of time is a little white, bit by bit accumulation, step by step, slowly grow up. I believe that for the big guys, it is not difficult to write a small program, but for me this kind of learning is not long for people, every step is in the mud, do not know where there is a pit in the mud, of course, this for the novice, is a kind of growth, step on the pit, the road will gradually smooth up.

So still want to refuel struggle.

This is the first small program project I wrote, because it is with others, I wrote part of it, I want to write this article, record my first small program project, at the same time to write their own small program, share with you, I hope to help people in the effort.

Applets sharing

Bilibili_appellate P

Overall effect display

Take a look at the results:

These are some of the tools used to write applets.

There are like vant components

Official documents of wechat applets

Fiddler packet capture tool

Alibaba Font Library

page

As a whole

Start to write small procedures, the first is to cut the page, first look at the home page

What do we use when we write pages?

  1. External styles, such as WeUI styles

  2. External components, such as Vant

  3. Since the writing component

  4. The writing style

  5. Font library, such as Alibaba font library

    Some common styles, such as search boxes, navigation bars, etc., or components, can be introduced to external direct use, usage is documented, look at the use of the page, but without similar components and styles, you have to write your own page to use ICONS in many places, ICONS also reference external font libraryCopy the code

Page architecture

- van-search-van-tabs - hot - hot_item - chase_date_item - day_of_week - chase_index - chase_recommend - chase_recommendCopy the code

Use the Vant components Search and van-tabs to quickly assemble the entire page

And then under the popular TAB, it’s all a list of videos in one style, so I’ll just use a Wx: for loop, and I’ll wrap the TAB in a Scroll view for easy scrolling

Chase_date_item is obviously a van-tabs, but each TAB looks like a van-tabs. You can also use a wx: for loop with a list of tabs

The rest is the same, using the wx: for loop list

The following is the video player page and the drama player page. The search page only has a van-search, so it is not shown

Video player page:

Play page:

Styles (experience trample pit sharing)

Simple style we will write, so I will not post out, there is a need to go to my Gitee source code, link in the back of the article, if you like, you can point a collection

Here I will describe my experience and the pits I have stepped on

1. Flexible layout

Most layouts can be handled with elastic layouts. Horizontal layouts, which cannot be represented by elastic layouts, can be replaced with margins, using special selectors such as:

.chase_date_item__content:nth-child(4n+1){
  margin-left: 0;
}
Copy the code

It’s 4n plus 1

Some special needs, use absolute positioning, other times less positioning, affect performance

2. One problem with elastic layout is that margin and padding defined on a box with elastic layout will increase the width and height of the box. Using a width and height limit will not work, but you can solve this problem by adding a style:

    box-sizing: border-box;
Copy the code

3. One or more lines of text beyond display…

We all have one line of text that displays beyond… , the style is:

  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
Copy the code

But to achieve more than one line of text display… How do you do that? :

  text-overflow: ellipsis;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
Copy the code

We know we can do animations with transition. Here’s a quick introduction to the video

This looks like the transition height, but the length of the profile message is variable, so it can’t fix the height. If height is auto, the transition doesn’t work, so you have to use max-height instead. Set max-height to a value that can’t be higher than height, but it’s not too high, so it doesn’t work

.drop_content{
  max-height: 40vh;
  overflow: hidden;
  transition: all 0.5s;
}
.drop_content_on{
  max-height: 0;
  overflow: hidden;
  transition: all 0.5s;
}
Copy the code

5. An unruly button

Button has a lot of uses in small programs, but when we use it, its style is always not what we want, so we need to reset it

button::after { border: none; }
button {
  display: inline;
  padding: 0! important; margin:0! important; font-weight: normal ! important; color: #000! important; background-color: #fff ! important; }Copy the code

Here I need a button as a container for functionality, so I add styles! Important, some attributes will not take effect unless the level is raised. This is also some operations inside the button component of wechat small program, there is no way. These attributes can also be overridden by writing another class if necessary

6. Animation implementation of wechat applets

The cSS3 animation effect in the applet will not take effect. If you want to achieve the animation effect, you must use JS, and the animation property and API of the applet

Let’s see what happens

wxml

js

let animation = wx.createAnimation({   // Create an animation
      duration: 300.timingFunction: 'linear'.delay: 0
    });
    animation.rotate(180).step();    // Add animation
    this.setData({
      ani:animation.export()       // Add animation to data to drive the page
    });
Copy the code

When you’re done, you’ll notice that the animation will only run once. It’s a Bandtap event, but it doesn’t execute every time it clicks

Of course, you can add an animation to make it go back to the previous state, click again to work

    animation.rotate(180).step();
    animation.rotate(0).step();  // Add an animation to return to the previous state
Copy the code

But it’s not pretty, you can see my animation is click and turn and see what happens

Rotate(n){         // Pass in a parameter
    let animation = wx.createAnimation({
      duration: 300.timingFunction: 'linear'.delay: 0
    });
    animation.rotate(180*n).step();   // Each click changes the rotation Angle of the animation according to the incoming n
    this.setData({
      ani:animation.export()
    });
  },
Copy the code

Because this button also has the ability to change page data, more on this later

7. Component style: component is written by others, he will provide you with style interface, but often not up to the effect you want, in fact, this is the same as button, appropriate addition! Important increases the priority to work, for example:

Here's the Van-Tab component, I want to design the selected style, it provides the interface, but once I write the style, the original style is broken. You want to write your own style, but the built-in style of the component prevents you, use it properly! Important makes your style workCopy the code
.tab_active{ background-color: #FB7299; margin-top: 10rpx ! important; border-radius: 60rpx; color: #fff ! important; height: 70rpx; line-height: 70rpx ! important; }Copy the code

External components have a number of properties to set different styles, this is more documentation, I used the component: van-search van-tab

Function –

Once you’re done with your pages, start writing your features. Working with your pages is exhausting, but it’s going to get even more exhausting

data

To write a complete page, a very important one is the data, no data can not see the effect, we will use a static data when writing the page to better see the effect, there is no way to design some functions, and the micro channel small program page is data-driven, it is also very important

Having said that, I did not make real data and used some fake data. I tried to find the API interface of Bilibili, but I did not find a simple and easy interface, and some other complex interfaces could not be used, so I had to find other methods. If you have a good idea also hope to leave a message

I used The Fiddler packet capture tool to capture data. For details, please refer to this article

Captured JSON data can also be imported directly into the cloud database

In addition, some uncaptured handwritten data was placed in the data folder along with some unfixed data, that is, data that changes over time.

Module. exports + require is introduced in JS when needed

Function is introduced

1. Page, style switch

Small programs often need to switch pages, of course, there is no actual jump page, just hidden, we usually use wx: if:

<view wx:if="{{... }}"><view>Copy the code

However, this method is not good for frequent switching, because Wx: if will render when needed and will destroy when not needed. Frequent switching will render and destroy frequently. Instead, we can use hidden, really hidden:

<view hidden="{{currentId! =0}}"></view> <view hidden="{{currentId! =1}}"></view>Copy the code

Style switching can be done using ternary operators:

<view class="play-information__title {{isDrop ? 'detail_drop':'detail_nodrop'}}"></view>
Copy the code

2. Load data from top to bottom

In fact this is not difficult, because the scroll - the view component itself with these two events, can see [documents] (https://developers.weixin.qq.com/miniprogram/dev/component/scroll-view.html)Copy the code
<scroll-view class="hot_item-scroll" scroll-y
    bindscrolltolower="addmoreAfter"
    bindscrolltoupper="addmoreBefore"
    upper-threshold="0"
    lower-threshold="20"
    >
Copy the code

The last two properties indicate the distance at which the event is triggered, with the top set to 0 and the bottom set to 20

Link the specified set in the database, only take 20 of them into data, at the same time get all the data length of the set

const db=wx.cloud.database();
const plays=db.collection('plays');
async setvoicedata(){
    let res=await plays
    .limit(20)
    .get();
    this.voiceList=res.data;
    this.total=(await plays.count()).total;
    this.setData({
      voiceList:this.voiceList
    })
  },
Copy the code

Two event functions

Judge the data length of the page. If it exceeds the total length of all data, no more data will be displayed and returned; otherwise, 20 data will be pulled from all data (skip() is used to skip the data already pulled and get the new data), and then the data will be put into the data using the expansion operator, paying attention to asynchrony

async addmoreAfter(){
    const index=this.data.voiceList.length;
    if(index>=this.total){
      wx.showToast({
        title: 'No more data'.icon:'none'
      })
      return ;
    }
    wx.showToast({
      title: 'Loading'.icon:'loading'.duration:1000
    })
    let {data:voiceList}=await plays
    .skip(index)
    .limit(20)
    .get()
    this.setData({
      voiceList:[...this.data.voiceList,...voiceList]
    })
  },
  async addmoreBefore(){
    const index=this.data.voiceList.length;
    if(index>=this.total){
      wx.showToast({
        title: 'No more data'.icon:'none'
      })
      return ;
    }
    wx.showToast({
      title: 'Loading'.icon:'loading'.duration:1000
    })
    let {data:voiceList}=await plays
    .skip(index)
    .limit(20)
    .get()
    this.setData({
      voiceList:[...voiceList,...this.data.voiceList]
    })
  },
Copy the code

3. Sharing

Wechat applet has built-in API, button open-type set to share;

<button open-type="share"><text class="iconfont icon-weixin1"></text></button>Copy the code

If necessary, set up some data to transmit video information

<button open-type="share"><text class="iconfont icon-weixin1" data-id="{{... }}"></text></button>Copy the code

Set the style of sharing. Js has an onShareAppMessage function that handles this event and returns an object containing the title, image, and address to jump to when opened, which can pass the ID of the video

onShareAppMessage: function () {
    return{
    title:this.data.playInformation.title,
    imageUrl:this.data.playInformation.video_cover,
    path:"/pages/play/play? id="+this.data.playInformation.playid
    }
  }
Copy the code

4. Collection function

I’m going to connect to the database set and change the data, and I’m going to change the user data, but because I’m not responsible for the user, I’m not going to write, same principle, change the database data and change the local data at the same time

const db=wx.cloud.database();
const _=db.command;     / / cloud function
async collectPlay(){
    if(this.data.isCollect){
      this.playInformation.collect--;
      this.setData({
        isCollect:false.// Use to determine whether to collect data
        playInformation:this.playInformation
      });
      playCollection
      .where({
        playid:this.data.playInformation.playid
      })
      .update({
        data: {collect:_.inc(-1)    / / the decrement}})}else{
      this.playInformation.collect++;
      this.setData({
        isCollect:true.playInformation:this.playInformation
      })
      playCollection
      .where({
        playid:this.data.playInformation.playid
      })
      .update({
        data: {collect:_.inc(1)   / / since the increase}}}}),Copy the code

5. Search function search is to the database search, so the last function is similar, but to use the regular, fuzzy search

<van-search value="{{value}}"
 show-action
  shape="round"
  bind:search="onSearch"
  clearable="true"
  />
Copy the code
onSearch(e){
    wx.showToast({
      title: 'Query in progress'.icon:'loading'
    });
    let keyword=e.detail;       // The keyword passed when the event is triggered on the search component
    if(! keyword.trim()){// trim removes whitespace
      wx.showToast({
        title: 'Please enter the keyword you want to enter'.icon:'error'
      })
      return ;
    }
    posterCollection
    .where({
      title:db.RegExp({      // Regular expressions
        regexp:keyword,
        options:'i'        // Ignore case
      })
    })
      .orderBy('ts'.'desc')  / / sorting
      .get()
      .then(res= >{
        console.log(res);
        this.setData({
          result:res.data
        })
      })

  },
Copy the code

6. Change

The animation style of the change has been introduced before, and the data of the change is also limited. At the end of the change, it will return to the first recommendation, so this is a round robin, click to go to the next one, and at the end, return to the first one

const {result}=require('.. /.. /data/recommend');  // Globally import the required data. This file can be replaced as needed
const recommend = require('.. /.. /data/recommend');
Copy the code
changeRecommend(e){
    let id=e.currentTarget.dataset.id;
    let [n1,n2]=this.data.n; 
    // n is an array for counting, because there are two identical swaps, so we define an array to count separately, and merge the two together
    let n=this.data.n[id-1];  // Use the passed Id to determine which swap is triggered
    if(n>6){
      n=0;
    }            // Determine if the round is last, if so, jump to the first
    const recommend=modules[id].items;  // Data is stored as an array
    let recommendShow=recommend.slice(n*3,n*3+3); // Get the current round data
    this.Rotate(n);                // Trigger animation
    if(id==1) {this.setData({
        recommendShow,
        n:[n+1,n2]             // Update data})}else{
      this.setData({
        recommendShowMy:recommendShow,          // Update data
        n:[n1,n+1]})}},Copy the code

7. Display data by date

It wasn’t hard, but it took a while to design the data, and here’s the code

    chaseWeek:['一'.'二'.'三'.'four'.'five'.'六'.'day'].episodes: [{dayofweek:1.data: {... },... ]// Same array, sorted by week
    // Prepare data
Copy the code
// Change the sort of data according to the date
datebar(){
    const firstepisodes=this.data.episodes;  // Get the initial data
    let episodes=[];
    let todayOfWeek=new Date().getDay();  // Get today this week
    for(let i=0; i<7; i++){// Loop to change the data order
      let j=(i+todayOfWeek+4) %7;
      episodes.push(firstepisodes[j]);
    }
    this.setData({
        episodes
      })                   // Set the data
  },
Copy the code

For asynchronous reasons, I put this function in the onReady cycle, and using wx: for on the page changes the output based on the date

other

As for the components and the ability to generate posters from the canvas, it is not completely solved yet, but I need to practice for a few more days, maybe there will be a next article, if you have a share, please comment

conclusion

The above is all my share content, my small step, I do not know whether to bring you help or entertainment, I hope you can like it, like if you point a thumb-up oh

The source code

Finally, I would like to support bilibili_appellate