vue进阶 --- 实例演示

来源:互联网 发布:如何筛选重复数据 编辑:程序博客网 时间:2024/06/05 03:04

  这篇博客将通过一个实例来对vue构建项目的过程有一个了解。

转自http://www.cnblogs.com/zhuzhenwei918/p/6822964.html

  主要用到的知识点如下所示:

  1. vue-router 2.0路由配置
  2. router-view 和 router-link的使用
  3. transition控制页面的跳转
  4. .vue后缀的单文件组件

 

调整目录结构

  我们先用vue-cli构建项目,然后将 src 目录下的APP.vue删除,然后添加一个pages文件夹,这个文件夹的目的在于存放页面, 页面也是组件,但是在components下的不是一个完整的页面,而pages下的组件是一个页面组件。这样结构更清晰一些。

  

 

.vue后缀的单文件组件

  

  这就是我们最终希望做出来的效果图,其中的组件包括homeHeader和list,他们都是组件,都可以用.vue文件来表示。

  然后我们把HomeHeader.vue和DetailHeader.vue以及List.vue放在components下,因为他们都是一个页面的一部分。 接着把 Home.vue 和 Detail.vue 组件放在pages下,因为这两个是页面。 目录结构如下所示:

  

  OK! 组件的架构大体就是这样的了,接着,我们通过List.vue来看看单页面组件是如何的。

  提示: 写vue文件时,最好先安装vue高亮插件,这样可以提高我们的编码效率。

  

复制代码
<template>  <li class="sec-li">    <router-link to="/detail" class="link">      <div class="img-wrap">        <img src="../assets/img/book.jpg" alt="img">      </div>      <p class="book-name">{{title}}</p>      <p class="book-price">¥{{price}}元</p>    </router-link>  </li></template><style scoped>  .sec-li {    float: left;    width: 50%;    margin-bottom: 0.1rem;  }  .link {    display: block;    padding: 0.3rem 0;    text-align: center;  }</style><script>  export default {    props: ['price', 'title']  }</script>
复制代码
  • 其中template就是用于存放html的地方,注意: template下只能有一个标签。 和react是类似的。
  • style是来用存放css样式的,也可以使用sass和less,只要安装相应的包来编译即可。 其中的scoped属性可以让css样式只作用在这个组件之中,这样就不会影响到其他的组件了。
  • script中的js用了es6的语法,导出了对象,其中的props用于父组件像子组件传递数据。

 

使用vue-router2.0

  通过vue的目的是创建单页面应用,所以就没有了页面的跳转,而是组件的跳转,要实现组件的跳转,我们就要用到vue-router了。

  首先,我们可以看到packag.json中是没有vue-router的,所以我们需要自己来安装vue-router,即npm install vue-router --save。 

  router-view是用来实现路由内容的地方,在这里,会通过路由不停地切换routr-view中的内容,这也就是vue创建单页面应用的内在。 

  (注意:下面这段代码是处在根目录下的index.html中的一部分,也就是说,整个页面就这么一个html文件,所以称为单页面应用)

<div id="app">  <router-view></router-view></div>

  router-link相当于a标签,在点击router-link下的元素的时候,我们就可以将to所指向的组件渲染到router-view中。 

   

 

跳转页面动画

  另外,我们在根目录下的index.html中可以设置跳转动画如下所示:

复制代码
      /* 跳转页面动画 */.slide-enter,        .slide_back-enter {            position: absolute;            width: 100%;        }        .slide-leave,        .slide_back-leave {            position: absolute;            width: 100%;        }        .slide-enter-active,        .slide_back-enter-active {            transition: all 0.3s linear;        }        .slide-leave-active {            position: absolute;            transition: all 0.3s linear;            transform: translate(-100%);        }        .slide-enter{            transform: translateX(100%);        }        .slide_back-leave-active {            position: absolute;            transition: all 0.3s linear;            transform: translate(100%);        }        .slide_back-enter {            transform: translateX(-100%);        }  
复制代码

 

 

 

 

 

 最后贴上代码:

 1.根目录下的index.html

