基于Vue的淘宝首页跳转商品搜索页的最佳实现方式总结(包括v-model组件间使用技巧总结)
今天在练习淘宝项目的时候,做到一个最为常见的功能,就是从主页搜索框搜索内容,点击搜索后能跳转到详细商品页面,同时用户也能在该页面重新搜索,不必返回主页面再搜,大致意思看下图。其实这个功能很多都有,比如百度,我们搜索后进入词条内部,其上面依然有搜索框可以重新搜索。以前没注意这个,今天注意了特来总结下以免忘记。其实这里面包含两点需要注意的(①v-model组件间使用技巧,②子组件不能直接在内部改变父组件传递过来的参数)。
目录
1.功能需求
淘宝主页搜索内容a,之后跳转到商品搜索页
通过路由参数将搜索内容展示在商品搜索页中(到这里都是很普通的操作)
在商品搜索页中重新输入内容(模拟用户想看别的搜索的情况),这时候地址栏参数也应该跟着变,进行重新搜索。看的不难,也是正常操作。但是我在弄得时候着实让我花了点时间转弯,可能原因还是v-model组件间使用以及computed使用生疏导致的吧。通过这两个的使用及技巧就可以很简单清晰的实现如下功能。下面我将详细说明每一步。
2. 目录结构
3.详细说明
3.1路由表
主页面就是/,商品搜搜页就是/search其中kw就是要求主页跳转过来时必须要带的参数,也就是用户输入的搜索内容
let router=new Router({
routes:[
{path:'/',name:'home',component:home},
{path:'/login',name:'login',component:login},
{path:'/reg',name:'reg',component:reg},
{path:'/search/:kw',name:'search',component:search}
]
});
3.2主页搜索
在主界面用户进行搜索,将搜索内容以参数形式$router.push到商品搜索页中
<!--主页搜索的按钮部分html-->
<div class="search-kw-container fl">
<input type="text" class="search-kw" @keydown.enter="btnFind(kw)" v-model="kw">
</div>
//在主页methods中的搜索方法
btnFind(kwContent){
if(!kwContent){
return;
}
else{
//console.log('搜索内容',kwContent);
//路由跳转并传递参数
this.$router.push({
name:'search',
params:{
kw:kwContent
}
});
}
}
3.3商品搜索页
用computed里面得get接收路由param参数,在set中对header组件传递过来新数据进行路由重定向
该页要接收主页通过路由传递的参数。问题是用数据接收好呢?还是用computed计算属性好呢?其实无论使用什么方式功能都能实现,但是如果你要力求简洁清晰那么还是要使用computed计算属性,因为这里面的set函数可以帮助我们在接收到新的参数时重新定向路由。试想用户此时在商品搜索页重新输入内容,那么在computed得set中重新$router.push就可以了;如果你设计得是数据接收参数,那么很容易导致数据得混乱。
在商品搜索index页中this.$route.params获取路由参数并返回。
//监听属性 类似于data概念
computed: {
myKw:{
get(){
//从搜索框中取kw参数
let {kw}=this.$route.params;
return kw
},
set(val){
//路由跳转传递kw参数
//直接给路由地址栏加内容最好方便操作,比操作数据方便
this.$router.push({
name:'search',
params:{
kw:val
}
});
}
}
},
将商品搜索页获取到的用户输入参数myKw传递给myheader组件。
注意:
v-model = :value=' 变量1 ' + @input=' 变量1=$event.target.value '
<!-- 搜索详情页 -->
<template>
<div class="page">
<!-- 搜索头 -->
<myHeader v-model="myKw"></myHeader>
<!-- fix搜索头 -->
<myFixHeader></myFixHeader>
<!-- sortbar -->
<mySortbar></mySortbar>
<!-- myGoodList -->
<myGoodList></myGoodList>
<!-- ad-list广告 -->
<myAdList></myAdList>
</div>
</template>
3.4myheader组件页
在myheader组件中接收传入的myKw参数
props接收的参数是value,因为v-model = :value + @input
接收到数据后重新赋值给myheader组件中的变量,这样在myheader中的搜索框就可以使用v-model双向绑定了,如果不这样,你直接双向绑定获取的value,到时候用户重新输入内容时就会出现子组件更改父组件数据的情况,极不安全,这就是为你的项目在埋雷。
//import引入的组件需要注入到对象中才能使用
props:['value'],
components: {},
data() {
//这里存放数据
return {
inputTxt:this.value
};
},
myheader页的HTML中双向绑定的就是自身的变量inputTxt。
<!-- 详细搜索页搜索头 -->
<template>
<div class='searchHeader'>
<header>
<a href="javascript:;" class="logo fl">logo</a>
<div class="search-container fr clearfix">
<input
type="text"
class="search-input fl"
placeholder="请输入要搜索的词"
v-model="inputTxt"
@keydown.enter="btnSearch"
/>
<button type="button" class="search-btn fr" @click="btnSearch">搜 索</button>
</div>
</header>
</div>
</template>
点击搜索进行搜索,将用户更改后的数据重新扔给父级即商品搜索页index。
this.$emit里名字不能变,一定要是input,因为我们在商品搜索index页中给header组件传递参数时候用的是v-model,【v-model = :value + @input】切记!!!!
//方法集合
methods: {
btnSearch(){
//console.log('this.inputTxt',this.inputTxt);
this.$emit('input',this.inputTxt);
}
},
在商品搜索index页中的computed的set函数里(看3.3中computed)进行路由重定向就可以完美实现这个需求了。
注:
因为路由地址本身没有任何变化,所以浏览器会提示路由重复定向的警告,具体解决办法看我的这篇文章:https://blog.csdn.net/qq_42539194/article/details/112759315
3.5myheader页的另一种写法便于理解
在myheader页中将v-model拆开成:value和@input的写法更为清楚,但是@input="$emit('input',inputTxt)"向外emit的名字input还是不能变。这么写的问题在于用户只要在搜索框写内容,就会马上触发。这和正常需求不相符合。
<!-- 详细搜索页搜索头 -->
<template>
<div class='searchHeader'>
<header>
<a href="javascript:;" class="logo fl">logo</a>
<div class="search-container fr clearfix">
<input
type="text"
class="search-input fl"
placeholder="请输入要搜索的词"
:value="inputTxt"
@input="$emit('input',inputTxt)"
/>
<button type="button" class="search-btn fr" >搜 索</button>
</div>
</header>
</div>
</template>
演变过程:
1)在input中将@input="$emit('input',inputTxt)"去掉。
<!-- 详细搜索页搜索头 -->
<template>
<div class='searchHeader'>
<header>
<a href="javascript:;" class="logo fl">logo</a>
<div class="search-container fr clearfix">
<input
type="text"
class="search-input fl"
placeholder="请输入要搜索的词"
:value="inputTxt"
/>
<button type="button" class="search-btn fr" >搜 索</button>
</div>
</header>
</div>
</template>
2)将@input="$emit('input',inputTxt)"写到button点击事件里。
<template>
<div class='searchHeader'>
<header>
<a href="javascript:;" class="logo fl">logo</a>
<div class="search-container fr clearfix">
<input
type="text"
class="search-input fl"
placeholder="请输入要搜索的词"
:value="inputTxt"
/>
<button type="button" class="search-btn fr" @click="$emit('input',inputTxt)">搜 索</button>
</div>
</header>
</div>
</template>
3)将input中的:value直接换成双向绑定v-model就可以了。
<!-- 详细搜索页搜索头 -->
<template>
<div class='searchHeader'>
<header>
<a href="javascript:;" class="logo fl">logo</a>
<div class="search-container fr clearfix">
<input
type="text"
class="search-input fl"
placeholder="请输入要搜索的词"
v-model="inputTxt"
/>
<button type="button" class="search-btn fr" @click="$emit('input',inputTxt)">搜 索</button>
</div>
</header>
</div>
</template>
总结:
相信看到这里的同学就应该对类似于淘宝首页跳转商品搜索页的最佳实现方式有了清晰的认识,对computed的使用,v-model的使用演变以及路由重复加载解决办法有了进一步了解。当然我写的还是针对我目前遇到的问题的总结,所以肯定会有不足之处。欢迎同学在评论区进行补充留言。
相关文章
- 【转】vue.js表单校验详解
- Vue一次性多个请求数据
- Vue Class 与 Style 绑定
- 【前端VUE】大文件分片上传技术资料搜集
- 01-路由跳转 安装less this.$router.replace(path) 解决vue/cli3.0语法报错问题
- vue配置对象
- Vue + TypeScript + Element 项目实践(简洁时尚博客网站)及踩坑记(中)
- 使用.NET Core和Vue搭建WebSocket聊天室
- Vue技术12.6总结Vue数据监测
- Vue基础案例(水果搜索,购物车,todolist,留言板,跑马灯)
- vue系列:vue使用腾讯云播放器TCPlayer踩坑cannot read propeerty ‘nodeName‘of null
- 场景类:vue实现简单的搜索
- vue实现搜索、提交等功能【回车事件】
- Vue 生命周期(二) 和 如何打印出来HTMLDivElement
- 【Vue 开发实战】实战篇 # 29:如何设计一个高扩展性的路由
- Vue实战篇(Vue仿今日头条)
- vue-mixins使用注意事项和高级用法
- Vue 2.0 华丽的音乐搜索播放 Demo