前面一篇博客介绍了从零开始准备Vue.js所需的一些环境和工具。这片博客就来跟大家探讨一下Vue.js 2.0中的一些特性,以及一个小实例,通过实例来跟大家分享,想必更容易理解。

先来看一下,看完这篇博客,你会做出什么样的效果吧。

就是这样的一个小的demo,其中主要用到了vue-router 2.0 和vue的单文件组件,这里再细分一下如下

  • vue-router 2.0 定义路由配置
  • router-view 和 router-link 来控制路由
  • transition 控制页面之间的跳转动画
  • .vue后缀名的单文件组件
  • 简单的ES6语法

修改项目目录结构

先来看一下项目的机构,我在原项目目录结构上稍作调整,让目录结构更清晰一些。如下图

在 src 目录下,删除 App.vue ,增加 pages 文件夹,该文件夹用来用来放置我们创建的“页面”(比如,Home.vue)。其实,这里说的“页面”也是组件,只是它变现为一个“页面”而已,跟components 目录下的组件没有本质的区别,我们分开目录放置主要是更语义化,结构更清晰易懂。

可能有的刚接触的同学还不太了解组件(.vue后缀结尾的文件),不要着急,接着往下看。

.vue后缀名的单文件组件

这里先说一下我对组件的理解。组件,顾名思义就是一组元素组成的一个原件(理解的比较浅显、直白),在Vue.js中,表现为一个自定义元素。开篇展示的图中,首页的的列表中的每一项就可以看成一个组件(事实上,在demo中,我也是这么做的),这个组件由一张图片,一个显示价格的元素,一个显示名称的元素组成,我就可以先把它定义为一个list组件。
首先,我们先来分析一下两个页面中组件,如下图
主页可以看做由两个组件组成,homeHeader和list组件,而详情页则可以看成是有detailHeader跟下边的图文内容组成(这里的图文内容也可以写成组件,但是博主这里想偷懒一下,有兴趣的,可以自己试着写成组件)。
分析完两个页面的组件构成之后,我们修改项目目录如下
这样的目录结构,就一目了然了吧。两个页面,Home和detail和其中用到的三个组件。ps:assets目录下新建的img目录,里边放的一张图片是测试用的。
做了这么一大堆铺垫,现在来简单说一说单文件组件.vue文件。拿List.vue为例,说说单文件组件的结构,如下图
单文件组件,由三大部分组成,template、style、script,想必看到这三个标签元素,大家也都对其作用大概了解了吧。

template

template是放置组件的组成部分——html元素的地方,是整个组件的模板构成。不过有一点需要特别注意,template下只能存在一个根html元素作为wrapper,不能存在两个并列的跟元素,否则会报错。

style

style下放置组件的样式,可以用css预处理器less或者sass等,前提是需要安装这些依赖包,和设置lang属性,博主比较懒,直接用css了。这个style里的样式表在项目运行的时候会生成一个style标签,插入到index.html的head标签里,如果组件里的style标签为空,则会在index.html的head里插入一个空的style标签,所以,建议大家,这个组件没有用到css,就不要写一个空的style,直接省略就好。
既然每个组件的样式都会生成一个style插入到index.html中,我们做的又是单页面应用,所有的代码都基于index.html的,那如果我们的项目比较大或者是多人协作开发的,难免会在写组件的时候会命名相同的class,这样的话,具有相同class的不同组件的样式就会收到影响,产生不可预估的样式问题,那岂不是很头疼。其实,vue早就替我想到了这个问题,可以给style设置一个scoped的属性,意思是该style里的样式只对这个组件起作用,不会影响其他组件中含有相同class的元素。那vue是怎么做到的呢?这里先卖个关子,后边再探究竟。

script

