原文链接:https://blog.csdn.net/qwezxc24680/article/details/74550556

从github上看到一个不错的开源项目:https://github.com/lavyun/vue-demo-search,

自己琢磨着不看代码做了一遍学习了不少,现将碰到的坑与填坑过程分享出来。

首先看一下demo的界面:

简单来说就是一个复刻各大搜索引擎的功能,用户输入关键字能出现搜索建议并上下键控制输入框内容。

同时点击上方logo能够切换不同引擎,点击搜一下能跳转到对应网站搜索结果。

首先分析一下页面,基本由2个部分组成:上方的LOGO部分和下方的输入框与搜索建议弹框。

由于篇幅关系,这次先分析logo部分的实现代码。

基于这次练习是针对Vue组件,所以我们可以将其拆分为logo组件和搜索组件,并将其设为父子组件方便初学,将来熟练以后可以考虑变为更常见的兄弟组件并使用event bus或者vuex来实现组件通信。

开发环境: Vue2.0、Node.js、npm、webpack、vue-cli、vue-resources、webstorm

为了以后项目工程化的目标,所以我们使用node+npm+webpack来构建项目。

准备工作包括安装node,npm,然后依次安装webpack,vue-cli

具体教程网上很多,就不在此赘述了。

1、选择一个文件夹放工程,cmd进入该目录

cd 目录路径(这里有个小坑,cd命令只对路径当前盘符有效果,例如在c盘输入d:../...是没有效果的还要再输入d:回车或者先进入d盘再cd 路径)

2、创建项目

vue init webpack-simple 工程名字(不能使用中文)

会有一些初始化的设置,如下输入:

Target directory exists. Continue? (Y/n)直接回车默认(然后会下载 vue2.0模板,慢的话连vpn)

Project name (vue-test)直接回车默认

Project description (A Vue.js project) 直接回车默认

use sass?(Y/n)是否使用sass,选n回车

Author 写你自己的名字

3、安装项目依赖

npm install(npm服务器在国外可能会很慢,实在不行挂vpn)

4、启动项目

npm run dev

正常的话默认浏览器就会打开页面了,如图:

这就是vue默认模板了,我们需要修改掉,开始建我们自己的项目。

首先修改src文件夹下的index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue搜索</title>
</head>
<body>
<div id="app1"></div>
</body>
</html>

再到src下的main.js:

import Vue from 'vue';
import App from './App1.vue';
var vueResource = require('vue-resource');
Vue.use(vueResource); new Vue({
el: '#app',
render: h => h(App)
})

注意这里import App from ‘./App1.vue’对应项目vue文件,要使用vue resources也要在这里声明。

然后在src下创建App1.vue:

<template>
<div id="app">
<panel></panel>
</div>
</template> <script>
import panel from './components/panel-new.vue' export default {
components: {
panel
}
}
</script>

需要说明的是,vue文件一般来说由<template></template>、<script></script>、<style></style>组成,对应放html、js和css代码。

这里出现第一个坑,就是template内只放一个div!

就算有并列的兄弟组件也还是要写成:

<template>

<div>

<logo></logo>

<content></content>

<ending></ending>

</div>

</template>

而不能是:

<template>

<div>

<logo></logo>

</div>

<div>

<content></content>

</div>

<div>

<ending></ending>

</div>

</template>

否则会报错。

引入组件后用export default导出到template中,此处有第二个bug:

千万不要在单文件组件(.vue)中再次new Vue()!

因为已经在main.js中创建过实例了,重复的实例将会出现意外,详情见我在seqement fault中的提问:

https://segmentfault.com/q/1010000009870708?_ea=2079044

接下来就是最关键的组件部分,在src下创建components文件夹,再新建logo-new.vue:

<template>
<div class="logo">
<img class="logoNow" :src="imgs[imgState].imgSrc" @click="toggle">
<div class="triangle" @click="toggle">
<span></span>
</div>
<div class="logoMain">
<transition name="fade">
<ul v-show="toggleState" class="listLogo" @mouseleave="leaveList">
<li v-for="(item, index) in imgs" :class=" index == imgSelected ? 'colorBack' : ''" @click="changeImg(index)"
@mouseover="changeBackColor(index)">
<img :src="item.imgSrc">
</li>
</ul>
</transition>
</div>
</div>
</template> <script>
export default {
data () {
return {
//下拉图片背景初始值
imgSelected: -1,
//判断下拉条件
toggleState: false,
//界面显示哪张图片
imgState: 0,
//图片一类的静态文件,应该放在这个static文件夹下,
// 这个文件夹下的文件(夹)会按照原本的结构放在网站根目录下
imgs: [{
imgSrc: ('.././static/360_logo.png')
}, {
imgSrc: ('.././static/baidu_logo.png')
}, {
imgSrc: ('.././static/sougou_logo.png')
}]
}
},
methods: {
toggle: function () {
this.toggleState = !this.toggleState,
//清空上次背景色,
this.imgSelected = -1
},
changeImg: function (index) {
this.toggleState = !this.toggleState,
this.imgState = index,
this.$emit('logoNow', [index])
},
changeBackColor: function (index) {
this.imgSelected = index
},
leaveList: function () {
this.toggleState = false,
this.imgSelected = -1
}
}
}
</script> <style>
ul {
padding: 0;
margin: 0;
} .logoMain {
position: relative;
} .listLogo {
z-index: 9999;
position: absolute;
top: 50%;
left: 60%;
width: 200px;
margin-left:-100px;
/*border: 1px solid #fefefe;*/
} li {
background-color: #fefefe;
list-style-type: none;
width: 200px;
margin-left: -50px;
} /*li:hover {
background-color: #ccc;
}*/
li img {
cursor: pointer;
width: 200px;
height: 58.33px;
} .logoNow, .triangle{
cursor: pointer;
} .triangle {
display: inline-block;
position: relative;
left: -80px;
top: -70px;
} .triangle span {
position: absolute;
display: inline-block;
width: 0;
height: 0;
border-width: 8px;
border-color: #000 transparent transparent transparent;
border-style: solid dashed dashed dashed;
} .fade-enter-active, .fade-leave-active {
transition: all .5s;
} /* .fade-leave-active 在 <2.1.8 中 */
.fade-enter, .fade-leave-to {
opacity: 0;
-webkit-transform: translateY(20px);
-moz-transform: translateY(20px);
-ms-transform: translateY(20px);
-o-transform: translateY(20px);
transform: translateY(20px);
} .colorBack {
background-color: #ccc;
cursor: pointer;
}
</style>

说下整体思想:

点击logo图片可以弹出下拉框选择3个不同的搜索引擎,再点击选项替换logo的img src。

因为vue是以mvvc模式,任何操作都要与模型(数据)挂钩,不能再用dom的思想;所以我们在data里给img设置一个数组,再由一个变量给定具体数值作为下标判断其显示状态。至于下拉菜单部分可以设置为一个ul列表,再用v-show指令控制其显示与否,同样用一个布尔值变量toggleState来判断,默认为false,一旦点击logo图片就会使其变为true,进而出现下拉菜单。

这里的重点在于如何将点击的li与切换到对应logo图片挂上钩?

原生js的思想是用一个for循环,获取到当前‘i’的值再去处理。Vue中也有类似的功能,在v-for循环中有一个参数‘index’可以表示当前索引,将其赋值给下标变量即可完成动态logo图片切换。

另一个难点在于如何在列表li添加hover变色效果?

