添加:增强型搜索框插件

This commit is contained in:
xugaoyi 2020-02-27 16:49:35 +08:00
parent 02faeb06a0
commit a35822f473
7 changed files with 343 additions and 6 deletions

5
.gitignore vendored
View File

@ -9,7 +9,4 @@ node_modules
docs/.vuepress/dist
# 百度链接推送
urls.txt
#其他
SearchBox.vue
urls.txt

View File

@ -36,10 +36,13 @@ module.exports = {
plugins: [ // 插件
require('./plugins/love-me'), // 鼠标点击爱心特效
require('./plugins/title-badge'), // h1标题徽章
require('./plugins/enhanced-search'), // 增强型搜索框
'vuepress-plugin-baidu-autopush', // 百度自动推送,作用:加快将页面推送给百度搜索
'@vuepress/back-to-top', // 返回顶部
// ['@vuepress/search', {
// ['@vuepress/search', { `
// searchMaxSuggestions: 10
// }],

View File

@ -0,0 +1,304 @@
<template>
<div class="search-box">
<input
@input="query = $event.target.value"
aria-label="Search"
:value="query"
:class="{ 'focused': focused }"
:placeholder="placeholder"
autocomplete="off"
spellcheck="false"
@focus="focused = true"
@blur="focused = false"
@keyup.enter="go(focusIndex)"
@keyup.up="onUp"
@keyup.down="onDown"
ref="input"
>
<ul
class="suggestions"
v-if="showSuggestions"
:class="{ 'align-right': alignRight }"
@mouseleave="unfocus"
>
<li
class="suggestion"
v-for="(s, i) in suggestions"
:class="{ focused: i === focusIndex }"
@mousedown="go(i)"
@mouseenter="focus(i)"
>
<a :href="s.path" @click.prevent>
<span class="page-title">{{ s.title || s.path }}</span>
<span v-if="s.header" class="header">&gt; {{ s.header.title }}</span>
</a>
</li>
<li
class="suggestion"
@mousedown="goMDN()"
>
<a @click.prevent>在MDN中搜索"{{query}}"</a>
</li>
<li
class="suggestion"
@mousedown="goRunoob()"
>
<a @click.prevent>在Runoob中搜索"{{query}}"</a>
</li>
</ul>
</div>
</template>
<script>
/* global SEARCH_MAX_SUGGESTIONS, SEARCH_PATHS, SEARCH_HOTKEYS */
export default {
data () {
return {
query: '',
focused: false,
focusIndex: 0,
placeholder: undefined
}
},
mounted () {
this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
document.addEventListener('keydown', this.onHotkey)
},
beforeDestroy () {
document.removeEventListener('keydown', this.onHotkey)
},
computed: {
showSuggestions () {
return (
this.focused
&& this.suggestions
// && this.suggestions.length
)
},
suggestions () {
const query = this.query.trim().toLowerCase()
if (!query) {
return
}
const { pages } = this.$site
const max = this.$site.themeConfig.searchMaxSuggestions || SEARCH_MAX_SUGGESTIONS
const localePath = this.$localePath
const matches = item => (
item
&& item.title
&& item.title.toLowerCase().indexOf(query) > -1
)
const res = []
for (let i = 0; i < pages.length; i++) {
if (res.length >= max) break
const p = pages[i]
// filter out results that do not match current locale
if (this.getPageLocalePath(p) !== localePath) {
continue
}
// filter out results that do not match searchable paths
if (!this.isSearchable(p)) {
continue
}
if (matches(p)) {
res.push(p)
} else if (p.headers) {
for (let j = 0; j < p.headers.length; j++) {
if (res.length >= max) break
const h = p.headers[j]
if (matches(h)) {
res.push(Object.assign({}, p, {
path: p.path + '#' + h.slug,
header: h
}))
}
}
}
}
return res
},
// make suggestions align right when there are not enough items
alignRight () {
const navCount = (this.$site.themeConfig.nav || []).length
const repo = this.$site.repo ? 1 : 0
return navCount + repo <= 2
}
},
methods: {
getPageLocalePath (page) {
for (const localePath in this.$site.locales || {}) {
if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
return localePath
}
}
return '/'
},
isSearchable (page) {
let searchPaths = SEARCH_PATHS
// all paths searchables
if (searchPaths === null) { return true }
searchPaths = Array.isArray(searchPaths) ? searchPaths : new Array(searchPaths)
return searchPaths.filter(path => {
return page.path.match(path)
}).length > 0
},
onHotkey (event) {
if (event.srcElement === document.body && SEARCH_HOTKEYS.includes(event.key)) {
this.$refs.input.focus()
event.preventDefault()
}
},
onUp () {
if (this.showSuggestions) {
if (this.focusIndex > 0) {
this.focusIndex--
} else {
this.focusIndex = this.suggestions.length - 1
}
}
},
onDown () {
if (this.showSuggestions) {
if (this.focusIndex < this.suggestions.length - 1) {
this.focusIndex++
} else {
this.focusIndex = 0
}
}
},
go (i) {
if (!this.showSuggestions) {
return
}
this.$router.push(this.suggestions[i].path)
this.query = ''
this.focusIndex = 0
},
goMDN(){
window.open('https://developer.mozilla.org/zh-CN/search?q=' + this.query, '_blank')
},
goRunoob(){
window.open('https://www.runoob.com/?s=' + this.query, '_blank')
},
focus (i) {
this.focusIndex = i
},
unfocus () {
this.focusIndex = -1
}
}
}
</script>
<style lang="stylus">
.search-box
display inline-block
position relative
margin-right 1rem
input
cursor text
width 10rem
height: 2rem
color lighten($textColor, 25%)
display inline-block
border 1px solid darken($borderColor, 10%)
border-radius 2rem
font-size 0.9rem
line-height 2rem
padding 0 0.5rem 0 2rem
outline none
transition all .2s ease
background #fff url(search.svg) 0.6rem 0.5rem no-repeat
background-size 1rem
&:focus
cursor auto
border-color $accentColor
.suggestions
background #fff
width 20rem
position absolute
top 1.5rem
border 1px solid darken($borderColor, 10%)
border-radius 6px
padding 0.4rem
list-style-type none
&.align-right
right 0
.suggestion
line-height 1.4
padding 0.4rem 0.6rem
border-radius 4px
cursor pointer
a
white-space normal
color lighten($textColor, 35%)
.page-title
font-weight 600
.header
font-size 0.9em
margin-left 0.25em
&:hover
background-color #f3f4f5
&.focused
background-color #f3f4f5
a
color $accentColor
@media (max-width: $MQNarrow)
.search-box
input
cursor pointer
width 0
border-color transparent
position relative
&:focus
cursor text
left 0
width 10rem
// Match IE11
@media all and (-ms-high-contrast: none)
.search-box input
height 2rem
@media (max-width: $MQNarrow) and (min-width: $MQMobile)
.search-box
.suggestions
left 0
@media (max-width: $MQMobile)
.search-box
margin-right 0
input
left 1rem
.suggestions
right 0
@media (max-width: $MQMobileNarrow)
.search-box
.suggestions
width calc(100vw - 4rem)
input:focus
width 8rem
</style>

View File

@ -0,0 +1,18 @@
# Enhanced-search
此插件`Enhanced-search` 是基于官方的搜索框插件 [@vuepress/plugin-search](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-search) 做了功能添加,添加的功能如下:
* 在搜索结果最底部添加了 `在MDN中搜索'xxx'``在Runoob中搜索'xxx'` 选项。
### 使用
在`config.js`的`plugins`选项添加插件:
```js
require('./plugins/enhanced-search')
```
此插件会覆盖原本的 `plugin-search` 插件,但参数选项和 `plugin-search` 插件完全一致。

View File

@ -0,0 +1,14 @@
const { path } = require('@vuepress/shared-utils')
module.exports = (options) => ({
alias: {
'@SearchBox':
path.resolve(__dirname, 'EnhancedSearchBox.vue')
},
define: {
SEARCH_MAX_SUGGESTIONS: options.searchMaxSuggestions || 5,
SEARCH_PATHS: options.test || null,
SEARCH_HOTKEYS: options.searchHotkeys || ['s', '/']
}
})

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -105,7 +105,7 @@ permalink: /pages/bd1af2f75fd361fc
3. 最后在vue模板中使用即可
```js
axios.get('/api/test.json')
axios.get('/api/test.json') // 注意这里需要.json后缀
.then(function(res){
console.log(res);
})