Step by step, I will teach you to use Vue.js+Vuex to create an app that collects WeChat public numbers.

  javascript, node.js, vue.js, vuex, webpack

Only look not to praise, or only collect not to praise is to play rascal, don’t go after school, I find my brother to pick up you.

Project address:



Download & Run

git clone
 cd wechat-subscriptor && npm install
 npm run dev   // run in dev mode
 cd backend-server && node crawler.js   // turn on the crawler server
 open `localhost:8080` in your broswer and enjoy it.

Project introduction

I have paid close attention to many public numbers on WeChat and often browse the contents. However, when I read articles, I was always interrupted by various WeChat messages, so I had to cut them out, reply to the messages, and then click back to the public number all the way to reopen the articles. The cycle was endless and annoying. Later, it occurred to me that WeChat has cooperation with sogou and can directly search for public numbers through sogou. So why not use this resource to make an application dedicated to collecting public numbers? This application can easily search the public number, then store it, and open it directly when you want to see it. Well, in fact, it is not difficult, so we should start from the architecture.

Overall structure

International practice, first look at the architecture diagram:


Then there is the technical selection:

  1. The API of sogou is used as the interface for inquiring public numbers.

  2. Due to cross-domain problems, it was passednodeCrawler interface

  3. UsevueTo develop,vuexState management

  4. UsemuiAs a UI framework, it is convenient to package into mobile phone app in the future.

  5. Usevue-cliInitialize the project and passwebpackBuild

First of all, analyze the red circlevuexPart of it. It is the core of the whole APP and the processing center of all data.

All components of the client are in theactionTo complete the processing of incoming data (such as asynchronous requests, etc.), and then pass through theactionTriggermutationModifystate, followed bystateaftergetterIt is distributed to all components to meet the characteristics of “single data stream” and also conform to the officially recommended practices:


After understanding the most important thingvuexAfter that, the rest of the story will come out smoothly. Arrows indicate the flow of data.LocalStorageThe node server is responsible for storing the contents of favorites so that the contents will not be lost when the application is opened next time. The node server is responsible for crawling the data provided by the sogou API according to the keywords.

Is it very simple? Let’s start coding together!

Initialization item

npm install vue-cli -gInstall the latest version ofvue-cli, and thenvue init webpack wechat-subscriptorAfter setting up and installing the dependency package step by step according to the prompts, enter the directory of the project and make minor changes. The final directory structure is as follows:


Please browse the specific contents directly.Projects

Server & Crawler

Enter/backend-serverFolder and create a new one namedcrawler-server.jsThe code is as follows:

/*** crawler-server.js ***/
 'use strict'
 const http = require('http')
 const url = require('url')
 const util = require('util')
 const superagent = require('superagent')
 const cheerio = require('cheerio')
 const onRequest = (req, res) => {
 // CORS options
 res.writeHead(200, {'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': '*'})
 let keyWord = encodeURI(url.parse(req.url, true).query.query)
 // recieve keyword from the client side and use it to make requests
 if (keyWord) {
 let resultArr = []
 superagent.get('  type=1&query=' + keyWord + '&ie=utf8&_sug_=n&_sug_type_=').end((err, response) => {
 if (err) console.log(err)
 let $ = cheerio.load(response.text)
 $('.mt7 .wx-rb').each((index, item) => {
 // define an object and update it
 // then push to the result array
 let resultObj = {
 title: '',
 wxNum: '',
 link: '',
 pic: '',
 resultObj.title = $(item).find('h3').text()
 resultObj.wxNum = $(item).find('label').text() = $(item).attr('href')
 resultObj.pic = $(item).find('img').attr('src')
 http.createServer(onRequest).listen(process.env.PORT || 8090)
 console.log('Server Start!'  )

A simple crawler that sends requests to sogou through keywords provided by the client and then uses themcheerioAnalyze and obtain key information. The address of the sogou Public Number search is posted here. You can try it yourself:

When the server is turned on, just bring the parameter requestlocalhost:8090You can get the content.

UseVuexState management

Post it firstvuexOfficial documents:, believe me, don’t read the Chinese version, or you will step on the pit, the English version is enough.

As can be seen from the previous architecture diagram, all data flows are throughvuexYes, I learned about it from the above documents.vuexAfter the usage of, we enter/vuexFolder to build the corestore.jsCode:

/*** store.js ***/
 import Vue from 'vue'
 import Vuex from 'vuex'
 const state = {
 collectItems: [],
 searchResult: {}
 state.collectItems = localStorage.getItem("collectItems").split(','):
 const mutations = {
 SET_RESULT (state, result) {
 state.searchResult = result
 COLLECT_IT (state, name) {
 localStorage.setItem("collectItems", state.collectItems)
 DELETE_COLLECTION (state, name) {
 state.collectItems.splice(state.collectItems.indexOf(name), 1)
 localStorage.setItem("collectItems", state.collectItems)
 export default new Vuex.Store({

Below we will focus on the analysis of the code.

First we define astateObject, the two attributes in which correspond to favorite content and search results. In other words, the entire APP data is stored instateObject, take as you like.

Next, we define anothermutationsObject. We can putmutationsTo be understood as “for changestateA series of methods of state “. InvuexIn the concept of “human rights and fundamental freedoms”,stateOnly throughmutationThe advantage of modification is that it can manage the application status more intuitively and clearly, instead of throwing data everywhere.

It is not difficult to see through the code, threemutationThe role of respectively is:

  • SET_RESULT: Store search results instate

  • COLLECT_IT: Add to Favorite Actions (Includinglocalstorage)

  • DELETE_IT: Remove from Favorites (includinglocalstorage)

Component data processing

Our APP has two components.SearchBar.vueAndSearchResult.vue, respectively corresponding to the search part component and the result part component. The search component contains favorites, so it can also be understood as having three parts.

Search for some componentsSearchBar.vue

/*** SearchBar.vue ***/
 vuex: {
 getters: {
 collectItem(state) {
 return state.collectItems
 actions: {
 deleteCollection: ({ dispatch }, name) => {
 dispatch('DELETE_COLLECTION', name)
 searchFun: ({ dispatch }, keyword) => {
 $.get('http://localhost:8090', { query: keyword }, (data) => {
 dispatch('SET_RESULT', JSON.parse(data))

The code is a bit long, so I will only focus on it here.vuexPart, complete code can refer toProjects.

  • gettersObtainstoreThe data are used for components.

  • actionsThe two methods of are responsible for distributing data tostoreChinese supplymutationUse

Look at the official example, in the component toactionIt seems that it is very complicated to pass the argument, but in fact it can be completely passed.methodsTo process parameters, in the triggeractionsAt the same time pass in the parameters.

Results partial componentSearchResult.vue

/*** SearchResult.vue ***/
 vuex: {
 getters: {
 wordValue(state) {
 return state.keyword
 collectItems(state) {
 return state.collectItems
 searchResult(state) {
 return state.searchResult
 actions: {
 collectIt: ({ dispatch }, name, collectArr) => {
 for(let item of collectArr) {
 if(item == name) return false
 dispatch('COLLECT_IT', name)

The result part mainly lies in the demonstration and needs to be triggered.actionThe only place for this is to add it to favorites. It should be noted that repeated additions should be avoided, so thefor...ofLoops are not added when the current element already exists in the array.

The end

After analyzing the code of the key logic part, this APP is the same thing. The UI part will not go into details. Just look at the source code of the project or DIY yourself. As for packaging into APP, first you need to download HBuilder, then you can package it directly through it and use it together.muiCan experience better effect, do not know why so many people black it.

The API provided by sogou is very powerful, but remind us not to operate too frequently, or your IP will be blocked by it, mine has been blocked …

WeexIt has already come out. It can be used to build Native applications. It is exciting to think about it. I will finish this project on a whim.WeexThe version of play …

Finally, thank you for reading. If you think my article is good, please pay attention to my column. See you next time!