origin

Programming is something that requires theory and practice to really learn the skills. Therefore, the author wants to feel the design philosophy of Vue3 and the crystallization of the authors' labor through some practical applications. So, what to do? It suddenly occurred to me that people don’t like to post WeChat Moments very much anymore. After all, WeChat is such a large-scale super APP, and it is filled with your relatives, colleagues, bosses, etc. If you complain a little, you are too embarrassed to post it. In this case, let's be an anonymous circle of friends, so that there is no place to hide things that you don't want to be seen in the circle of acquaintances. Hahaha (I'm a little excited to think about it!)

code

As soon as I said it, the author quickly initialized the project and started the journey of moving bricks. The operating system used to develop this project is MBP, the technology stack is a common combination of Vue3 + Vue Router + Axios, and Vant is selected as the UI component library. In addition, dayjs is used for date processing, and the lodash library is also used, which is easy to use directly. utility function.

Log in

Since it is a circle of friends, it must be logged in. In order not to have a complicated login and registration process, the author intends to directly access the JSSDK of the WeChat public account to realize the authorized login of WeChat. Of course, there are still a lot of pits here, and the author has written another article for the record. Interested people can drop down to the elegant implementation of authorized login in Vue WeChat development . In this project, the author accesses the WeChat silent authorization method. This authorization login method is almost unaware of users, but cannot obtain the user's WeChat nickname and avatar. However, since our main focus is anonymity, it does not exactly match the needs. Well (it feels really comfortable to be a product by myself, if I need to cut it, I will cut it, hahahaha)

If the user's avatar and nickname cannot be obtained, will it appear too empty on the display? Yes, I have considered it. This problem is easy to say, directly generate a nickname library on the server side, and assign a random one to each user! As for the avatars, I was thinking of creating an avatar library just like my nickname. As a result, by a coincidence, the author found such a project:

boringavatars
github

This project can generate a corresponding avatar image based on a series of random hash values, which is very interesting and very simple to use, similar to the following:

 import Avatar from "boring-avatars";

<Avatar
  size={40}
  name="Maria Mitchell"
  variant="marble"
  colors={["#92A1C6", "#146A7C", "#F0AB3D", "#C271B4", "#C20D90"]}
/>;

I happily use it in my project.

Post news

After the user logs in, the first thing is to publish the news. The function of sending dynamics is actually not complicated, that is, fill in the form and submit it to the server. For the interface, I took a look at the design of WeChat to send friends, and then added a label, which is roughly as follows:

发布动态

This involves file uploading. Considering the limited bandwidth of the server, the author uses Qiniu cloud storage as the static resource server, and realizes the image uploading through the client-side direct transmission. It is very simple for the client to directly communicate with Trumpchi. Whether it is Qiniu Cloud or the file management service of other cloud vendors, you can upload it using the form upload method (that is, the method of direct post request to transfer formdata), and the author uses Axios for uploading. Example:

 const formData = new FormData();
formData.append("file", file); // file对象
formData.append("token", token); //通过服务端获取的上传凭证
formData.append("key", key); //资源名,可以自行设定规则生成
const uploadUrl = "http://up-z2.qiniu.com";

axios
  .request({
    url: uploadUrl,
    method: "post",
    onUploadProgress(progressEvent) {
      // 上传进度
    },
    data: formData,
    timeout: 0,
    headers: { "Content-Type": "multipart/form-data" },
  })
  .then((res) => {
    // 上传后的文件信息
    console.log(res.data);
  });

There are actually many details involved in image uploading, including uploading experience optimization, image compression, watermarking, batch uploading, resuming uploading at breakpoints, multipart uploading, access authentication, and more. Due to time constraints, the author has not implemented them one by one for the time being. Next time, the author must share various details about the image upload function in detail.

dynamic list

The dynamic list is also very simple. With the use of the vant component library, a list that can be pulled down to refresh and slide up to load more information flow lists can be quickly developed. The approximate logic is as follows:

 <template>
  <van-pull-refresh
    v-if="feedList.length"
    v-model="refreshing"
    :pull-distance="200"
    @refresh="onRefresh"
  >
    <van-list
      v-model:loading="isLoading"
      :finished="finished"
      finished-text="没有更多了"
      @load="fetchData"
    >
      <template v-for="feed in feedList" :key="feed.id" class="feed-list">
        <FeedItem :data="feed"></FeedItem>
      </template>
    </van-list>
  </van-pull-refresh>
</template>

<script lang="ts">
import { useAxios } from "@/hooks/useAxios";
import { defineComponent } from "vue";
import { PullRefresh, List } from "vant";
import FeedItem from "./FeedItem.vue";
export default defineComponent({
  name: "FeedList",
  components: {
    [PullRefresh.name]: PullRefresh,
    [List.name]: List,
    FeedItem,
  },
  data() {
    return {
      feedList: [],
      refreshing: false,
      isLoading: false,
      finished: false,
      page: 1,
      apiUrl: "/api/foo/bar", // 请求接口
      params: {}, //请求参数
    };
  },
  mounted() {
    this.onRefresh();
  },
  methods: {
    fetchData() {
      const limit = 10;
      // 刷新
      if (this.refreshing) {
        this.feedList = [];
        this.page = 1;
        this.refreshing = false;
      }
      const params = {
        p: this.page,
        limit,
        ...this.params,
      };

      useAxios.get(this.apiUrl, params).then((res) => {
        this.isLoading = false;
        this.feedList = [...this.feedList, ...res];
        this.page++;
        if (res.length < limit) {
          // 到最后了
          this.finished = true;
        }
      });
    },
    onRefresh() {
      this.finished = false;
      this.isLoading = true;
      this.fetchData();
    },
  },
});
</script>

Finally, the author added a tab component to display all the dynamics and my dynamics. The effect is as follows:
猿圈

write at the end

Although the anonymous circle of friends is only a very simple and small project, in fact, there are quite a lot of details in its implementation. In addition to the completion of publishing news and brushing news, the author has also implemented functions such as likes and comments. In the subsequent iterations, I will continue to share the implementation details of other function points, hoping to inspire readers. Of course, I also hope that there are big brothers who can communicate (give guidance) together. The author has deployed the project to the server. You can copy the link to WeChat to open it, or scan the code to access:

体验地址

About the author

A wild programmer who has been working alone in the start-up team for a long time, he has done server-side development with PHP/Python, and now he is mainly engaged in front-end web development. After doing front-end development for a while, I found that development efficiency and functional reusability are the two core pain points of our front-end programming. So the author has been thinking about how to solve these two major pain points, and then strive to get rid of 996 as soon as possible, win Bai Fumei, and go to the peak of life (hehehe~). Welcome to discuss with me like-minded people, add the author's WeChat whitney1289 .

imwty
1.1k 声望99 粉丝

Enjoy creating rather than coding!