vue进阶 --- 实例演示
这篇博客将通过一个实例来对vue构建项目的过程有一个了解。
主要用到的知识点如下所示:
- vue-router 2.0路由配置
- router-view 和 router-link的使用
- transition控制页面的跳转
- .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: %;
margin-bottom: .1rem;
}
.link {
display: block;
padding: .3rem ;
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: %;
}
.slide-leave,
.slide_back-leave {
position: absolute;
width: %;
}
.slide-enter-active,
.slide_back-enter-active {
transition: all .3s linear;
}
.slide-leave-active {
position: absolute;
transition: all .3s linear;
transform: translate(-%);
}
.slide-enter{
transform: translateX(%);
}
.slide_back-leave-active {
position: absolute;
transition: all .3s linear;
transform: translate(%);
}
.slide_back-enter {
transform: translateX(-%);
}
最后贴上代码:
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: ; padding: ; }
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: %;
}
.slide-leave,
.slide_back-leave {
position: absolute;
width: %;
}
.slide-enter-active,
.slide_back-enter-active {
transition: all .3s linear;
}
.slide-leave-active {
position: absolute;
transition: all .3s linear;
transform: translate(-%);
}
.slide-enter{
transform: translateX(%);
}
.slide_back-leave-active {
position: absolute;
transition: all .3s linear;
transform: translate(%);
}
.slide_back-enter {
transform: translateX(-%);
}
</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 > ){
deviceWidth = ;
}
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(, to.path.length-).split('/').length
// 官方给出的例子为 const toDepth = to.path.split('/').length 由于现在只有两个路由路径'/'和'/detail'
// 按照官方给的例子,这两个路由路径深度都为 2 ,所以,这里稍作调整,不知道有什么不妥
// 但目前在这个demo中能正常运行,如果知道更好的方法,欢迎留言赐教
const fromDepth = from.path.substring(, from.path.length-).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: .88rem;
}
.header_inner {
position: fixed;
top: ;
left: ;
right: ;
z-index: ;
max-width: 640px;
height: .88rem;
box-sizing: border-box;
margin: auto;
padding: .24rem;
border-bottom: .02rem solid #80ccd6;
background-color: #fff;
}
.header_cont {
text-align: center;
padding: .4rem;
line-height: .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: %;
margin-bottom: .1rem;
}
.lp_li_a {
display: block;
padding: .3rem ;
margin: .05rem;
text-align: center;
background: #fff;
}
.lp_li_imgWrap {
padding: .24rem ;
}
.lp_li_imgWrap > img {
width: auto;
height: .3rem;
}
.lp_li_name {
height: .5rem;
line-height: .5rem;
font-size: 16px;
color: #;
}
.lp_li_price {
height: .5rem;
line-height: .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: ;
}
.header {
height: .88rem;
}
.header_inner {
position: fixed;
top: ;
left: ;
right: ;
z-index: ;
max-width: 640px;
height: .88rem;
box-sizing: border-box;
margin: auto;
padding: .24rem;
border-bottom: .02rem solid #80ccd6;
background-color: #fff;
}
.header_btn {
width: .5rem;
height: %;
background-repeat: no-repeat;
}
.header_btn_back {
line-height: .86rem;
}
.header_cont {
text-align: center;
padding: .4rem;
line-height: .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: auto;
overflow-x: hidden;
}
.cont_ul {
padding-top: .05rem;
margin: -.12rem;
}
.cont_ul:after {
content: "";
display: block;
width: ;
height: ;
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: .24rem;
font-size: 12px;
}
img {
display: block;
width: %;
margin: auto .2rem;
}
p {
font-size: 14px;
line-height: .5rem;
text-align: justify;
padding-bottom: .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
vue进阶 --- 实例演示的更多相关文章
- ASP.NET Core 6框架揭秘实例演示[14]:日志的进阶用法
为了对各种日志框架进行整合,微软创建了一个用来提供统一的日志编程模式的日志框架.<日志的基本编程模式>以实例演示的方式介绍了日志的基本编程模式,现在我们来补充几种"进阶" ...
- ASP.NET Core 6框架揭秘实例演示[12]:诊断跟踪的进阶用法
一个好的程序员能够在系统出现问题之后马上定位错误的根源并找到正确的解决方案,一个更好的程序员能够根据当前的运行状态预知未来可能发生的问题,并将问题扼杀在摇篮中.诊断跟踪能够帮助我们有效地纠错和排错&l ...
- VUE进阶(路由等)
初级教程:http://www.cnblogs.com/dmcl/p/6137469.html VUE进阶 自定义指令 http://cn.vuejs.org/v2/guide/custom-dire ...
- Vue 进阶教程之:详解 v-model
分享 Vue 官网教程上关于 v-model 的讲解不是十分的详细,写这篇文章的目的就是详细的剖析一下, 并介绍 Vue 2.2 v-model改进的地方,然后穿插的再说点 Vue 的小知识. 在 V ...
- Vue进阶篇
前引 今天是2018年12月30,虽不是2018年的最后一天,但是却是自己在2018年写的最后一篇博客了,昨天下班在地铁上闲来无事,翻起了关注的一些公众号发的技术博文,里面就提到写博客的重要性,其实这 ...
- 《Vue 进阶系列之响应式原理及实现》
https://www.bilibili.com/video/av51444410/?p=5 https://github.com/amandakelake/blog/issues/63 https: ...
- SSO之CAS单点登录实例演示
本文目录: 一.概述 二.演示环境 三.JDK安装配置 四.安全证书配置 五.部署CAS-Server相关的Tomcat 六.部署CAS-Client相关的Tomcat 七. 测试验证SSO 一.概述 ...
- Thrift入门及Java实例演示<转载备用>
Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...
- 原生JS编写的照片墙效果实例演示特效
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
随机推荐
- shape不同版本这间的兼容
在做那个只有左边上面是圆角和只有右边下边是圆角的时候,出现了一个问题,那就是在android3.0以前,android:bottomLeftRadius与android:bottomRightRadi ...
- WebGoat系列实验Access Control Flaws
WebGoat系列实验Access Control Flaws Using an Access Control Matrix 在基于角色的访问控制策略中,每个角色都代表了一个访问权限的集合.一个用户可 ...
- 关于AJAX异步加载节点无法触发点击事件问题的解决方式
做练习的过程中遇到一个问题,使用AJAX异步新增一个节点,无法触发点击事件,经过查阅之后知道一个方式,使用JS的委托事件,在此做一个记录. $(document).on('click', '.recr ...
- w2008 R2 401 - 未授权: 由于凭据无效,访问被拒绝。
1.打开服务器的"IIS信息服务管理器"-->选择你发布的网站-->选择功能视图中的"身份验证"-->右键匿名身份验证,选择"编辑& ...
- docker网络模式----入门docker的难点
众所周知,现在docker是轻量级虚拟化的典型代表!这段时间想要建立一个分布式系统,但是手头上主机没那么多,所以使用docker进行虚拟化,但是在使用的过程中对网络这一部分是一直不太理解,特别找了一篇 ...
- 「JOI 2017 Final」JOIOI 王国
「JOI 2017 Final」JOIOI 王国 题目描述 题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」 JOIOI 王国是一个 H ...
- Django之request对象
在view.py的函数中.我们的函数中第一个参数都是request.在request中有一些信息,比如正在加载这个页面的用户是谁,或者是用什么浏览器之类的.这对于我们网站的管理是很有用处的. requ ...
- loj #2037. 「SHOI2015」脑洞治疗仪
#2037. 「SHOI2015」脑洞治疗仪 题目描述 曾经发明了自动刷题机的发明家 SHTSC 又公开了他的新发明:脑洞治疗仪——一种可以治疗他因为发明而日益增大的脑洞的神秘装置. 为了简单起见 ...
- P2387 [NOI2014]魔法森林 LCT维护最小生成树
\(\color{#0066ff}{ 题目描述 }\) 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 ...
- Warning: Call to 'toArray()' with pre-sized array argument 'new String[list.size()]'
当使用如下代码将List转换为Array类型时: List<String> list = new ArrayList<>(); String[] array = list.to ...