vue项目
一、uve目录结构
1.1 node_modules
npm 加载的项目依赖模块。
1.2 public
可以放置静态资源,任何放置在 public
文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。
1.3 src
这是开发使用的目录,几乎所有的操作都在这里进行。
assets: 放置一些图片,如logo等。
components: 目录里面放置组件文件
App.vue: 项目入口文件,也可以将组件写在这里
main.js: 项目的核心文件
1.4 package.json
项目配置文件。
1.5 README.md
项目的说明文档,markdown 格式
二、文件的具体配置(图书系统为例)
2.1 main.js
1.入口文件:加载vue、router、store等配置 以及 加载自定义配置(自己的js、css,第三方的js、css) 。
2.创建项目唯一根组件,渲染App.vue,挂载到index.html中的挂载点 => 项目页面显示的就是 App.vue 组件 。
3.在App.vue中设置页面组件占位符 。
4.浏览器带着指定 url链接 访问vue项目服务器,router组件就会根据 请求路径 匹配 映射组件,去替换App.vue中设置页面组件占位符。
eg: 请求路径 /user => 要渲染的组件 User.vue => 替换App.vue中的
2.2 App.vue
about标签没有用,删掉。样式没有用,删掉。
<template> <div id="app"> <!--提供一个视图组件占位符,占位符被哪个views下的视图组件替换,浏览器就显示哪个页面组件--> <router-view/> </div> </template>
2.3 router/index.js
路由规则表:注册页面组件,与url路径形成映射关系
// @ 代表 /src,也就是src项目绝对路径 // 文件后缀可以省略 import User from '@/views/User' import BookDetail from '@/views/BookDetail.vue' Vue.use(VueRouter); const routes = [ { path: '/', name: 'home', component: Home }, { path: '/index', redirect: '/' }, { path: '/user', name: 'user', component: User }, { path: '/book/detail/:pk', name: 'book-detail', component: BookDetail }, ];
2.4 view
.vue文件就是一个组件:html、css、js。
html由template标签提供:有且只有一个根标签。
css由style标签管理:style标签添加scope属性,保证样式只在该组件内部起作用(样式组件化)。
js由script标签管理:内部书写的就是组件{}语法,但是一定要导出 export default。
Home.vue:
<template> <div class="home"> <!--vue项目环境下,模板也受vue环境控制,使用标签支持大小写--> <!--使用导入的小组件--> <Nav></Nav> <div class="main"> <!-- key属性是为标签建立缓存的标识,不能重复,且在循环组件下,必须设置 --> <Book v-for="book in books" :book="book" :key="book.title" /> </div> <Footer></Footer> </div> </template> <script> // 1、导入要使用的小组件 import Nav from '@/components/Nav.vue' import Footer from '../components/Footer.vue' import Book from '../components/Book.vue' // 前台自己提供的静态资源,在传输后再使用(组件间交互),要才有require函数来加载资源 // let img1 = require('../assets/img/西游记.jpg'); let books = [ {id:1, img:require('../assets/img/西游记.jpg'), color:'red', title: '西游记', info: '西游记这本书写的好啊!里面有妖怪啊,主人公猴子死了啊!!!'}, {id:3, img:require('../assets/img/东游记.jpg'), color:'orange', title: '东游记', info: '东游记这本书写的好啊!里面都没有妖怪啊,有个球啊!!!'}, {id:4, img:require('../assets/img/西厢记.jpg'), color:'cyan', title: '西厢记', info: '西厢记不看过,内容也就那样吧!!!'}, {id:7, img:require('../assets/img/水浒传.jpg'), color:'yellow', title: '水浒传', info: '你看不懂,别看了,我也不讲了!!!'}, ]; export default { name: 'home', // 2、注册要使用的小组件 components: { Nav, Footer, Book, }, data() { return { books } } } </script>
User.vue:
<template> <div class="user"> <Nav /> <h1>用户页面</h1> <Footer /> </div> </template> <script> import Nav from '@/components/Nav.vue' import Footer from '../components/Footer.vue' export default { name: "User", components: { Nav, Footer, }, data(){ return { } }, methods: { } } </script> <style scoped> </style>
Book.vue
组件的生命周期钩子 :
一个组件,会在页面中渲染,也会销毁存放到内存(不渲染) => 加载组件到销毁组件 。从加载一个组件到销毁该组件,整个生命周期中存在很多特殊的时间节点(组件要创建了,创建成功了,要加载了,加载成功了, 要更新数据了,数据更新完毕了,要销毁了,销毁成功了),这些特殊的时间节点,vue都提供了对应的回调方法,来辅助完成在这些时间 节点需要完成的业务逻辑。
生命周期钩子函数书写的位置:钩子直接作为vue实例的成员。
<template> <div class="book-detail"> <div class="back" @click="backAction">返回</div> <p>{{ book }}</p> </div> </template> <script> let books_detail = { '1': {author: 'Owen', img:require('../assets/img/西游记.jpg'), color:'red', title: '西游记', info: '西游记这本书写的好啊!里面有妖怪啊,主人公猴子死了啊!!!'}, '3': {author: 'Jason', img:require('../assets/img/东游记.jpg'), color:'orange', title: '东游记', info: '东游记这本书写的好啊!里面都没有妖怪啊,有个球啊!!!'}, '4': {author: 'Tank', img:require('../assets/img/西厢记.jpg'), color:'cyan', title: '西厢记', info: '西厢记不看过,内容也就那样吧!!!'}, '7': {author: 'Egon', img:require('../assets/img/水浒传.jpg'), color:'yellow', title: '水浒传', info: '你看不懂,别看了,我也不讲了!!!'}, }; export default { name: "BookDetail", data() { return { num: 10, book: {} } }, methods: { backAction() { // go的参数是正负整数,代表历史记录前进或后退几步 this.$router.go(-1); } }, beforeCreate() { window.console.log('该组件要被创建了'); window.console.log(this.num); }, // 最常用的钩子函数:组件加载后,可以请求后台数据,更新组件数据;组件间路由传参的值获取 created() { window.console.log('该组件已经创建了'); window.console.log(this.num); // 获取跳转到详情页的当前书本id,再根据id获得书本的详细信息 // window.console.log(this.$router); // $router管理路由跳转的 // window.console.log(this.$route); // $route管理路由数据的 let pk = this.$route.params.pk; // window.console.log(pk in {'1': 100, '2': 200}); if (!(pk in books_detail)) { this.$router.go(-1); // 数据不存在,返回 } this.book = books_detail[pk]; }, destroyed() { window.console.log('该组件已经销毁了') } } </script> <style scoped> .back { cursor: pointer; width: 60px; text-align: center; background-color: lightslategrey; } </style>
2.5 components
Footer.vue:
<template> <div class="footer"> <p>这是页脚</p> </div> </template> <script> export default { name: "Footer" } </script> <style scoped> .footer { width: 100%; height: 120px; background-color: lightslategrey; } .footer p { line-height: 120px; text-align: center; } </style>
Nav.vue:
<template> <ul class="nav"> <li> <!--router-link会被解析为a标签,但是不能直接写a,因为a跳转回刷新页面--> <!--<a href="/">主页</a>--> <router-link to="/">主页</router-link> </li> <li> <!--<a href="/user">用户</a>--> <router-link to="/user">用户</router-link> </li> </ul> </template> <script> export default { name: "Nav" } </script> <style scoped> .nav { width: 100%; height: 60px; background-color: aquamarine; list-style: none; margin: 0; padding: 0; } .nav li { width: 80px; text-align: center; float: left; } .nav li:hover { background-color: antiquewhite; cursor: pointer; } a { color: black; text-decoration: none; display: block; width: 80px; line-height: 60px; } /*router-link渲染的a激活时的状态*/ a.router-link-exact-active { color: pink; } </style>
Book.vue:
<template> <div class="book"> <div class="left"> <!--<div class="img" :style="{backgroundColor: book.color}"></div>--> <!-- 资源的加载才有相对路径 --> <img class="img" :src="book.img" alt=""> </div> <div class="right"> <!--<h2 @click="goDetail(book.id)">{{ book.title }}</h2>--> <h2> <!--<router-link :to="'/book/detail/' + book.id">{{ book.title }}</router-link>--> <router-link :to="{name: 'book-detail', params: {pk: book.id}}">{{ book.title }}</router-link> </h2> <p>{{ book.info }}</p> </div> </div> </template> <script> export default { props: ['book'], data() { return { color: 'red', title: '西游记', info: '西游记这本书写的好啊!里面有妖怪啊,主人公猴子死了啊!!!' } }, methods: { goDetail(id) { window.console.log(id); window.console.log(this.book.id); } } } </script> <style scoped> .img { width: 360px; height: 160px; } .left, .right { float: left; } .book:after { display: block; content: ''; clear: both; } .book { margin: 10px 0; border: 1px solid rgba(0,0,0,0.3); } .right { margin-left: 20px; } h2 { cursor: pointer; } </style>