本文转自http://blog.csdn.net/joshua_hit/article/details/59635160
继续搞Vuejs的前端,在之前我已经在Windows系统上配置好了一个初始的vue-cli页面,目前我需要做的工作,就是开始写代码,学习增删页面,加入输入框按钮什么的。另外希望能尽快学会如何通过API取数据,感觉上,能学会这些东西,就能达到一项技术2/8原则里边那个8了。
为了实现这个目的,我上网看了一系列的博客教程,照着抄了很多代码,最后都没办法用。我怀疑原因可能是大家用的版本不一样,感觉上Vue发展速度很快,导致的结果就是每个人写的风格都不一样,后来费了好大力,终于算是自己摸索出了一些结果。搞定了增删按钮以及页面跳转。
我们先回溯一下上一次的进度:刚刚使用vue-cli建立了一个项目,这个项目内似乎东西很多,但是我们只需要关注src文件夹下的东西就行了,运行npm run dev
以后,浏览器会自动弹出一个页面,如下:
而目前的文件夹目录如下:
我们要做的,就是开始理解Vue增删页面的模式,组件和路由(就是网页链接URL)的跳转模式。
大致理解Vue设计思想
首先要理解的是vue的设计理念是怎样的?在我眼里,组件化
是vue最为成功的一项涉及。组件化这个特性把一整个网站都打散成了很小的一个又一个部分。举个例子,看目前的目录下,有三个文件:整个项目目录下的index.htm,src目录下的App.vue,和components文件夹下的Hello.vue.
理解这三者的关系很重要,Index是一个最外层的网站框架,它其实什么都没有,有一个head,head里边可以定义一些CSS一类的,然后body部分完全是空的,它仅仅载入了一个名字叫做app的vue module.
所以说App.vue这个东西,就是嵌套在index.html中的。然后我们在看App.vue文件写了些什么?
// App.vue file
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
额外说一句,vue文件都是这个模式,一共由三个部分构成:上边的
<template>
包含有最终用户看到的按钮框框;中间的<script>
定义了这个组件(module)所用到的数据和函数;后边的<style>
定义了这个组件的样式等等。
所以我们暂时只关注最上边的<template>
,其中只有两句代码比较核心:一行插入了一个图片,另一行写的是<router-view></router-view>
。在这里,大概能猜到,App.vue里其实也差不多是空的,它只是给页面上添加了一个Logo而已,实质性的文章,都没有添加。那么我们看到的页面上的文字到底是哪里来的?它们全部在Hello.vue文件里。App.vue调用了Hello.vue这个组件,并将它显示在了Logo的下方,并且,是通过router来控制的显示,而不是直接插入组件。
最后,我们打开router文件夹下的index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
}
]
})
这个router文件是针对App.vue的路由,对应的内容,全部都会显示在刚才看到的那一行<router-view></router-view>
中,在这里,App.vue会自动寻找这一些组件,比如,在目前的index.js中,path显示的是”/”对吧?这就意味着,当页面打开到App.vue,而没有增加其他的url后缀的时候 (http://localhost:8080/#/),App.vue会自动载入Hello这个组件,加载在那个Logo的下面。
如果还不能理解,下面我们做一个小实验:
你修改path的值为“/Hello”,那么你只有在(http://localhost:8080/#/Hello)才会重新看到刚才那个页面。而在(http://localhost:8080/#/)目录下,你会发现,只有一个logo,其他什么都没有。
稍微总结一下
- 上述的小实验已经充分证明了,index.html, App.vue, Hello.vue之间的关系。一般来说,index.html是不用动的(顶多增加一些css头文件)。所以我们开始修改的其实文件就是App.vue,然后鉴于我们想要添加文件,所以需要修改router里边的index.js文件,最后鉴于我们要添加新页面和组件,我们还需要增加一些components文件夹里边的东西。
- 如果按照目前的index.js的结构,如果你怎么修改那个Hello.vue文件,或者增加其他组件,它们只有一个归宿:就是躺在App.vue里的那个Logo图像的下面。因为App.vue是父组件,而Hello.vue只不过是它的子组件。但是这并不意味着谁重要谁难写,因为如果你把App.vue里边那个logo那一行注释掉,App.vue就什么都无法呈现,仅仅是为Hello.vue以及未来的一些页面提供了一个承载框架而已。
- 未来开发完的网站里,用户感觉上可能是一个页面和一个url的单独对应,就像是曾经的每一个PHP文件对应每一个url一样,但实际上,可能很多页面,都像Hello.vue一样,仅仅是App.vue的子组件而已。
- 目前在App.vue里,有Hello组件;以后我们在Hello组件里,还可以插入其他的组件,当然不一定是这种使用router的办法,因为用这个模式,每一个组件都会有一个对应的url,如果你的页面上有三个tab,可能没有必要每一个tab对应一个url吧?但目前要理解的就是:我个人觉得Vue最核心的设计理念,就是把一个看起来很完整的页面,分散到了每一个组件,这个组件可能大道一个页面,Hello.vue,也可能小到一个按钮,最终我们看到的页面,是这一群组件的堆砌的结果,这样做的一大好处就是,每一个组件都可以单独进行与数据库和用户的交互,开发更为清晰。
Git 保存
做到目前位置,我们也没有存过档,可以用Github存一下档。(熟练的高手可以忽视这一段,我是小白),在自己的Github下新建一个叫做LearnVue
的repositories。代码以后就上传到这个页面上。然后确保本机上安装了Git,没有的话下载安装一下,Windows上安装超简单的,安装完以后打开Gitbash,先将目录转到Front文件夹下,然后使用如下一些命令:
git init
git add .
git commit -m "My Vue Demo"
git remote add origin https://github.com/JoshuaTian/LearnVue.git
git push -u origin master
过程中会出现一个要求你登录的页面,直接登录就是了。截图如下(图中我的命令写错了一个,读者忽视就是,用上述的代码):
然后再回到Github页面上,刷新一下,就能看到代码已经全部上传了。以后如果代码被改乱了,可以来Github上找目前的存档恢复(我常有这种问题)。
初学vue-router
继续,刚才我们通过修改index.js上的path,已经理解了,Hello.vue和App.vue的关系,以及网址和页面(或者说页面上的某一个部分)是如何对应上的。现在我们继续探索一下,如何在子页面上,添加路由。目前的局面是,App.vue组件(它确实只是一个组件)下有Hello.vue组件,而Hello.vue的位置,是App.vue组件里面那个Logo的下面,下面我们用最快的速度再作出三个页面:
修改router文件夹下的index.js文件:
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import Home from '@/components/Home'
import FirstPage from '@/components/FirstPage'
import SecondPage from '@/components/SecondPage'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/Hello',
name: 'Hello',
component: Hello
},
{
path: '/Home',
name: 'Home',
component: Home
},
{
path: '/FirstPage',
name: 'FirstPage',
component: FirstPage
},
{
path: '/SecondPage',
name: 'SecondPage',
component: SecondPage
}
]
})
在这个文件中,我们添加了三个路由,Home,FirstPage,SecondPage,现在cmd那边肯定在报错,因为我们还没有建立那个对应的那三个Page页面的vue文件。
然后我们去components文件夹下,建立三个vue文件:Home.vue,FirstPage.vue, SecondPage.vue. 内容几乎都一样,就三行,如下(每一个就只有中间的h1标签不同,其他都一样,中间那个分开写到三个页面里),这三个页面就是分别Home,FirstPage,SecondPage将要渲染到屏幕上的东西。
// components/Home.vue
<template>
<h1> This is Home Page </h1>
//<h1> This is First Page </h1>
//<h1> This is Second Page </h1>
</template>
最后修改一下Hello.vue页面,我们需要在其中加入链接,这样就可以点击某个按钮转移到新的界面了。(我多删了一些东西),让页面看起来更清爽一些:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<router-link id="Home" to="/Home">Home</router-link>
<router-link id="FirstPage" to="/FirstPage">FirstPage</router-link>
<router-link id="SecondPage" to="/SecondPage">SecondPage</router-link>
</ul>
<h2>Ecosystem</h2>
<ul>
<li><a href="http://localhost:8080/#/Home" target="_blank">Home</a></li>
<li><a href="http://localhost:8080/#/FirstPage" target="_blank">FirstPage</a></li>
<li><a href="http://localhost:8080/#/SecondPage" target="_blank">SecondPage</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'hello',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
上边这一段代码中,我添加了六个可以点击的连接,前三个用的是vue推荐的router-link方式,后三个用的是最传统的href的方式。我个人只用前者,之所以放在这里是做比较用的。然后页面就成了这个样子。
现在,我们如果点击任何一个连接,就能看到跳转:
可以看到,目前所有的页面,都是在那个Logo下面,这是因为Hello.vue,Home.vue,FirstPage.vue,SecondPage.vue,全部都是App.vue的下属组建。都是被放置在Logo下的,现在如果你去App.vue里把Logo删掉,它们就是看上去都完全不同的三个页面了。
刚才已经我们成功地学会了如何添加页面,这样以后做网站如果页面不够,就用这办法可以一个一个地加,如果想要添加那种完全依赖url驱动的网页,例如/user:1,/user:2这样的,我目前还不会,但应该不会太难。
下面我们尝试在一个子页面上添加组件:
严格来说,这句话是病句,因为Hello.vue就是一个组件,我们要做的,实在组件上再添加组件,那么路由因该怎么弄?刚才做的东西,就是可以让我们在App.vue这个父组件中更换页面了,那么如何在Hello.vue页面中做到更换?如果能实现这一步,网站的所有链接跳转就都能实现了,网站无非有两种,页面直接切换,或者页面中的某个部件发生替换(就像是我们刚才在Vue那个大Logo下替换Home, FirstPage一样),所以我们需要学会如何在Vue的任何一个页面上,更换添加组件。
下面以Home.vue为例。
再打开router文件夹下的index.js,在之前写过的Home下面添加一个children路由:
// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import Home from '@/components/Home'
import FirstPage from '@/components/FirstPage'
import SecondPage from '@/components/SecondPage'
import FirstPart from '@/components/HomeComponents/FirstPart'
import SecondPart from '@/components/HomeComponents/SecondPart'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
},
{
path: '/Home',
name: 'Home',
component: Home,
children: [
{
path: '/',
name: 'FirstPart',
component: FirstPart
},
{
path: 'SecondPart',
name: 'SecondPart',
component: SecondPart
}
]
},
{
path: '/FirstPage',
name: 'FirstPage',
component: FirstPage
},
{
path: '/SecondPage',
name: 'SecondPage',
component: SecondPage
}
]
})
写完以后是上边这样子,我们在Home的路由中,又添加了两个子路由,FirstPart和SecondPart. 这里FirstPart的路由是”/”,代表着是默认选择,否则的话,一打开Home页面,FirstPart和
然后再Home.vue组件中添加几行:
<template>
<div>
<h1> This is Home Page </h1>
<router-link id="FirstPart" to="/Home">FirstPart</router-link>
<router-link id="SecondPart" to="/Home/SecondPart">SecondPart</router-link>
<hr>
<router-view></router-view>
</div>
</template>
这样,我们就规定了,从Home页面渲染的组件,都显示在<hr>
那条线下面。
最后我们去到Components文件夹下,建立一个小文件夹HomeComponents(不建也行,自己找得到就好),在其中新建两个文件,FirstPart.vue和SecondPart.vue,内容几乎一致:
// components/HomeComponents/FirstPart.vue
<template>
<div>
<h2> This is First Part </h2>
</div>
</template>
好了,然后再刷新页面,转到Home页面上,就可以看到:
这样,我们就成功地在Home页上又添加了两个小的页面。
学会这一步以后,我们就可以随意地增删页面,而且页面上也可以添加更多的组件,一层一层地嵌套。在这里,我都是在用路由router来连接一个又一个的组件。而其实如果某个组件只有一个button一类的情况,用这种办法实在是没有必要。基本上,这种办法就适合架设比较大的一些页面:
例如:我学Vue的目的是为了架设一个个人网站,我大概有主页,博客页,项目页,关于页,简历页等等,这些大页面毫无疑问是需要用这种路由来假设的。假如在我的项目页里,只有四五个项目,每一个项目都是那种占满整个网页的图表,那么我就可以在项目页里,再开4-5个路由单独指向每一个项目。其余的应该没有必要,直接在Vue中添加组件就行。
下面的部分,就是有关于如何在Vue中直接Import组件。
直接Import组件
我们继续,鉴于我是想要写一个个人网站,现在我假设想要添加五个页面:主页,博客目录页,项目展示页,用户注册登录页,简历页,关于页。
虽然只有六个页面,但是要想做好,要想的东西挺多的,因为vue不像是php,不能写了一半页面了,才开始想下一半页面该怎么做,而是一开始就要想清楚,每一个页面的架构是怎样的,甚至于,每一个图表,每一个按钮最终会放在哪一个组件中?用写文章来类比,原本用php写网页,就像是写流水账一样,写到中间下半部再怎么设计结尾都可以。但是用vue,就必须要先规定死,这篇文章,开头是哪一个组件?中间是哪一个组件?结尾是哪一个组件?某一些更细的组件(例如一列排比句)应该放在中间组件的哪一个部位等等。在这里写文档,我就先不这么认认真真地设计思考了,先尽快搭出框架来。
引用一些CSS模板
到现在要开始做页面了,如果纯靠手来code整个页面,实在是太累了,所以可以使用一些现成的页面组件。这里写的组件或者模板,和前文写的组件完全不是一个意思啊!这里的组件的意思是,Bootstrap,Element,iView一类的东西。打开一看就懂了,都是一些已经写得很漂亮很漂亮的网页组件代码片段,只用引用相关的CSS文件和JavaScript文件就能用。
有关于Vue的这类组件,似乎TalkingData的iView和饿了吗的Element做的最好。具体谁更好,我也不知道……随便抓了(Element)用起来,反正都没用过,有这方面经验的同学可以告诉我。
首先打开CMD或者CMDer,在Front文件夹下,输入:
npm install element-ui -save
这样的话Element组件就被安装到了Project里,打开main.js文件,在其中加入:
import Vue from 'vue'
import ElementUI from 'element-ui' //New Added
import 'element-ui/lib/theme-default/index.css' //New Added
import App from './App'
import router from './router'
Vue.config.productionTip = false
Vue.use(ElementUI) //New Added
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
这样我们就可以在整个项目都是用这一套组件了。
写出导航条
首先我们要写一个导航条,应该写在哪里呢?其实写在Hello.vue或者App.vue中严格来说都可以,但是如果写在Hello.vue中,以后添加Home, Register, Document, About等等页面,你都需要添加一次。所以还是写在App.vue中比较合适。
我们先在components文件夹中新建一个AppComponents的文件夹,专门用来放置被直接加载到App.vue中的组件,然后在其中添加一个Navbar.vue
文件,我们要在其中添加导航条。
直接打开Element的页面开始抄袭。把整个导航条复制到我们Navbar.vue文件中。要稍微做一些调整,比如,添加<template>
。具体的文件如下:
// components/AppComponents/Navbar.vue
<template>
<el-menu theme="dark" :default-active="activeIndex"
class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">Home</el-menu-item>
<el-menu-item index="2">Article</el-menu-item>
<el-submenu index="3">
<template slot="title">Projects</template>
<el-menu-item index="3-1">Shiny</el-menu-item>
<el-menu-item index="3-2">LearnVue</el-menu-item>
<el-menu-item index="3-3">OtherProject</el-menu-item>
</el-submenu>
<el-menu-item index="4">Login</el-menu-item>
<el-menu-item index="5">Resume</el-menu-item>
<el-menu-item index="5">About</el-menu-item>
</el-menu>
</template>
<script>
export default {
data () {
return {
activeIndex: '1',
activeIndex2: '1'
}
},
methods: {
handleSelect (key, keyPath) {
console.log(key, keyPath)
}
}
}
</script>
然后,直接修改App.vue(因为导航条是要被放在App.vue里,这样所有的页面都能看到,而不用重新在每一个页面都重写)。改成这样:
// App.vue
<template>
<div id="app">
<mynavbar></mynavbar>
<img src="./assets/logo.png">
<router-view></router-view>
</div>
</template>
<script>
import mynavbar from './components/AppComponents/Navbar.vue'
export default {
name: 'app',
components: {
mynavbar
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 0px;
}
</style>
简单来说就是三步:
- import 那个组件。
- 添加到mynavbar到export中。
- 在div最上方写:
<mynavbar></mynavbar>
- (修改一下下边的Style里边的那个margin-top为0px.)
然后我们再打开http://localhost:8080,就已经变成了:
无论你怎么点击那些Home,FirstPage,界面会换导航条都不会动的。当然如果你点击导航条上的那些东西,也是什么变化都不会有的,因为上边什么都还没有做。
通过这种办法,我们只需要两步,就可以将一个组件添加到某一个大组件上,而不需要像之前一样很麻烦地调用路由。
以后我们的页面基本上都是一堆组件的堆砌。用这种办法,我们就可以耐心地一点一点把巨大的页面架构起来。这种办法,比起曾经的PHP确实麻烦许多,但是如果项目大了,项目分离就很容易,每个人只需要负责一个组件就行了,完事儿了汇总在一起,就是一堆module的import。这就是使用Vue的目的。
OK,通过这种办法,构建页面,转换路由已经没有问题了,下面还剩下的问题大概有几个:
1. 如何使用API调用数据。
2. 组件间通信,比如,目前的导航条,默认选择是Home,如果我换到了其他的网址,如何自动调整Navbar。
3. 如何部署上线。