History function
Objective: to realize the function of searching history
- Initialize history data
data () { return { // Search keywords q: '', // Historical keywords history: JSON.parse(localStorage.getItem('keywords') || '[]') } },
- The history is displayed only when there is data
<div class="history-box" v-else-if="history.length">
- Render history data
<van-cell v-for="(item, index) in history" :key="index"> <a class="word_btn">{{item}}</a> <van-icon @click="delHistory(key)" class="close_btn" slot="right-icon" name="cross"/> </van-cell>
Summary:
- Cache historical keywords after carriage return
- Enter the search component and directly read the cache when initializing the data
- Dynamic rendering history data
- Array de duplication operation
handleSearch () { // After the carriage return is triggered: 1. Save the historical keyword; 2. Jump to search list page this.history.unshift(this.q) // Set is a constructor introduced by ES6. The storage structure is similar to that of array, in which duplicate data is not allowed this.history = [...new Set(this.history)] // Put the history array into the cache localStorage.setItem('keywords', JSON.stringify(this.history)) }
Summary: it is convenient to provide Set constructor based on ES6 for de duplication
Note: Set is a constructor introduced by ES6. The storage structure is similar to that of array, in which duplicate data is not allowed
- Delete history
deleteSingle (index) { // Click the cross to delete the corresponding historical keyword this.history.splice(index, 1) // The cache should also be updated window.localStorage.setItem(SEARCHKEY, JSON.stringify(this.history)) },
- Clear history
<van-icon name="delete" @click="deleteAll"></van-icon>
deleteAll () { // Clear all historical keywords this.history = [] // The cache should also be emptied window.localStorage.removeItem('keywords') },
Note: two parts should be deleted when deleting: 1. Data in data; 2. Data in cache
Associative search function
Objective: to realize the association search function
- Encapsulated search interface method
export const searchList = (q) => { return request({ method: 'get', url: 'v1_0/suggestion', params: { q } }) }
<van-search @input='keywordList'
// Associative query async keywordList () { const ret = await searchList(this.q) this.keylist = ret.data.options },
Summary: enter a keyword and call the interface once to get the list data matching the keyword.
- Realize function anti shake effect debounce / throttle (throttling)
Function anti shake function: limit the frequency of task execution
If the trigger interval of this condition is less than a fixed time, the task will be triggered twice.
Trigger condition: enter a character
Specified time: 1 second
Task: call interface to send request
// Associative query keywordList () { // The following expression is function anti shake clearTimeout(this.timer) if (!this.q.trim()) return this.timer = setTimeout(async () => { const ret = await searchList(this.q) this.keylist = ret.data.options }, 1000) },
Summary:
- Function anti shake debounce: the task will not be executed until the trigger condition exceeds a specific time for two consecutive times. (keyword search, account repeatability verification)
- Function throttling: execute the task only once in a fixed time, no matter how many times the condition is triggered. (paging dynamic loading)
- Render search list results
<van-cell :key='index' v-for='(item, index) in keylist' icon="search"> <p v-html='item'></p> </van-cell>
Note: the v-html instruction is required to display the content
- Highlight control of association list
// Requirement: highlight the content of the list item after matching with the key (wrap a layer of span label) this.keylist = ret.data.options.map(item => { // const arr = [] // const arr = new Array() // const obj = {} // const obj = new Object() // const reg = /\d/ // const reg = new RegExp('\d') // The native js method replace is used to replace substrings in the entire string const reg = new RegExp(this.q, 'ig') return item.replace(reg, `<span>${this.q}</span>`) })
Summary: be familiar with the usage of regular expression based constructor and js replace method.
- Route jump is another way to pass parameters
Summary: when jumping to route through programmed navigation, you can go through the? After splicing the parameters to the routing path
this.$router.push('/sresult?kw=' + this.q) // Route mapping { path: '/sresult', component: Sresult }
How to get the parameters after the question mark inside the component? this.$route.query.kw
this.$router.push('/sresult/' + this.q) // Route mapping { path: '/sresult/:kw', component: Sresult }
The way to obtain this routing parameter inside the component: this$ route. params. kw
- Realize the jump of search page
- Jump after entering. The parameter is the entered keyword
// Implement search handleSearch () { // Prevent entering empty strings // q.trim() is a native js method used to remove the space '' on both sides if (!this.q.trim()) return // After the carriage return is triggered: 1. Save the historical keyword; 2. Jump to search list page this.history.unshift(this.q) // Set is a constructor introduced by ES6. The storage structure is similar to that of array, in which duplicate data is not allowed this.history = [...new Set(this.history)] // Put the history array into the cache window.localStorage.setItem('keywords', JSON.stringify(this.history)) // Jump to search list page // this.$router.push('/sresult?kw=' + this.q) // this.$router.push('/sresult/' + this.q) this.$router.push({ // path: 'sresult', name: 'myresult', query: { kw: this.q } }) }
Summary:
- There are many kinds of jumps in programming navigation usage
- The name attribute can be set in the routing map, and the programmed navigation can jump based on the name value
- Different parameter transfer methods have different attributes of query/params
- Click the list item of Lenovo to jump, and the parameter is the content of the list item
// Click Lenovo entry to jump handleJump (kw) { // kw now includes the highlighted label of span, which needs to be removed const reg = new RegExp(`<span>${this.q}</span>`, 'ig') kw = kw.replace(reg, this.q) this.$router.push({ name: 'myresult', query: { kw: kw } }) },
Summary: before clicking jump, the highlighted label of span needs to be removed from the parameters passed.
Search results - basic layout
Objective: to achieve the basic layout of the search list page
- Search list layout
<div class="container"> <!-- Navigation fixed positioning fixed --> <van-nav-bar fixed title="search result" left-arrow @click-left="$router.back()" /> <!-- Article list --> <van-list v-model="loading" :finished="finished" finished-text="No more"> <van-cell-group> <van-cell> <div class="article_item"> <h3 class="van-ellipsis">PullRefresh Pull down refresh PullRefresh Drop-down refresh drop-down refresh</h3> <div class="img_box"> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> <van-image class="w33" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> </div> <div class="img_box"> <van-image class="w100" fit="cover" src="https://img.yzcdn.cn/vant/cat.jpeg" /> </div> <div class="info_box"> <span>You are like a gust of wind</span> <span>8 comment</span> <span>10 Minutes ago</span> </div> </div> </van-cell> </van-cell-group> </van-list> </div>
- Search results list style
.container { padding-top: 92px; height: 100%; overflow-y: auto; box-sizing: border-box; } .article_item { h3 { font-weight: normal; line-height: 2; } .img_box { display: flex; justify-content: space-between; .w33 { width: 33%; height: 180px; } .w100 { height: 360px; width: 100%; } } .info_box { color: #999; line-height: 2; position: relative; span { padding-right: 20px; } } }
Search results - pull up function
Objective: to realize the search pull-up function
- Package pull-up loading interface
// Search the list of articles by keyword export const searchArticles = (options) => { return request({ method: 'get', url: 'v1_0/search', // axios uses params to pass get request parameters params: { // Current page number page: options.pagenum, // Number of entries per page per_page: options.pagesize, // Keywords for query q: options.kw } }) }
- List related data
data () { return { loading: false, finished: false, // Search parameters queryData: { page: 1, perPage: 10, // Initialize data through routing parameters q: this.$route.query.q }, // search result list: [], // Total list total: 0 } }, methods: { async searchArticles () { // Search article list results by keyword const [err, ret] = await searchArticles(this.queryData) if (err) { this.$toast.fail('Failed to query article') } else { // Get the list data and total number of articles this.list = ret.data.results this.total = ret.data.total_count } } },
- Trigger pull-up to load more actions
methods: { async onLoad () { // When the page is loaded, it is triggered once. If there is not enough screen, it is called again const ret = await searchArticles(this.queryData) this.list.push(...ret.data.results) this.total = ret.data.total_count // End this loading this.loading = false // Judge the status of loading completion if (this.list.length >= this.total) { // No more data to load this.finished = true } else { // There is more data to load: page number accumulation this.queryData.pagenum += 1 } } }, created () { // Get query keywords in routing parameters this.queryData.kw = this.$route.query.kw }
- Render list content
<van-cell v-for='item in list' :key='item.art_id.toString()'> <div class="article_item"> <h3 class="van-ellipsis">{{item.title}}</h3> <div class="img_box"> <van-image :key='index' v-for='(img, index) in item.cover.images' :class="[{w33: item.cover.type===3}, {w100: item.cover.type===1}]" fit="cover" :src="img" /> </div> <div class="info_box"> <span>{{item.aut_name}}</span> <span>{{item.comm_count}}comment</span> <span>{{item.pubdate|formatTime}}</span> </div> </div> </van-cell>
Summary:
- Paging logic based on pagenum and pagesize
- Basic use of van list component
- Usage of dynamic binding of class name
summary
- Historical keyword of cache search: local storage API
- Array de duplication: a new constructor Set introduced based on ES6
- Delete history Keywords: single delete and delete all (local storage API)
- Prevent entering null characters: the usage of trim method of native js
- Business process of function anti shake (※); Contrast function throttling
- Concept; Application scenarios; code implementation
- Basic functions of keyword matching: calling interface; Fill page
- Highlight control of list items: regular constructor usage (benefit: support variables) (※)
- Usage of route passing parameters (passing parameters based on question mark) (※)
- Program navigation route jump. Route mapping supports name, or jump with name (※)
- Note the parameter passed: query/params
- Usage of name
- Paging based on pagenum and pagesize parameters: time-based paging