最简单的方法自然是css中添加li:hover{background:#xxx},

但这显然不是我们想要的方法,用了vue自然要利用其双边绑定的特性。

给li设置一个监听mouseover的方法,将当前index赋值给一个变量,再用一个三元表达式绑定class即只要变量值与当前index相等,则添加一个带背景色的class,否则class为空。

最后一个问题则是给下拉菜单添加过渡效果

vue封装了css3的transition效果,只要在元素上添加name属性,然后在style中用name-xxx指定参数即可,具体详见官网https://cn.vuejs.org/v2/api/#transition

还有一个坑就是给多个元素/组件设置过渡效果就要使用transition-group标签,像我们这个ul列表就是要的。

另外一个问题就是使用的时候一定要紧贴元素外层,不能中间隔了一个div,这样是没有效果的。

到此logo部分的组件大致完成,panel组件请留意我下一篇博文。

博主也是初学vue,并不精深,有出入的地方烦请各位看官指出!

Vue2.0组件实现动态搜索引擎(一)的更多相关文章

  1. 通信vue2.0组件

    vue2.0组件通信各种情况总结与实例分析   Props在vue组件中各种角色总结 在Vue中组件是实现模块化开发的主要内容,而组件的通信更是vue数据驱动的灵魂,现就四种主要情况总结如下: 使用p ...

  2. vue2.0组件库

    UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...

  3. vue2.0组件传值

    props down   emit up 嘿嘿    如果是第一次接触vue2.0组件传值的肯定很疑惑,这是什么意思(大神总结的,我也就是拿来用用) “down”—>指的是下的意思,即父组件向子 ...

  4. Vue2.0+组件库总结

    转自:https://blog.csdn.net/lishanleilixin/article/details/84025459 UI组件 element - 饿了么出品的Vue2的web UI工具套 ...

  5. 转:Vue2.0+组件库总结

    UI组件 element - 饿了么出品的Vue2的web UI工具套件 Vux - 基于Vue和WeUI的组件库 mint-ui - Vue 2的移动UI元素 iview - 基于 Vuejs 的开 ...

  6. Vue2.0组件间数据传递

    Vue1.0组件间传递 使用$on()监听事件: 使用$emit()在它上面触发事件: 使用$dispatch()派发事件,事件沿着父链冒泡: 使用$broadcast()广播事件,事件向下传导给所有 ...

  7. Vue2.0组件之间通信(转载)

    Vue中组件这个特性让不少前端er非常喜欢,我自己也是其中之一,它让前端的组件式开发更加合理和简单.笔者之前有写过一篇Vue2.0子父组件通信,这次我们就来聊一聊平级组件之间的通信. 首先我们先搭好开 ...

  8. Vue2.0组件的继承与扩展

    如果有需要源代码,请猛戳源代码 希望文章给大家些许帮助和启发,麻烦大家在GitHub上面点个赞!!!十分感谢 前言 本文将介绍vue2.0中的组件的继承与扩展,主要分享slot.mixins/exte ...

  9. Vue2.0组件之间通信

    Vue中组件这个特性让不少前端er非常喜欢,我自己也是其中之一,它让前端的组件式开发更加合理和简单.笔者之前有写过一篇Vue2.0子父组件通信,这次我们就来聊一聊平级组件之间的通信. 首先我们先搭好开 ...

随机推荐

  1. 在sql server数据库的一个表中如何查询共有多少字段

    select a.* from sys.columns a,sys.tables bwhere a.object_id = b.object_id and b.name = '要查的表名'

  2. form表单里的坑

    我们在写前端表单页面的时候,为了更好的SEO,我们会使用form标签,但是我们经常的情况是:我们并不需要form标签的一些默认事件,比如: 1.form内只有一个input标签的话,回车会触发表单的提 ...

  3. 【BZOJ4940】【YNOI2016】这是我自己的发明

    阅读此篇文章前请先跟我大喊三声:dllxl!dllxl!dllxl! 咳咳. 题意: Description 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1. 将树根换为 x. ...

  4. [arc082e]ConvexScore

    题意: 给出直角坐标系中的$N$个点$(X_i,Y_i)$,定义由其中部分点构成的点集为“凸点集”当且仅当这些点恰好能构成一个凸多边形(内部没有其他点). 如图,点集$\{A,C,E\}$和$\{B, ...

  5. Hibernate简单的保存操作

    1.这里面我想先说一下session对象的创建,这个是我们操纵数据库的核心对象,因此首先我们应该获取相应的session对象. public static Configuration cfg; pub ...

  6. 紫书 习题8-19 UVa 1312 (枚举技巧)

    这道题参考了https://www.cnblogs.com/20143605--pcx/p/4889518.html 这道题就是枚举矩形的宽, 然后从宽再来枚举高. 具体是这样的, 先把所有点的高度已 ...

  7. [置顶] Docker学习总结(7)——云端基于Docker的微服务与持续交付实践

    本文根据[2016 全球运维大会•深圳站]现场演讲嘉宾分享内容整理而成 讲师简介 易立 毕业于北京大学,获得学士学位和硕士学位:目前负责阿里云容器技术相关的产品的研发工作. 加入阿里之前,曾在IBM中 ...

  8. 【转】C#正则表达式教程和示例

    [转]C#正则表达式教程和示例 有一段时间,正则表达式学习很火热很潮流,当时在CSDN一天就能看到好几个正则表达式的帖子,那段时间借助论坛以及Wrox Press出版的<C#字符串和正则表达式参 ...

  9. MATLAB插值

    转自原文 MATLAB插值 插值问题 在应用领域中,由有限个已知数据点,构造一个解析表达式,由此计算数据点之间的函数值,称之为插值. 实例:海底探测问题 某公司用声纳对海底进行测试,在5×5海里的坐标 ...

  10. [Android Studio 权威教程]配置出“NB”的Android Studio

    前几篇博客我们已经安装好了As,并且创建了我们的第一个HelloWrod ,这片blog我们继续配置出一个NB的Android Studio 假设你是一个才開始接触到AS或者想从Eclipse转型到A ...