一个简单的Vue项目的创建
- 创建一个UserList.vue组件
 

- 在App.vue中使用该组件
 
- 使用组件的第一步,导入组件
 - 使用组件的第二部,申明这个组件
 - 使用组件的第三步:引用组件
 

结果:

事件和插值语法
<template>
<div>
    <!-- template只允许有一个唯一的孩子 -->
    <h1>这是一个一级标题</h1>
    <div>{{ username }}</div>
    <div>性别{{ sex }} , 年龄{{ age }}</div>
    <button @click="btnClick1">点我触发事件</button>
    <hr>
    <ul>
        <li v-for="(user,index) of userList" :key="user.id">
            {{ index }}----{{ user.username }}
    </li>
    </ul>
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
                username:'ZhangSan',
                sex:'男',
                age:18,
                userList:[
                    {
                        id:1,
                        username:'ZhangSan',
                        password:'123'
                    },
                    {
                        id:2,
                        username:'LiSi',
                        password:'456'
                    },
                    {
                        id:3,
                        username:'WangWu',
                        password:'789'
                    }
                ]
            }
        },
        methods:{
            btnClick1(){
                console.log("Hello Vue");
            }
        }
    }
</script>
 
结果:

ref属性
<!--ref属性的作用就是找组件对象
	这个对象是一个js对象	
-->
<!-- 给h1添加一个ref="h1" -->
<h1 ref="h1">这是一个一级标题</h1>
methods:{
	btnClick1(){
		var h1Element=this.$refs.h1
		console.log("找到的组件是"+h1Element.innerText)
	}
}
 
props
接收参数
- App.vue
 
<template>
<div id="app">
    <!-- 使用组件的第三步:引用组件 -->
    <user-list name="ZhangSan" :age="18" title="个人信息"></user-list> 
    </div>
</template>
<script>
    // 使用组件的第一步,导入组件
    import UserList from './components/UserList.vue';
    export default {
        name: 'App',
        //使用组件的第二部,申明这个组件
        components: {
            UserList
        }
    }
</script>
 
- UserList.vue
 
<template>
<div>
    <h1>{{ title }}</h1>
    <h1>{{ age }}</h1>
    <h1>{{ name }}</h1>
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
            }
        },
        //第一种方式:数组式接收数据
        //props:["name","title","age"]
        //第二种方式:对象式
        // props:{
        //   name:String,
        //   age:Number,
        //   title:String
        // }
        //第三种方式
        props:{
            name:{
                type:String,
                required:true
            },
            age:{
                type:Number,
                requestd:true
            },
            title:{
                type:String,
                required:true
            }
        }
    }
</script>
 
scoped
添加到style中,只有当前组件生效
 
<template>
<div>
    <h1>{{ title }}</h1>
    <h1>{{ age }}</h1>
    <h1>{{ name }}</h1>
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
            }
        },
        //第一种方式:数组式接收数据
        //props:["name","title","age"]
        //第二种方式:对象式
        // props:{
        //   name:String,
        //   age:Number,
        //   title:String
        // }
        //第三种方式
        props:{
            name:{
                type:String,
                required:true
            },
            age:{
                type:Number,
                requestd:true
            },
            title:{
                type:String,
                required:true
            }
        }
    }
</script>
<style scoped>
    div{
        color: aqua;
    }
</style>
 
结果:

localstorage和sessionstorage
<template>
<div>
    <button @click="saveLocalStorage">向localstorage中存数据</button><br><br>
    <button @click="deleteLocalStorage">向localstorage中删除数据</button><br><br>
    <button @click="getLocalStorage">向localstorage中获取数据</button><br><br>
    <hr>
    <button @click="saveSessionStorage">向sessionstorage中存数据</button><br><br>
    <button @click="deleteSessionStorage">向sessionstorage删除数据</button><br><br>
    <button @click="getSessionStorage">向sessionstorage获取数据</button><br><br>
    </div>
