文章目录
封装Search组件搜索框
App.vue
<template>
<div>
<!-- 搜索页面 -->
<!-- 搜索框 插槽 -->
<search shape="round" :clearable="true">
<template v-slot:button>
<h1>搜索</h1>
</template>
</search>
<!-- 搜索记录 -->
<!-- 智能提示 -->
</div>
</template>
<script>
import Search from './views/Search.vue'
export default {
components: {
Search
}
}
</script>
<style>
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => {
return h(App)
}
}).$mount('#app')
Search.vue
<template>
<div class="search-body">
<!-- 搜索输入框 -->
<div class="search-input-body">
<input type="text" v-model="kw" class="search-input-el" :style="{borderRadius: rarius}">
<span class="clear-btn" @click="clearKw" v-show="kw.length > 0 && clearable">×</span>
</div>
<!-- 提交按钮 -->
<button>搜索</button>
<slot name="button"></slot>
</div>
</template>
<script>
export default {
props: {
shape: {
type: String,
default: 'square',
validator: function(val){
return ['square','round'].includes(val)
}
},
clearable: {
type: Boolean,
default: true
}
},
data(){
return {
// rarius: '' //设置当前搜索框的形状
kw: '' ,//搜索关键字
}
},
watch: {
kw(val,oldVal){
if(val.length > 20){
this.kw = oldVal
}
}
},
computed: {
rarius(){
let val
if(this.shape === 'round'){
val = '20px'
}else if(this.shape === 'square'){
val = '0'
}
return val
}
},
methods: {
clearKw(){
this.kw = ''
}
}
}
</script>
<style scoped>
.search-body{
display: flex;
}
.search-input-body{
/* border: 1px solid #000; */
width: 200px;
height: 30px;
line-height: 30px;
position: relative;
margin-right: 10px;
}
.search-input-el{
width: 200px;
height: 30px;
text-indent: 10px;
border: 0;
outline: none;
background-color: #eee;
/* border-radius: 20px; */
}
.clear-btn{
position: absolute;
top: 0px;
right: 10px;
cursor: pointer;
}
</style>
router 里的 index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
store 里的 index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
封装Tag组件并保持搜索记录
App.vue
<template>
<div>
<!-- 搜索页面 -->
<!-- 搜索框 插槽 -->
<!-- 搜索记录 -->
<div class="history-body">
<div class="history-top">
<span>搜索记录</span>
<span class="iconfont icon-shanchu1" @click="clearHistory"></span>
</div>
<div class="history-list">
<tag v-for="(item,index) in historyList" :key="index" :text="item"></tag>
</div>
</div>
<!-- 智能提示 -->
</div>
</template>
<script>
import Tag from './views/Tag.vue'
export default {
components: {
Tag,
},
data(){
return {
historyList: [],
}
},
watch: {
historyList(list){
localStorage.historyList = JSON.stringify(list)
}
},
created(){
let list = localStorage.historyList
if(list){
this.historyList = JSON.parse(list)
}
},
methods: {
search(val){ //在搜索上的回车事件
//搜索
console.log('搜索:', val)
//保存记录
let index = this.historyList.indexOf(val)
// if(index == -1){
// this.historyList.unshift(val)
// }else{
// this.historyList.splice(index,1)
// this.historyList.unshift(val)
// }
if(index != -1){
this.historyList.splice(index,1)
}
this.historyList.unshift(val)
// this.historyList.push(val)
},
clearHistory(){
let rel = confirm('确定要清空吗?')
if(!rel) return
this.historyList = []
}
}
}
</script>
<style scoped>
.history-top{
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
width: 300px;
margin: 30px 0px;
}
.iconfont{
color: #888;
font-size: 14px;
cursor: pointer;
}
.iconfont:hover{
color: red;
}
</style>
Tag.vue
<template>
<span class="tag" :style="{color}">
{{text}}
</span>
</template>
<script>
export default {
props: {
text: String,
color: String
}
}
</script>
<style scoped>
.tag{
background-color: #ccc;
color: #333;
padding: 3px 10px;
font-size: 14px;
margin: 10px;
border-radius: 5px;
}
</style>
封装Cell组件
App.vue
<template>
<div>
<!-- 搜索页面 -->
<!-- 搜索框 插槽 -->
<!-- 搜索记录 -->
<!-- 智能提示 -->
<div class="message-list" v-show="kwVal.length > 0">
<cell title="男装" text="200" @click="search"></cell>
</div>
</div>
</div>
</template>
<script>
import Cell from './views/Cell.vue'
export default {
components: {
Cell,
},
data(){
return {
kwVal: '',
}
},
methods: {
searchInput(val){
this.kwVal = val
},
}
}
</script>
<style scoped>
.message-list{
width: 200px;
height: 500px;
border: 1px solid #bbb;
position: absolute;
top: 40px;
background-color: #fff;
}
</style>
Cell.vue
<template>
<div class="cell-body" @click="handleClick">
<span class="title">{{title}}</span>
<tag :text="text"></tag>
</div>
</template>
<script>
import Tag from './Tag.vue'
export default {
props: ['title','text'],
components: {
Tag
},
methods: {
handleClick(){
this.$emit('click',this.title)
}
}
}
</script>
<style scoped>
.cell-body{
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0px 10px;
height: 40px;
border-bottom: 1px solid #eee;
}
.title{
font-size: 14px;
}
</style>
axios搜索接口调用
App.vue
<template>
<div>
<!-- 搜索页面 -->
<!-- 搜索框 插槽 -->
<!-- 搜索记录 -->
<!-- 智能提示 -->
</div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data(){
return {
guess: [] ,//搜索联想词
}
},
watch: {
kwVal(val){
if(val.trim() === '') return
axios.get('http://api.web1024.cn/taobao/guess',{
params: {
key: '',
kw: val
}
}).then(res=>{
// console.log(res.data.data)
this.guess = res.data.data
})
}
},
}
}
</script>
<style scoped>
</style>
参考文件 目录
参考文件 目录
— — assets
— — components
— — router
— — index.js
— — store
— — index.js
— — views
— — Cell.vue
— — Search.vue
— — Tag.vue
— — App.vue
— — main.js
整合
— — router — — index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
— — store — — index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
— — views — — Cell.vue
<template>
<div class="cell-body" @click="handleClick">
<span class="title">{{title}}</span>
<tag :text="text"></tag>
</div>
</template>
<script>
import Tag from './Tag.vue'
export default {
props: {
title: String,
text: [String,Number]
},
components: {
Tag
},
methods: {
handleClick(){
this.$emit('click',this.title)
}
}
}
</script>
<style scoped>
.cell-body{
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0px 10px;
height: 40px;
border-bottom: 1px solid #eee;
}
.title{
font-size: 14px;
}
</style>
— — views — — Search.vue
<template>
<div class="search-body">
<!-- 搜索输入框 -->
<div class="search-input-body">
<input type="text" v-model="kw" class="search-input-el" @input="handleInput" @keypress.enter="handlePress" :style="{borderRadius: rarius}">
<span class="clear-btn" @click="clearKw" v-show="kw.length > 0 && clearable">×</span>
</div>
<!-- 提交按钮 -->
<!-- <button>搜索</button> -->
<slot name="button"></slot>
</div>
</template>
<script>
export default {
props: {
shape: {
type: String,
default: 'square',
validator: function(val){
return ['square','round'].includes(val)
}
},
clearable: {
type: Boolean,
default: true
},
// value: String
},
data(){
return {
// rarius: '' //设置当前搜索框的形状
kw: '' ,//搜索关键字
}
},
watch: {
kw(val,oldVal){
if(val.length > 20){
this.kw = oldVal
}
}
},
computed: {
rarius(){
let val
if(this.shape === 'round'){
val = '20px'
}else if(this.shape === 'square'){
val = '0px'
}
return val
}
},
methods: {
clearKw(){ //点击清空按钮事件
this.kw = ''
this.$emit('input',this.kw)
},
handlePress(){ //输入框的回车事件
this.$emit('enter',this.kw)
},
handleInput(){
this.$emit('input',this.kw)
}
}
}
</script>
<style scoped>
.search-body{
display: flex;
}
.search-input-body{
/* border: 1px solid #000; */
width: 200px;
height: 30px;
line-height: 30px;
position: relative;
margin-right: 10px;
}
.search-input-el{
width: 200px;
height: 30px;
text-indent: 10px;
border: 0;
outline: none;
background-color: #eee;
/* border-radius: 20px; */
}
.clear-btn{
position: absolute;
top: 0px;
right: 10px;
cursor: pointer;
}
</style>
— — views — — Tag.vue
<template>
<span class="tag" :style="{color}">
{{text}}
</span>
</template>
<script>
export default {
props: {
text: String,
color: String
}
}
</script>
<style scoped>
.tag{
background-color: #ccc;
color: #333;
padding: 3px 10px;
font-size: 12px;
margin: 10px;
border-radius: 5px;
}
</style>
— — App.vue
<template>
<div>
<!-- 搜索页面 -->
<!-- 搜索框 插槽 -->
<search shape="round" :clearable="true" @enter="search" @input="searchInput">
<template v-slot:button>
<button>搜索</button>
</template>
</search>
<!-- 搜索记录 -->
<div class="history-body">
<div class="history-top">
<span>搜索记录</span>
<span class="iconfont icon-shanchu1" @click="clearHistory"></span>
</div>
<div class="history-list">
<tag v-for="(item,index) in historyList" :key="index" :text="item"></tag>
</div>
</div>
<!-- 智能提示 -->
<div class="message-list" v-show="kwVal.length > 0">
<cell v-for="(item,index) in guess" :key="index" :title="item.kw" :text="item.total" @click="search"></cell>
</div>
</div>
</template>
<script>
import Search from './views/Search.vue'
import Tag from './views/Tag.vue'
import Cell from './views/Cell.vue'
import axios from 'axios'
export default {
components: {
Search,
Tag,
Cell
},
data(){
return {
historyList: [],
kwVal: '',
guess: [] //搜索联想词
}
},
watch: {
historyList(list){
localStorage.historyList = JSON.stringify(list)
},
kwVal(val){
if(val.trim() === '') return
axios.get('http://api.web1024.cn/taobao/guess',{
params: {
key: '',
kw: val
}
}).then(res=>{
// console.log(res.data.data)
this.guess = res.data.data
})
}
},
created(){
let list = localStorage.historyList
if(list){
this.historyList = JSON.parse(list)
}
},
methods: {
search(val){ //在搜索上的回车事件
console.log(this.kwVal)
//搜索
console.log('搜索:', val)
//保存记录
let index = this.historyList.indexOf(val)
// if(index == -1){
// this.historyList.unshift(val)
// }else{
// this.historyList.splice(index,1)
// this.historyList.unshift(val)
// }
if(index != -1){
this.historyList.splice(index,1)
}
this.historyList.unshift(val)
// this.historyList.push(val)
},
clearHistory(){
let rel = confirm('确定要清空吗?')
if(!rel) return
this.historyList = []
},
searchInput(val){
this.kwVal = val
}
}
}
</script>
<style scoped>
.history-top{
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
width: 300px;
margin: 30px 0px;
}
.iconfont{
color: #888;
font-size: 14px;
cursor: pointer;
}
.iconfont:hover{
color: red;
}
.message-list{
width: 200px;
/* height: 500px; */
border: 1px solid #bbb;
position: absolute;
top: 40px;
background-color: #fff;
}
</style>
— — main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => {
return h(App)
}
}).$mount('#app')