Vue.js2.0开发环境搭建(二)

转载自  Vue.js 2.0从入门到放弃---入门实例(二)

前面一篇博客介绍了从零开始准备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如下:
<!-- 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组件是用来控制页面切换的动画用的,transitionName绑定到的是main.js中的data中的transitionName字段。


修改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, // 在vue实例配置中,用routerwatch: {// 监视路由,参数为要目标路由和当前页面的路由'$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('/').lengththis.transitionName = toDepth < fromDepth ? 'slide_back' : 'slide'// 根据路由深度,来判断是该从右侧进入还是该从左侧进入}}
})

HomeHeader.vue代码
<!-- 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>

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>

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>

Home.vue代码
<!-- Home.vue -->
<template><div class="container"><!-- 由于html不区分大小写,所以js中驼峰命名方式在html中要改成用短横线连接的形式 --><home-header></home-header><div class="content"><ul class="cont_ul"><listv-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>

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>

最后,差点忘了,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://www.mzph.cn/news/328052.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

工程打包是什么意思_太生动形象了!500个建筑施工3D动画演示,施工工艺一目了然,零基础工程人也能看懂...

在建筑行业干了这么多年&#xff0c;老杨深知其中的艰辛。刚毕业的时候去了中建&#xff0c;那时候带我的老师傅很忙&#xff0c;天天都让看书&#xff0c;看得头晕眼花&#xff0c;不懂的地方也不好意思去问&#xff0c;后来还是一个同事给了这500个建筑施工3D动画演示&#x…

使用 dotnet watch 开发 ASP.NET Core 应用程序

原文&#xff1a;Developing ASP.NET Core applications using dotnet watch作者&#xff1a;Victor Hurdugaci翻译&#xff1a;谢炀(Kiler)校对&#xff1a;刘怡(AlexLEWIS)、许登洋(Seay) 介绍 dotnet watch 是一个开发阶段在源文件发生变动的情况下使用 dotnet 命令的工具。…

蓝桥杯JAVA---2013---B----世纪末的星期