</template>
<script>
    export default { 
        name: 'BrowerStorage',
        methods:{
            saveLocalStorage(){
                //向LocalStorage存数据
                localStorage.setItem("key1","val1")
            },
            deleteLocalStorage(){
                //LocalStorage删除数据
                localStorage.removeItem("key1")
            },
            getLocalStorage(){
                //获取LocalStorage数据
                var val = localStorage.getItem("key1")
                console.log(val)
            },
            saveSessionStorage(){
                //向SessionStorage存数据
                sessionStorage.setItem("key2","val2")
            },
            deleteSessionStorage(){
                //删除SessionStorage数据
                sessionStorage.removeItem("key2")
            },
            getSessionStorage(){
                //获取SessionStorage的数据
                var val = sessionStorage.getItem("key2")
                console.log(val)
            }
        }
    }
</script>
 
全局事件总线
- 在main.js中安装全局事件总线
 
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
    render: h => h(App),
    //生命周期的第一个钩子函数
    beforeCreate() {
        Vue.prototype.$bus = this //安装全局事件总线
    },
}).$mount('#app')
 
- 在userList.vue中进行监听传过来的消息
 
<template>
<div>
    我喜欢的语言是:{{ language }}
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
                language:''
            }
        },
        mounted(){
            //监听传递过来的消息
            this.$bus.$on("changeName",(newtext)=>{
                this.language=newtext;
            })
        },
        beforeDestroy(){
            this.$bus.$off ("changeName");
        }
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- 在userSchool.vue中发送数据
 
<template>
<div>
    <button @click="btnClick">点击查看</button>
    </div>
</template>
<script>
    export default { 
        name: 'UserSchool',//名字是可以随便写的
        methods:{
            btnClick(){
                //向某一个频道发送数据
                this.$bus.$emit("changeName","Java")
            }
        }
    }
</script>
 
结果:

代理服务器的配置和Axios的请求发送
什么是跨域

如何解决跨域问题
- 在服务器端写一个过滤器,将响应头设置为可信赖
 - 在Vue端设置代理服务器
 - 给整个tomcat设置允许跨域 实际的操作也是设置相应资源可信赖
 

代理服务器的配置(vue.config.js)
- 在vue.config.js中配置
 
module.exports = {
    assetsDir: 'static',
    productionSourceMap: false,
    devServer: {
        proxy: {
            '/api':{ 
                target:'http://127.0.0.1:9090',
                changeOrigin:true,
                pathRewrite:{
                    '/api':''
                }
            }
        }
    }
}
 

Axios的请求发送
- 请求发送第一步:导包
 


- 客户端发送请求(不带参数的GET请求)
 

- 服务器端响应
 

package com.wz.practice.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
}
 
package com.wz.practice.servlet;
import com.alibaba.fastjson.JSON;
import com.wz.practice.pojo.User;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(urlPatterns = "/users")
public class UserServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("获取到的数据是:username:"+username+"password"+password);
        //向客户端返回json格式的数据
        User user = new User(1, "用户名数据", "密码数据");
        String data = JSON.toJSONString(user);
        //向客户端返回数据
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.write(data);
        writer.flush();
        writer.close();
    }
}
 
结果:

- 带参数的GET请求
 
ProxyAxios.vue
<template>
<div>
    <button @click="btnClick1">发送get请求不带参数 </button><br><br>
    <button @click="btnClick2">发送get请求带参数   </button><br><br>
    <button @click="btnClick3">发送post请求不带参数</button><br><br>
    <button @click="btnClick4">发送post请求带参数  </button><br><br>
    </div>
</template>
<script>
    export default { 
        name: 'ProxyAxios',
        methods:{
            btnClick1(){
                //发送get请求不带参数
                this.$axios.get("/api/users").then(
                    response=>{
                        var val = response.data;
                        console.log("获取到的数据是:"+val)
                    },error=>{
                        console.log("失败"+error.message)
                    }
                )
            },
            btnClick2(){
                //发送get请求带参数
                this.$axios.get("/api/users",{
                    params:{
                        username:"ZhangSan",
                        password:"123"
                    }
                }).then(
                    response=>{
                        var val = response.data;
                        console.log("获取到的数据是:"+val)
                    },error=>{
                        console.log("失败"+error.message)
                    }
                )
            },
            btnClick3(){
            },
            btnClick4(){
            }
        }
    }
