vue项目

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>
posted @ 2019-11-16 22:27  唐ceng  阅读(323)  评论(0编辑  收藏  举报