script里自然是放的js代码。这里会用到一些ES6的语法,大家可以去这里 学习ES6的一些新的语法特性。在List.vue的script中,大致意思就是导出一个对象(这个组件),其中设置可以通过属性price和title传递数据。看下边的示意图
具体的怎样利用props传递数据,请看 这里。
.vue单文件组件的三大组成部分大概就是这些,具体的内容,主要是script,整个组件的功能代码全在这里边,大家还要多去学习和了解,由于在下才疏学浅,也只能介绍这些了。

vue-router 2.0

由于用vue主要开发单页面应用,没有页面之间的跳转,在vue中,一个所谓的“页面”实则是一个看起来很像“页面”的一个组件(这个组件大部分情况下包含其他子组件)而已。既然没有页面,那怎样实现页面之间的切换呢?那就是我们现在要介绍的主角——vue-router 2.0。
vue-router是在vue中控制路由的。ps:如果你不太理解路由这个概念,可以简单的理解为url重的hash部分,只不过vue做了一些封装和完善。要控制路由,还需要借助两个vue-router自带的两个组件router-view和router-link。

安装vue-router 2.0

打开命令行,cd到当前项目的目录,运行 cnpm install vue-router --save  ,f等待安装完成即可。

router-view

router-view是现实路由内容的地方,即如果有多个“页面”需要切换,显示当前“页面“的地方。需要注意的是,使用vue-router控制路由则必须router-view作为容器。
router-view还可以嵌套,即嵌套路由,详情去 这里学习哟~

router-link

router-link有一个to属性,其属性值是目标路由,在运行项目的时候,router-link表现为a标签,to属性则表现为a标签的href属性。至于,为什么不直接用a标签,我也不知道呢。如果你知道的话,可以留言告诉我,不胜感激的呢~
这是List组件中用到的router-link组件。
基本的概念和准备工作都做好了,剩下的就是贴代码了,瞬间感觉轻松好多。
修改根目录下的index.html如下:

[html] view plaincopy
  1. <!-- index.html -->
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  7. <title>first-vue</title>
  8. <style type="text/css">
  9. * { margin: 0; padding: 0; }
  10. html,body { background: #eee; }
  11. ul,li { list-style: none; }
  12. a { text-decoration: none; }
  13. img { vertical-align: middle; }
  14. /* 跳转页面动画 */
  15. .slide-enter,
  16. .slide_back-enter {
  17. position: absolute;
  18. width: 100%;
  19. }
  20. .slide-leave,
  21. .slide_back-leave {
  22. position: absolute;
  23. width: 100%;
  24. }
  25. .slide-enter-active,
  26. .slide_back-enter-active {
  27. transition: all 0.3s linear;
  28. }
  29. .slide-leave-active {
  30. position: absolute;
  31. transition: all 0.3s linear;
  32. transform: translate(-100%);
  33. }
  34. .slide-enter{
  35. transform: translateX(100%);
  36. }
  37. .slide_back-leave-active {
  38. position: absolute;
  39. transition: all 0.3s linear;
  40. transform: translate(100%);
  41. }
  42. .slide_back-enter {
  43. transform: translateX(-100%);
  44. }
  45. </style>
  46. </head>
  47. <body>
  48. <div id="app">
  49. <transition :name="transitionName">
  50. <router-view></router-view>
  51. </transition>
  52. </div>
  53. <script type="text/javascript">
  54. // 计算html的font-size
  55. (function(){
  56. function resizeBaseFontSize(){
  57. var rootHtml = document.documentElement,
  58. deviceWidth = rootHtml.clientWidth;
  59. if(deviceWidth > 640){
  60. deviceWidth = 640;
  61. }
  62. rootHtml.style.fontSize = deviceWidth / 7.5 + "px";
  63. }
  64. resizeBaseFontSize();
  65. window.addEventListener("resize", resizeBaseFontSize, false);
  66. window.addEventListener("orientationchange", resizeBaseFontSize, false);
  67. })();
  68. </script>
  69. </body>
  70. </html>

其中 transition组件是用来控制页面切换的动画用的,transitionName绑定到的是main.js中的data中的transitionName字段。

修改src目录下的main.js如下:
[javascript] view plaincopy
  1. // main.js
  2. // 导入Vue,这个是必需的,在使用Vue之前,必须先导入
  3. import Vue from 'vue'
  4. // 导入 vue-router,并使用
  5. import VueRouter from 'vue-router'
  6. Vue.use(VueRouter)
  7. // 导入 pages 下的 Home.vue
  8. import Home from './pages/Home'
  9. import Detail from './pages/Detail'
  10. // 定义路由配置
  11. const routes = [
  12. {
  13. path: '/',
  14. component: Home
  15. },
  16. {
  17. path: '/detail',
  18. component: Detail
  19. }
  20. ]
  21. // 创建路由实例
  22. const router = new VueRouter({
  23. routes
  24. })
  25. // 创建 Vue 实例
  26. new Vue({
  27. el: '#app',
  28. data(){
  29. return {
  30. transitionName: 'slide'
  31. }
  32. },
  33. router, // 在vue实例配置中,用router
  34. watch: {
  35. // 监视路由,参数为要目标路由和当前页面的路由
  36. '$route' (to, from){
  37. const toDepth = to.path.substring(0, to.path.length-2).split('/').length
  38. // 官方给出的例子为 const toDepth = to.path.split('/').length 由于现在只有两个路由路径'/'和'/detail'
  39. // 按照官方给的例子,这两个路由路径深度都为 2 ,所以,这里稍作调整,不知道有什么不妥
  40. // 但目前在这个demo中能正常运行,如果知道更好的方法,欢迎留言赐教
  41. const fromDepth = from.path.substring(0, from.path.length-2).split('/').length
  42. this.transitionName = toDepth < fromDepth ? 'slide_back' : 'slide'
  43. // 根据路由深度,来判断是该从右侧进入还是该从左侧进入
  44. }
  45. }
  46. })

HomeHeader.vue代码

[plain] view plaincopy
  1. <!-- HomeHeader.vue -->
  2. <template>
  3. <header class="header">
  4. <div class="header_inner">
  5. <div class="header_cont">主页</div>
  6. </div>
  7. </header>
  8. </template>
  9. <style>
  10. .header {
  11. height: 0.88rem;
  12. }
  13. .header_inner {
  14. position: fixed;
  15. top: 0;
  16. left: 0;
  17. right: 0;
  18. z-index: 99;
  19. max-width: 640px;
  20. height: 0.88rem;
  21. box-sizing: border-box;
  22. margin: 0 auto;
  23. padding: 0 0.24rem;
  24. border-bottom: 0.02rem solid #80ccd6;
  25. background-color: #fff;
  26. }
  27. .header_cont {
  28. text-align: center;
  29. padding: 0 0.4rem;
  30. line-height: 0.86rem;
  31. font-size: 15px;
  32. overflow: hidden;
  33. text-overflow: ellipsis;
  34. white-space: nowrap;
  35. }
  36. </style>

List.vue代码

[plain] view plaincopy
  1. <!-- List.vue -->
  2. <template>
  3. <li class="sec_li">
  4. <router-link to="/detail" class="lp_li_a">
  5. <div class="lp_li_imgWrap">
  6. <img src="../assets/img/lp_01.jpg" alt="">
  7. </div>
  8. <p class="lp_li_name">{{ title }}</p>
  9. <p class="lp_li_price">¥{{ price }}元</p>
  10. </router-link>
  11. </li>
  12. </template>
  13. <style scoped>
  14. .sec_li {
  15. float: left;
  16. width: 50%;
  17. margin-bottom: 0.1rem;
  18. }
  19. .lp_li_a {
  20. display: block;
  21. padding: 0.3rem 0;
  22. margin: 0 0.05rem;
  23. text-align: center;
  24. background: #fff;
  25. }
  26. .lp_li_imgWrap {
  27. padding: 0.24rem 0;
  28. }
  29. .lp_li_imgWrap > img {
  30. width: auto;
  31. height: 2.3rem;
  32. }
  33. .lp_li_name {
  34. height: 0.5rem;
  35. line-height: 0.5rem;
  36. font-size: 16px;
  37. color: #333;
  38. }
  39. .lp_li_price {
  40. height: 0.5rem;
  41. line-height: 0.5rem;
  42. font-size: 16px;
  43. color: #fb3b3b;
  44. }
  45. </style>
  46. <script>
  47. export default {
  48. props: ['price', 'title']
  49. }
  50. </script>

DetailHeader.vue代码

[plain] view plaincopy
  1. <!-- DetailHeader.vue -->
  2. <template>
  3. <header class="header">
  4. <div class="header_inner flexWrap">
  5. <div
  6. id="header_btn_nav"
  7. class="header_btn header_btn_back"
  8. v-on:click="goBack"
  9. >返回</div>
  10. <div class="header_cont flex">详情</div>
  11. <div class="header_btn header_btn_cart"></div>
  12. </div>
  13. </header>
  14. </template>
  15. <style>
  16. .flexWrap {
  17. display: -webkit-flex;
  18. display: flex;
  19. }
  20. .flex {
  21. flex: 1;
  22. }
  23. .header {
  24. height: 0.88rem;
  25. }
  26. .header_inner {
  27. position: fixed;
  28. top: 0;
  29. left: 0;
  30. right: 0;
  31. z-index: 99;
  32. max-width: 640px;
  33. height: 0.88rem;
  34. box-sizing: border-box;
  35. margin: 0 auto;
  36. padding: 0 0.24rem;
  37. border-bottom: 0.02rem solid #80ccd6;
  38. background-color: #fff;
  39. }
  40. .header_btn {
  41. width: 0.5rem;
  42. height: 100%;
  43. background-repeat: no-repeat;
  44. }
  45. .header_btn_back {
  46. line-height: 0.86rem;
  47. }
  48. .header_cont {
  49. text-align: center;
  50. padding: 0 0.4rem;
  51. line-height: 0.86rem;
  52. font-size: 15px;
  53. overflow: hidden;
  54. text-overflow: ellipsis;
  55. white-space: nowrap;
  56. }
  57. .header_btn:active {
  58. opacity: 0.7;
  59. }
  60. </style>
  61. <script>
  62. export default {
  63. methods: {
  64. goBack(){
  65. window.history.back();
  66. }
  67. }
  68. }
  69. </script>

Home.vue代码

[plain] view plaincopy
  1. <!-- Home.vue -->
  2. <template>
  3. <div class="container">
  4. <!-- 由于html不区分大小写,所以js中驼峰命名方式在html中要改成用短横线连接的形式 -->
  5. <home-header></home-header>
  6. <div class="content">
  7. <ul class="cont_ul">
  8. <list
  9. v-for="item in items"
  10. :price="item.price"
  11. :title="item.title">
  12. </list>
  13. </ul>
  14. </div>
  15. </div>
  16. </template>
  17. <style>
  18. .container {
  19. max-width: 640px;
  20. margin: 0 auto;
  21. overflow-x: hidden;
  22. }
  23. .cont_ul {
  24. padding-top: 0.05rem;
  25. margin: 0 -0.12rem;
  26. }
  27. .cont_ul:after {
  28. content: "";
  29. display: block;
  30. width: 0;
  31. height: 0;
  32. clear: both;
  33. }
  34. </style>
  35. <script>
  36. // 导入要用到的子组件
  37. import HomeHeader from '../components/HomeHeader'
  38. import List from '../components/List'
  39. export default {
  40. data () {
  41. return {
  42. items: [
  43. { price: "129.00", title: "大学" },
  44. { price: "256.00", title: "中庸" },
  45. { price: "399.00", title: "论语" },
  46. { price: "998.00", title: "孟子" },
  47. { price: "99.00", title: "道德经" },
  48. { price: "89.00", title: "老子" },
  49. { price: "188.00", title: "金刚经" },
  50. { price: "209.00", title: "易筋经" },
  51. ]
  52. }
  53. },
  54. // 在components字段中,包含导入的子组件
  55. components: {
  56. HomeHeader,
  57. List
  58. }
  59. }
  60. </script>

Detail.vue代码

[plain] view plaincopy
  1. <!-- Detail.vue -->
  2. <template>
  3. <div class="detail">
  4. <detail-header></detail-header>
  5. <img src="../assets/img/lp_01.jpg" alt="">
  6. <p>崇贤馆始置唐代太宗朝。1999年,李克先生及志同道合者复兴其宗旨。以积累、传播中华优秀传统文化,提供全新国学体验馆为宏愿。</p>
  7. <p>其间,在季羡林、冯其庸等国学大师及著名文史学家傅璇琮、毛佩琦先生指导下,耕注先贤原典,以宣纸线装精品形式呈奉世人。作为一家国学传播机构,崇贤馆始终致力于中华传统文化的传承和推广,以古籍线装宣纸书的形式,对浩繁的史海巨著进行经典复刻。不仅如此,崇贤馆还延请了傅璇琮、毛佩奇等诸位在国学界内享有盛誉的专家和学者担纲学术顾问,以精益求精的治学态度面对每一部崇贤馆的作品,使之成为学术史中无尚的精品。</p>
  8. </div>
  9. </template>
  10. <style>
  11. .detail {
  12. padding: 0.24rem;
  13. font-size: 12px;
  14. }
  15. img {
  16. display: block;
  17. width: 80%;
  18. margin: 0 auto 0.2rem;
  19. }
  20. p {
  21. font-size: 14px;
  22. line-height: 0.5rem;
  23. text-align: justify;
  24. padding-bottom: 0.24rem;
  25. }
  26. </style>
  27. <script>
  28. import DetailHeader from '../components/DetailHeader'
  29. export default {
  30. components: {
  31. DetailHeader
  32. }
  33. }
  34. </script>

最后,差点忘了,style的scoped属性的问题。现在,我们把List.vue中的style加上scoped属性,然后在命令行cd到项目目录,运行 npm run dev ,在浏览器访问localhost:8080,然后审查列表标签,会发现在列表标签中多了一个自定义属性,如下

相应的css选择器也成了复合选择器,在原有选择器基础上复合了一个属性选择器,so~~这就是style scoped的奥秘之处。
这下应该没有什么遗漏了吧,好累,心好累~~~
哦,对了,如果用sublime开发,建议安装vue的插件,支持语法高亮哟~
应有些朋友的需求,把项目源码托管到github上,项目网址 https://github.com/Angewell/firstVue
原文地址: http://blog.qianduanchina.cn/post/59704ab47838a71273eb4da7

Vue.js 2.0从入门到放弃---入门实例(二)相关推荐

  1. Vue.js 3.0快速入门(附电影购票APP开发实战源码)

    前言 文档笔记来源:kuangshenstudy,清华大学出版社,结合视频资源食用更佳,相关资源源码在文末,有需要自取. 一.概述 Vue是什么? Vue.js是基于JavaScript的一套MVVC ...

  2. 【转】Vue.js 2.0 快速上手精华梳理

    Vue.js 2.0 快速上手精华梳理 Sandy 发掘代码技巧:公众号:daimajiqiao 自从Vue2.0发布后,Vue就成了前端领域的热门话题,github也突破了三万的star,那么对于新 ...

  3. Vue.js 3.0 响应式 API 比 2.x 好在哪儿?

    Hello,各位小伙伴,接下来的一段时间里,我会把我的课程<Vue.js 3.0 核心源码解析>中问题的答案陆续在我的公众号发布,由于课程的问题大多数都是开放性的问题,所以我的答案也不一定 ...

  4. Vue.js 2.0 渐进开发应用实践

    课程简介 Vue.js 作为当前的热门框架之一,之前大部分情况下是被介绍作轻量级.高性能的 MVVM 框架.随着 Vue.js 2.0 的发布,以及框架作者尤雨溪先生在 2016 年底的 NingJS ...

  5. 【哈士奇赠书活动 - 24期】-〖前端工程化:基于Vue.js 3.0的设计与实践〗

    文章目录 ⭐️ 赠书 - <前端工程化:基于Vue.js 3.0的设计与实践> ⭐️ 内容简介 ⭐️ 作者简介 ⭐️ 精彩书评 ⭐️ 赠书活动 → 获奖名单 ⭐️ 赠书 - <前端工 ...

  6. vue.js 2.0实现的简单分页

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...

  7. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  8. vue 3.0和2.0区别_一文看懂 Vue.js 3.0 的优化

    Vue.js 从 1.x 到 2.0 版本,最大的升级就是引入了虚拟 DOM 的概念,它为后续做服务端渲染以及跨端框架 Weex 提供了基础. Vue.js 2.x 发展了很久,现在周边的生态设施都已 ...

  9. 组件用.vue还是.js_如何使用Vue.js 2.0构建灵活的图像上传器组件

    组件用.vue还是.js by Cathy Ha 由凯茜·哈(Cathy Ha) 如何使用Vue.js 2.0构建灵活的图像上传器组件 (How to build a flexible image u ...

  10. [面试专题]Vue.js 2.0 独立构建和运行时构建的区别

    Vue.js 2.0 独立构建和运行时构建的区别 标签(空格分隔): 未分类 在使用 Vue.js 2.0 时,有独立构建(standalone)和运行时构建(runtime-only)两种版本可供选 ...

最新文章

  1. STP 根桥、根port、指定port是怎样选举的
  2. 解决cmd命令查看python版本“python不是内部命令或外部命令,也不是可执行程序解决方案”的问题
  3. 释疑のABAP内表的比较
  4. 基于MATLAB的LS-SVM实现方法以及SVM的一些知识点
  5. 怎么安装python的包_python下如何安装.whl包?
  6. 算法题目中常见的几种输入小点-gets,cin,scanf,getline,sstream
  7. mysql 更新 字段 递增_MySQL使用递增变量更新字段
  8. erpnext mysql_windows7+docker+erpnext部署
  9. 基于Nokia S60的游戏开发之一
  10. Magento: 获取客户信息 Get Customer’s Full Name, First Name, Last Name and Email Addres
  11. python作品讲解_python实例作品
  12. 头文件 ctype.h 以及函数 isalpha() tolower()
  13. PE文件格式学习之PE头移位
  14. python 类 内置方法_类相关内置方法
  15. 简单基础的原生JS实现图片上传添加
  16. ZOJ-3939 The Lucky Week
  17. POI删除Excel中数据有效性
  18. 交通-城市规划专业常用——10分钟步行圈(百度API)
  19. 前端---HTML QQ空间主页制作
  20. iOS VIPER 架构解读

热门文章

  1. 从(社区电商)订购 到 出库 业务流程(个人想法)
  2. 32岁了,我有机会转行做程序员吗?——Leo网上答疑(1)
  3. java多线程生产消费者_JAVA多线程实现生产者消费者的实例详解
  4. Linux课程---3、Linux远程登录和传输(操作Linux服务器软件)
  5. 11月安全回顾:你造吗?短信验证码未必可靠
  6. Python 常用函数Logging
  7. 前端那些事之时间轴篇
  8. 一个百分号%引起的事故
  9. 判断登陆权限的操作,登录后调到之前所操作的地址。
  10. eclipse提示打不开java虚拟机