</script>
 
结果:


- POST请求不带参数
 

- POST请求带参数

 

插槽slot
基本使用
- 在userList.vue中定义一个slot
 
<template>
<div>
    <h1>这里是userList的页面</h1>
    <!-- 在这里可以定义一个插槽,插槽就是占位符 -->
    <slot>
        这里就是插槽要显示内容的地方
    </slot>
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
                language:''
            }
        },
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- 在App.vue中使用
 
<template>
<div id="app">
    <user-list>
        <div>插槽的具体使用者</div>
    </user-list>
    </div>
</template>
<script>
    // 使用组件的第一步,导入组件
    import UserList from './components/UserList.vue';
    export default {
        name: 'App',
        //使用组件的第二部,申明这个组件
        components: {
            UserList 
        }
    }
</script>
 
结果:

具名插槽
<template>
<div>
    <h1>这里是userList的页面</h1>
    <!-- 在这里可以定义一个插槽,插槽就是占位符 -->
    <slot name="slot1">
        这里就是插槽要显示内容的地方
    </slot>
    <hr>
    <slot name="slot2">
        这是第二个插槽
    </slot>
    </div>
</template>
<script>
    export default { 
        name: 'UserList',//名字是可以随便写的
        data(){
            return{
                language:''
            }
        },
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
<template>
<div id="app">
    <user-list>
        <div slot="slot1">插槽的具体使用者AAAA</div>
        <div slot="slot2">插槽的具体使用者BBBB</div>
    </user-list>
    </div>
</template>
<script>
    // 使用组件的第一步,导入组件
    import UserList from './components/UserList.vue';
    export default {
        name: 'App',
        //使用组件的第二部,申明这个组件
        components: {
            UserList 
        }
    }
</script>
 
结果:

路由
路由是控制页面跳转的
- 导包
 

- 编写main.js
 

- HomePage.vue
 
<template>
<div style="background-color: pink;">
    <h1>这里是Home页面</h1>
    <hr>
    <div class="row">
        <div class="col-xs-2 col-xs-offset-2">
            <div class="list-group">
                <!-- Vue中借助router-link标签实现路由的切换 -->
                <router-link class="list-group-item" active-class="active" to="/about">About</router-link> 
                <router-link class="list-group-item" active-class="active" to="/message">Message</router-link>
    </div>
    </div>
    </div>
    <!-- 这个div主要是内容展示 -->
    <router-view></router-view>
    </div>
</template>
<script>
    export default { 
        name: 'HomePage'
    }
</script>
<style scope>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- AboutPage.vue
 
<template>
<div style="width: 100%; height: 200px; background: skyblue;">
    这是About页面
    </div>
</template>
<script>
    export default { 
        name: 'AboutPage',
        data(){
            return{
                language:''
            }
        },
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- MessagePage.vue
 
<template>
<div style="width: 100%; height: 200px; background: rosybrown;">
    这是Message页面
    </div>
</template>
<script>
    export default { 
        name: 'MessagePage'
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- App.vue
 
<template>
<div id="app">
    <home-page></home-page>
    </div>
</template>
<script>
    // 使用组件的第一步,导入组件
    import HomePage from './components/HomePage.vue';
    export default {
        name: 'App',
        //使用组件的第二部,申明这个组件
        components: {
            HomePage
        }
    }
</script>
 
结果:

多级路由
需求:在Message页面中增加两个按钮,点击之后,在Message页面中显示内容
- DetailPage.vue
 
<template>
<div style="width: 100%; height: 200px; background: yellowgreen;">
    这是Detail页面
    </div>
</template>
<script>
    export default { 
        name: 'DetailPage',
        data(){
            return{
                language:''
            }
        },
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- NewsPage.vue
 
<template>
<div style="width: 100%; height: 200px; background: palevioletred;">
    这是News页面
    </div>
</template>
<script>
    export default { 
        name: 'NewsPage',
        data(){
            return{
                language:''
            }
        },
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
- 在index.js中配置路由
 
//把路由导进来
import VueRouter from "vue-router";
//将要配置的路由的组件引进来(点击之后要跳转的都要配)
import AboutPage from "../components/AboutPage"
import MessagePage from "../components/MessagePage"
import DetailPage from "../components/DetailPage"
import NewsPage from "../components/NewsPage"
//创建并暴露一个路由器
export default new VueRouter({
    routes:[
        {
            path:'/about',
            component:AboutPage
        },
        {
            path:'/message',
            component:MessagePage,
            //在那里显示就在哪里配置
            children:[
                {
                    path:"detail",
                    name:"detail",
                    component:DetailPage
                },
                {
                    path:"news",
                    name:"news",
                    component:NewsPage
                }
            ]
        }
    ]
})
 
- 在Message页面中实现跳转的功能
 
<template>
<div>
    <div style="width: 100%; height: 500px; background: rosybrown;">
        <h1>这是Message页面</h1>
        <hr>
        <div class="row">
            <div class="col-xs-2 col-xs-offset-2">
                <div class="list-group">
                    <!-- Vue中借助router-link标签实现路由的切换 -->
                    <router-link class="list-group-item" active-class="active" to="/message/detail">Detail</router-link> 
                    <router-link class="list-group-item" active-class="active" to="/message/news">News</router-link>
    </div>
    </div>
    </div>
        <div>
            <!-- 这个div主要是内容展示 -->
            <router-view></router-view>
    </div>
    </div>
    </div>
</template>
<script>
    export default { 
        name: 'MessagePage'
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
结果:

编程式路由
前进、后退、跳转到指定页面
- HomePage.vue
 
<template>
<div style="background-color: pink;">
    <h1>这里是Home页面</h1>
    <div>
        <button @click="btnForward">前进</button>  
        <button @click="btnBack">后退</button>  
        <button @click="btnForwardAndBack">前进/后退</button>  
        <button @click="btnJump">跳转到指定页面</button> 
    </div>
    <hr>
    <div class="row">
        <div class="col-xs-2 col-xs-offset-2">
            <div class="list-group">
                <!-- Vue中借助router-link标签实现路由的切换 -->
                <router-link class="list-group-item" active-class="active" to="/about">About</router-link> 
                <router-link class="list-group-item" active-class="active" to="/message">Message</router-link>
    </div>
    </div>
    </div>
    <!-- 这个div主要是内容展示 -->
    <router-view></router-view>
    </div>
</template>
<script>
    export default { 
        name: 'HomePage',
        methods:{
            btnForward(){
                //前进
                this.$router.forward();
            },
            btnBack(){
                //后退
                this.$router.back();
            },
            btnForwardAndBack(){
                //前进或者后退
                this.$router.go(-1);
            },
            btnJump(){
                //跳转
                //第一种跳转方式push,有历史,可以后退
                // this.$router.push({
                //   name:"news",
                //   query:{
                //     username:"ZhangSan",
                //     password:"123"
                //   }
                // })
                //第二种跳转方式replace,没有历史
                this.$router.replace({
                    name:"news",
                    query:{
                        username:"ZhangSan",
                        password:"123"
                    }
                })
            }
        }
    }
</script>
<style scope>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 

-  
跳转页面发送的数据是可以取出来的
 -  
NewsPage.vue
 
<template>
<div style="width: 100%; height: 200px; background: palevioletred;">
    这是News页面
    </div>
</template>
<script>
    export default { 
        name: 'NewsPage',
        data(){
            return{
                language:''
            }
        },
        mounted(){
            var username = this.$route.query.username
            var password = this.$route.query.password
            console.log("username:"+username+"---password:"+password)
        }
    }
</script>
<style scoped>
    div{
        font-family: 楷体;
        font-size: 30px;
    }
</style>
 
结果:




