复制代码
<!DOCTYPE html><html>  <head>    <meta charset="utf-8">    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">    <title>first-vue</title>    <style type="text/css">        * { margin: 0; padding: 0; }        html,body { background: #eee; }        ul,li { list-style: none; }        a { text-decoration: none; }        img { vertical-align: middle; }        /* 跳转页面动画 */        .slide-enter,        .slide_back-enter {            position: absolute;            width: 100%;        }        .slide-leave,        .slide_back-leave {            position: absolute;            width: 100%;        }        .slide-enter-active,        .slide_back-enter-active {            transition: all 0.3s linear;        }        .slide-leave-active {            position: absolute;            transition: all 0.3s linear;            transform: translate(-100%);        }        .slide-enter{            transform: translateX(100%);        }        .slide_back-leave-active {            position: absolute;            transition: all 0.3s linear;            transform: translate(100%);        }        .slide_back-enter {            transform: translateX(-100%);        }    </style>  </head>  <body>    <div id="app">        <transition :name="transitionName">            <router-view></router-view>        </transition>    </div>    <script type="text/javascript">        // 计算html的font-size        (function(){            function resizeBaseFontSize(){                var rootHtml = document.documentElement,                    deviceWidth = rootHtml.clientWidth;                if(deviceWidth > 640){                    deviceWidth = 640;                }                rootHtml.style.fontSize = deviceWidth / 7.5 + "px";            }            resizeBaseFontSize();            window.addEventListener("resize", resizeBaseFontSize, false);            window.addEventListener("orientationchange", resizeBaseFontSize, false);        })();    </script>  </body></html>
复制代码

  这里的代码很简单,就是设置了transition和移动端字体的设置。其中 transition组件是用来控制页面切换的动画用的,transitionName绑定到的是main.js中的data中的transitionName字段。

2. src目录下的main.js代码如下:

复制代码
// main.js// 导入Vue,这个是必需的,在使用Vue之前,必须先导入import Vue from 'vue'// 导入 vue-router,并使用import VueRouter from 'vue-router'Vue.use(VueRouter)// 导入 pages 下的 Home.vue import Home from './pages/Home'import Detail from './pages/Detail'// 定义路由配置const routes = [    {        path: '/',        component: Home    },    {        path: '/detail',        component: Detail    }]// 创建路由实例const router = new VueRouter({    routes})// 创建 Vue 实例new Vue({  el: '#app',  data(){      return {          transitionName: 'slide'      }  },  router,  watch: {      // 监视路由,参数为要目标路由和当前页面的路由      '$route' (to, from){          const toDepth = to.path.substring(0, to.path.length-2).split('/').length          // 官方给出的例子为 const toDepth = to.path.split('/').length 由于现在只有两个路由路径'/'和'/detail'          // 按照官方给的例子,这两个路由路径深度都为 2 ,所以,这里稍作调整,不知道有什么不妥          // 但目前在这个demo中能正常运行,如果知道更好的方法,欢迎留言赐教          const fromDepth = from.path.substring(0, from.path.length-2).split('/').length          this.transitionName = toDepth < fromDepth ? 'slide_back' : 'slide'          // 根据路由深度,来判断是该从右侧进入还是该从左侧进入      }  }})
复制代码

 这里main.js首先引入了vue和vue-router,然后对router进行了设置,将router挂载到实例上,最后的watch路由实际上就是用来正确实现动画的效果的。不用也是可以的。

3.  HomeHeader.vue如下:

复制代码
<template>      <header class="header">          <div class="header_inner">              <div class="header_cont">主页</div>          </div>      </header>  </template>    <style>      .header {          height: 0.88rem;      }      .header_inner {          position: fixed;          top: 0;          left: 0;          right: 0;          z-index: 99;          max-width: 640px;          height: 0.88rem;          box-sizing: border-box;          margin: 0 auto;          padding: 0 0.24rem;          border-bottom: 0.02rem solid #80ccd6;          background-color: #fff;      }      .header_cont {          text-align: center;          padding: 0 0.4rem;          line-height: 0.86rem;          font-size: 15px;          overflow: hidden;          text-overflow: ellipsis;          white-space: nowrap;      }  </style>  
复制代码

 

4.  List.vue如下:

复制代码
<!-- List.vue --><template>    <li class="sec_li">        <router-link to="/detail" class="lp_li_a">            <div class="lp_li_imgWrap">                <img src="../assets/img/lp_01.jpg" alt="">            </div>            <p class="lp_li_name">{{ title }}</p>            <p class="lp_li_price">¥{{ price }}元</p>        </router-link>    </li></template><style scoped>    .sec_li {        float: left;        width: 50%;        margin-bottom: 0.1rem;    }    .lp_li_a {        display: block;        padding: 0.3rem 0;        margin: 0 0.05rem;        text-align: center;        background: #fff;    }    .lp_li_imgWrap {        padding: 0.24rem 0;    }    .lp_li_imgWrap > img {        width: auto;        height: 2.3rem;    }    .lp_li_name {        height: 0.5rem;        line-height: 0.5rem;        font-size: 16px;        color: #333;    }    .lp_li_price {        height: 0.5rem;        line-height: 0.5rem;        font-size: 16px;        color: #fb3b3b;    }</style><script>    export default {        props: ['price', 'title']    }</script>
复制代码

 

5. DetailHeader.vue如下:

复制代码
<!-- DetailHeader.vue -->  <template>      <header class="header">          <div class="header_inner flexWrap">              <div                   id="header_btn_nav"                   class="header_btn header_btn_back"                  v-on:click="goBack"                  >返回</div>              <div class="header_cont flex">详情</div>              <div class="header_btn header_btn_cart"></div>          </div>      </header>  </template>    <style>      .flexWrap {          display: -webkit-flex;          display: flex;      }      .flex {          flex: 1;      }      .header {          height: 0.88rem;      }      .header_inner {          position: fixed;          top: 0;          left: 0;          right: 0;          z-index: 99;          max-width: 640px;          height: 0.88rem;          box-sizing: border-box;          margin: 0 auto;          padding: 0 0.24rem;          border-bottom: 0.02rem solid #80ccd6;          background-color: #fff;      }      .header_btn {          width: 0.5rem;          height: 100%;          background-repeat: no-repeat;      }      .header_btn_back {          line-height: 0.86rem;      }      .header_cont {          text-align: center;          padding: 0 0.4rem;          line-height: 0.86rem;          font-size: 15px;          overflow: hidden;          text-overflow: ellipsis;          white-space: nowrap;      }      .header_btn:active {          opacity: 0.7;      }  </style>  <script>      export default {          methods: {              goBack(){                  window.history.back();              }          }      }  </script>  
复制代码

 

6. Home.vue如下:

复制代码
<!-- Home.vue -->  <template>      <div class="container">          <!-- 由于html不区分大小写,所以js中驼峰命名方式在html中要改成用短横线连接的形式 -->          <home-header></home-header>          <div class="content">              <ul class="cont_ul">                  <list                      v-for="item in items"                      :price="item.price"                      :title="item.title">                  </list>              </ul>          </div>      </div>  </template>  <style>      .container {          max-width: 640px;          margin: 0 auto;          overflow-x: hidden;      }      .cont_ul {          padding-top: 0.05rem;          margin: 0 -0.12rem;      }      .cont_ul:after {          content: "";          display: block;          width: 0;          height: 0;          clear: both;      }  </style>  <script>      // 导入要用到的子组件      import HomeHeader from '../components/HomeHeader'      import List from '../components/List'        export default {          data () {              return {                  items: [                      { price: "129.00", title: "大学" },                      { price: "256.00", title: "中庸" },                      { price: "399.00", title: "论语" },                      { price: "998.00", title: "孟子" },                      { price: "99.00", title: "道德经" },                      { price: "89.00", title: "老子" },                      { price: "188.00", title: "金刚经" },                      { price: "209.00", title: "易筋经" },                  ]              }          },          // 在components字段中,包含导入的子组件          components: {              HomeHeader,              List          }      }  </script>  
复制代码

 

这里值得注意的是: 我们需要使用import导入子组件。

7. Detail.vue如下:

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

 

同样,这里作为页面组件,我们也需要导入子组件。

 

注意:其中的 npm run dev 是在开发环境中使用, npm run build是在生产环境中使用。

 

  

 

  

 

 

 

 

 

 

参考文章

这里有vue项目和资料的汇总:https://segmentfault.com/q/1010000007073989/a-1020000007074331

原创粉丝点击