添加:增强型搜索框插件
This commit is contained in:
parent
02faeb06a0
commit
a35822f473
|
|
@ -9,7 +9,4 @@ node_modules
|
|||
docs/.vuepress/dist
|
||||
|
||||
# 百度链接推送
|
||||
urls.txt
|
||||
|
||||
#其他
|
||||
SearchBox.vue
|
||||
urls.txt
|
||||
|
|
@ -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
|
||||
// }],
|
||||
|
||||
|
|
|
|||
|
|
@ -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">> {{ 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>
|
||||
|
|
@ -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` 插件完全一致。
|
||||
|
||||
|
|
@ -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', '/']
|
||||
}
|
||||
})
|
||||
|
|
@ -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 |
|
|
@ -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);
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue