从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:
Vue搜索
再到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:
import panel from './components/panel-new.vue'
export default {
components: {
panel
}
}
需要说明的是,vue文件一般来说由、、组成,对应放html、js和css代码。
这里出现第一个坑,就是template内只放一个div!
就算有并列的兄弟组件也还是要写成:
而不能是:
否则会报错。
引入组件后用export default导出到template中,此处有第二个bug:
千万不要在单文件组件(.vue)中再次new Vue()!
因为已经在main.js中创建过实例了,重复的实例将会出现意外,详情见我在seqement fault中的提问:
https://segmentfault.com/q/1010000009870708?_ea=2079044
接下来就是最关键的组件部分,在src下创建components文件夹,再新建logo-new.vue:
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
}
}
}
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;
}
说下整体思想&#xff1a;
点击logo图片可以弹出下拉框选择3个不同的搜索引擎&#xff0c;再点击选项替换logo的img src。
因为vue是以mvvc模式&#xff0c;任何操作都要与模型(数据)挂钩&#xff0c;不能再用dom的思想&#xff1b;所以我们在data里给img设置一个数组&#xff0c;再由一个变量给定具体数值作为下标判断其显示状态。至于下拉菜单部分可以设置为一个ul列表&#xff0c;再用v-show指令控制其显示与否&#xff0c;同样用一个布尔值变量toggleState来判断&#xff0c;默认为false&#xff0c;一旦点击logo图片就会使其变为true&#xff0c;进而出现下拉菜单。
这里的重点在于如何将点击的li与切换到对应logo图片挂上钩&#xff1f;
原生js的思想是用一个for循环&#xff0c;获取到当前‘i’的值再去处理。Vue中也有类似的功能&#xff0c;在v-for循环中有一个参数‘index’可以表示当前索引&#xff0c;将其赋值给下标变量即可完成动态logo图片切换。
另一个难点在于如何在列表li添加hover变色效果&#xff1f;
最简单的方法自然是css中添加li&#xff1a;hover&#xff5b;background&#xff1a;#xxx&#xff5d;&#xff0c;
但这显然不是我们想要的方法&#xff0c;用了vue自然要利用其双边绑定的特性。
给li设置一个监听mouseover的方法&#xff0c;将当前index赋值给一个变量&#xff0c;再用一个三元表达式绑定class即只要变量值与当前index相等&#xff0c;则添加一个带背景色的class&#xff0c;否则class为空。
最后一个问题则是给下拉菜单添加过渡效果
vue封装了css3的transition效果&#xff0c;只要在元素上添加name属性&#xff0c;然后在style中用name-xxx指定参数即可&#xff0c;具体详见官网https://cn.vuejs.org/v2/api/#transition
还有一个坑就是给多个元素/组件设置过渡效果就要使用transition-group标签&#xff0c;像我们这个ul列表就是要的。
另外一个问题就是使用的时候一定要紧贴元素外层&#xff0c;不能中间隔了一个div&#xff0c;这样是没有效果的。
到此logo部分的组件大致完成&#xff0c;panel组件请留意我下一篇博文。
博主也是初学vue&#xff0c;并不精深&#xff0c;有出入的地方烦请各位看官指出&#xff01;