2013 一、世纪末的星期 方法一 package com.kuang.Test; import java.util.Calendar; public class Test{ public static void main(String[] args) {Calendar calendar Calendar.getInstance(); //获取Calendar类的实例for(int year 1999; year < 10000; year 100) …

PL/SQL编程基本概念

/* pl/sql编程 */--pl/sql块的结构 declare --声明部门&#xff1a;在此声明pl/sql用到的变量、类型以及游标&#xff0c;以及局部的存储过程和函数 begin--执行部分&#xff1a;过程及sql语句&#xff0c;即程序的组成部分 exception --异常处理部分&#xff1a;错误处理 end;…

Vue.js2.0开发环境搭建(三)

转载自 Vue.js2.0从入门到放弃---入门实例&#xff08;三&#xff09;今天就来简单说一下vue-resource&#xff0c;这是vue的一个与服务器端通信的HTTP插件&#xff0c;用来从服务器端请求数据。话不多说&#xff0c;直接上干货吧。这里PS一下&#xff0c;有人反映之前的代码下…

controller如何保证当前只有一个线程执行_聊聊Spring线程安全,读完之后,大部分程序员收藏了......

Spring作为一个IOC/DI容器&#xff0c;帮助我们管理了许许多多的“bean”。但其实&#xff0c;Spring并没有保证这些对象的线程安全&#xff0c;需要由开发者自己编写解决线程安全问题的代码。Spring对每个bean提供了一个scope属性来表示该bean的作用域。它是bean的生命周期。例…

.NET Core 使用 grpc 实现微服务

GRPC 是Google发布的一个开源、高性能、通用RPC&#xff08;Remote Procedure Call&#xff09;框架。提供跨语言、跨平台支持。以下以一个.NET Core Console项目演示如何使用GRPC框架。 一、定义服务 通过proto定义一个数学计算服务&#xff0c;其中包括两个服务方法&#xff…

范式 第一 第二 第三范式

第一范式&#xff08;每个数据项不可分&#xff09; 如果一个关系模式R的所有属性都是不可分的基本数据项&#xff0c;则R∈1NF&#xff08;即R符合第一范式&#xff09;。 第二范式 &#xff08;没有部分依赖&#xff09; 若关系模式R∈1NF&#xff08;即R符合第一范式&a…

Vue.js2.0开发环境搭建(四)

转载自 vuejs2.0从入门到放弃--入门实例&#xff08;四&#xff09;最近&#xff0c;很多小伙伴有疑惑&#xff0c;想学vuejs必须先了解复杂的构建工具和命令行操作吗&#xff01;&#xff01;答案是否定的&#xff01; 对于很多做前端的同学&#xff0c;涉及到命令行和构建工…

微信小程序父级之间的传值_微信小程序自定义组件封装及父子间组件传值的方法...

首先在我们可以直接写到需要的 page 中&#xff0c;然后再进行抽取组件&#xff0c;自定义组件建议wxzx-xxx命名例如&#xff0c;我们封装的组件名为 **wxzx-loadmorewxzx-loadmore.wxml正在加载{{tip}}这里就是把index.wxml中的需要封装成组件的代码原样copy过来wxzx-loadmore…

[公测]微信小程序设计指南文档

微信小程序开放了。不要在意名额&#xff0c;一定要加大专注度。并保持良好的想法以及意识&#xff0c;扩大认知范围&#xff0c;这样才能占得先机。程序上的事我不懂&#xff0c;设计文档还是有必要看一看。文档并没有讲如何更漂亮。只是从人性化的角度去讲&#xff0c;如何让…

多线程----join插队

package com.kuang.demo05; public class TestJoin implements Runnable {Overridepublic void run() {for (int i 0; i <10 ; i) {System.out.println("VIP线程来插队了&#xff01;&#xff01;&#xff01;"i);}}public static void main(String[] args) thro…

联通 培训 c班还 20190814

看我的ppt是没有很多文字的 文字都在心里 电脑比较旧 可以装一个Linux 还能用 还是装xp把 电脑旧可以在咸鱼上买一个ssd&#xff0c;还能用很久。 Linux 目录每个用户都一样 不可以修改 ps -ef | sudo service sudo 授权 一般都是普通用户 docker 启动就类似模拟…

Vue开源项目库汇总

转载自 Vue开源项目库汇总最近做了一个Vue开源项目库汇总&#xff0c;里面集合了OpenDigg 上的优质的Vue开源项目库&#xff0c;方便移动开发人员便捷的找到自己需要的项目工具等&#xff0c;感兴趣的可以到GitHub上给个star。 UI组件 element ★9305 - 饿了么出品的Vue2的web…

PL/SQL经典练习

/* PL/SQL编程*/--先把scott里面的表弄到test表空间里面来 CREATE TABLE EMP ASSELECT * FROM SCOTT.EMP; CREATE TABLE DEPT ASSELECT * FROM SCOTT.DEPT; /* 上机1 */ --&#xff08;1&#xff09;计算King所交税金DECLARE V_SHUIJIN NUMBER; --应交税金V_SA…

alertmanager 告警恢复_Prometheus配置企业微信告警

kubernetes operator安装的&#xff0c;如果不会可看上一篇文章前提&#xff1a;创建企业微信&#xff0c;创建应用然后配置altermanager.yamlglobal:resolve_timeout: 5m receivers: - name: wechatwechat_configs:- agent_id: "100000x"api_secret: Nm7PRrxxxxG8Ep…

IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API

IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API。 使用IdentityServer4 来实现使用客户端凭据保护ASP.NET Core Web API 访问。 IdentityServer4 GitHub: https://github.com/IdentityServer/IdentityServer4 IdentityServer 框架支持以下功能&…

JAVA多线程总结(笔记)

线程的特点 线程就是独立的执行路径&#xff1b;在线程运行时&#xff0c;即使没有自己创建线程&#xff0c;后台也会有多个线程&#xff0c;如主线程&#xff0c;gc线程&#xff1b;main()称之为主线程&#xff0c;为系统的入口&#xff0c;用于执行整个程序&#xff1b;在一…

很有道理的内容

男生选女朋友最看重的是什么? 病毒营销陈轩 被赞同30万&#xff0c;被收藏24万&#xff0c;顶级病毒营销专家&#xff0c;加个人微信送书 12,540 人也赞同了该回答 有女孩给我发私信&#xff1a; “我是个很好的女孩&#xff0c;漂亮身材好&#xff0c;白领一枚&#xff0c…

学python后做什么工作好_学习完Python课程后可以做什么工作?

Python作为人工智能、大数据的首选编程语言&#xff0c;也是进入编程世界的理想选择&#xff0c;已经成为了大家都在追求学习的语言&#xff0c;那么学习Python之后到底可以做什么呢?为您详细的介绍一下。什么是Python?Python是一种面向对象解释型计算机程序设计语言。而且Py…