【学习笔记】Vue

Vue官方文档:https://cn.vuejs.org/v2/guide/

一、第一个Vue程序

什么是MVVM

MVVM(Model-View-ViewModel)是一种软件设计模式, 由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。
ViewModel的作用: 该层向上与视图层进行双向数据绑定;向下与Model层通过接口请求进行数据交互
在这里插入图片描述
主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js,Anfular JS

为什么使用MVVC

MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处

  • 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
  • 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
  • 可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
    在这里插入图片描述

Vue介绍

Vue 是一套用于构建用户界面的渐进式框架, 发布于2014年2月。与其它大型框架不同的是, Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层, 不仅易于上手, 还便于与第三方库(如:vue-router,vue-resource,vue x) 或既有项目整合。

MVVM的实现者

  • Model:模型层, 在这里表示JavaScript对象
  • View:视图层, 在这里表示DOM(HTML操作的元素)
  • ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者

在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者

  • ViewModel能够观察到数据的变化, 并对视图对应的内容进行更新
  • ViewModel能够监听到视图的变化, 并能够通知数据发生改变

至此, 我们就明白了, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定

为什么使用使用Vue.js

  • 轻量级, 体积小是一个重要指标。Vue.js压缩后有只有20多kb(Angular压缩后56kb+,React压缩后44kb+)
  • 移动优先。更适合移动端, 比如移动端的Touch事件
  • 易上手,学习曲线平稳,文档齐全
  • 吸取了Angular(模块化) 和React(虚拟DOM) 的长处, 并拥有自己独特的功能,如:计算属性
  • 开源,社区活跃度高

Vue程序

  • Intellij IDEA下载Vue插件
    在这里插入图片描述
    在这里插入图片描述
    重启IDEA
    在这里插入图片描述
    出现Vue Component表示成功
    在这里插入图片描述

Vue下载地址

  • 开发版本
    包含完整的警告和调试模式:https://yuejs.org/js/vue.js
    删除了警告, 30.96KB min+gzip:https://vuejs.org/js/vue.min.js
  • cdn
    < script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js” >< /script >
    < script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js”>< /script>

编写html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<!--2. viw层 模板-->
<div id="div01">
    {{message}}
</div>

<!--1. 引入Vue.js ModelView的实现者
    这里面使用cdn
 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<!--3. model层 数据-->
<script>
    var vm = new Vue({
        el:"#div01",/*绑定元素的id*/
        data:{/*数据对象中有一个名为message的属性,初始值为 hello vue*/
            message:"hello vue"
        }
    });

</script>
</body>
</html>

测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不需要DOM操作,就让div中的内容发生了变化,这就是借助了Vue的数据绑定功能实现的; MV VM模式中要求View Model层就是使用观察者模式来实现数据的监听与绑定, 以做到数据与视图的快速响应

二、基础语法指令

指令会在渲染的DOM上应用特殊的响应式行为在这里

v-bind

将这个元素节点的title特性和Vue实例的message属性保持一致

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <span v-bind:title="message">
        鼠标悬浮几秒钟查看文字
    </span>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script>
    var vm = new Vue({
        el:"#div01",
        data:{
            message:"鼠标悬浮文字"
        }
    });

</script>
</body>
</html>

在这里插入图片描述

v-if,v-else

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script>
    var vm = new Vue({
        el:"#div01",
        data:{
            ok: true
        }
    });

</script>
</body>
</html>

v-else-if

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <h1 v-if="grade==='A'">A</h1>
    <h1 v-else-if="grade==='B'">B</h1>
    <h1 v-else>CD</h1>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script>
    var vm = new Vue({
        el:"#div01",
        data:{
            grade:"A"
        }
    });

</script>
</body>
</html>

v-for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <li v-for="item in array">
        {{item.message}}
    </li>

</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script>
    var vm = new Vue({
        el:"#div01",
        data:{
            array:[
                {message:"数组下标一"},
                {message:"数组下标二"},
                {message:"数组下标三"}
            ]
        }
    });

</script>
</body>
</html>

在这里插入图片描述

v-on

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <button v-on:click="say">讲话</button>
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data:{
            message:"你好 我是机器人"
        },
        methods:{
            say:function(){
                alert("你好") /*this指当前Vue示例*/
            }
        }
    });

</script>
</body>
</html>

三、表单双向绑定、组件

Vue.js是一个MV VM框架, 即数据双向绑定, 即当 数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化。 这也算是Vue.js的精髓之处了。

在表单中使用双向数据绑定

v-model指令在表单、及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。

v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!

单行文本

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    输入文本:<input type="text" v-model="message"/>
    {{message}}
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data:{
            message:""
        }
    });
</script>
</body>
</html>

多行文本

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    输入多行文本:<textarea v-model="message"></textarea>
    <br/>
    多行文本是:
    {{message}}
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data:{
            message:""
        }
    });
</script>
</body>
</html>

多复选框

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    复选框:<input type="checkbox"  value="java" v-model="message"/>java
            <input type="checkbox"  value="python" v-model="message"/>python
    {{message}}
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data: {
            message: []
        }
    });

</script>
</body>
</html>

单选框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    单选按钮:<input type="radio" value="" v-model="message"/><input type="radio" value="" v-model="message"/>女
    {{message}}
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data: {
            message: ""
        }
    });

</script>
</body>
</html>

下拉框

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    下拉框:
    <select v-model="message">
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>
    <br/>{{message}}
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>

<script type="text/javascript">
    var vm = new Vue({
        el:"#div01",
        data: {
            message: ""
        }
    });

</script>
</body>
</html>

组件

组件是可复用的Vue实例, 说白了就是一组可以重复使用的模板。
在这里插入图片描述

第一个Vue组件

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <yao></yao> <!--使用组件-->
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script type="text/javascript">
	<!--注册组件-->
    Vue.component("yao",{ /*自定义组件名字*/
        template:'<h1 style=\"font-size: 16px\">姚景阳<h1>' /*组件模板*/
    });
    var vm = new Vue({
        el:"#div01"
    })
</script>
</body>
</html>

使用props属性传递参数
传递参数到组件,使用props

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>测试Vue</title>
</head>
<body>

<div id="div01">
    <!--3. 遍历Vue对象中的Data, 通过v-bind 使自定义组件中的temp属性和遍历到的index 属性保持一致-->
    <yao v-for="index in array" v-bind:temp="index"></yao>
</div>

<!--换cdn-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script type="text/javascript">

<!--1.自定义的组件-->
    Vue.component("yao",{
        props:['temp'],
        template:'<li>{{temp}}</li>'
    })

/*2. new Vue 对象 绑定div,把array中的值传递到自定义组件中*/
    var vm = new Vue({
        el:"#div01",
        data:{
            array:["java","python","c++"]
        }
    });
</script>
</body>
</html>

四、Axios异步通信

什么是Axios

Axios是一个开源的可以用在浏览器端和Node JS的异步通信框架, 她的主要作用就是实现AJAX异步通信,其功能特点如下:

  • 从浏览器中创建XMLHttpRequests
  • 从node.js创建http请求
  • 支持Promise API[JS中链式编程]
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF(跨站请求伪造)

GitHub:https://github.com/axios/axios
  中文文档:http://www.axios-js.com/

为什么要使用Axios

由于Vue.js是一个视图层框架并且作者(尤雨溪) 严格准守SoC(关注度分离原则)所以Vue.js并不包含AJAX的通信功能为了解决通信问题, 作者单独开发了一个名为vue-resource的插件, 不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios框架。少用jQuery, 因为它操作Dom太频繁!

第一个Axios程序

Axios是基于ES6规范,所以更改IDEA配置
在这里插入图片描述
在根目录创建一段json数据 data.json

{
  "name": "狂神说Java",
  "url": "https://blog.kuangstudy.com",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://space.bilibili.com/95256449"
    },
    {
      "name": "狂神说Java",
      "url": "https://blog.kuangstudy.com"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

测试
使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中。
在data中的数据结构必须和Ajax响应回来的数据格式匹配

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="vue">

    {{info.name}}<br/>
    {{info.url}}<br/>
    {{info.address.city}}

</div>

<!--引入  Vue 和 Axios-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <script>
        var vm = new Vue({
            el:"#vue",
            data(){
                return{
                    info:{
                        name:null,
                        address:{
                            country:null,
                            city:null,
                            street:null
                        },
                        url:null
                    }
                }
            },
            mounted(){/*钩子函数*/
                axios.get('../data.json').then(response=>(this.info=response.data))
            }

        });
    </script>

</body>
</html>

vue的生命周期

在这里插入图片描述

五、计算属性

什么是计算属性

这里的计算就是个函数:它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div id="vue">
    currentTime1:{{currentTime1()}} <br/> <!--调用方法-->
    currentTime2:{{currentTime2}}<!--调用属性-->
</div>

<!--引入  Vue 和 Axios-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>

<script>
    var vm = new Vue({
        el:"#vue",
        data:{
            message:""
        },
        methods:{
            currentTime1:function () {
                return Date.now();/*返回时间戳*/
            }
        },
        computed:{/*计算属性:computed,methods方法不能重名,重名之后,只会调用method方法*/
            currentTime2:function () {
            this.message;
                return Date.now();/*返回时间戳*/
            }
        }

    });
</script>

</body>
</html>

在这里插入图片描述

  • methods:定义方法, 调用方法使用currentTime1(), 需要带括号
  • computed:定义计算属性, 调用属性使用currentTime2, 不需要带括号

在这里插入图片描述

结论
  调用方法时,每次都需要讲行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销

六、内容分发(插槽)

在Vue.js中我们使用元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中

应用测试
比如准备制作一个待办事项组件(todo) , 该组件由待办标题(todo-title) 和待办内容(todo-items)组成,但这三个组件又是相互独立的 (如果不是相互独立的,可以在待办事项组件template中使用待办标题组件),该如何操作呢?

  • 第一步定义一个待办事项的组件
<!DOCTYPE html>
<html lang="en" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <div id="app">
        <todo></todo>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    <script type="text/javascript">
        Vue.component("todo",{
            template: '<div>'+
                    '<div>待办理事项(标题)</div>'+
                        '<ul>'+
                              '<li>狂神说Java(内容)</li>'+
                        '</ul>'+
                    '</div>'
        });
        var vm = new Vue({
            el:"#app"
        });
    </script>
</body>
</html>
  • 第二步 我们需要让,代办事项的标题和值实现动态绑定,怎么做呢?我们可以留一个插槽(不在template模板中使用组件,而是留一个插槽,插入组件)!
<!DOCTYPE html>
<html lang="en" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <div id="app">
        <!--4. 在待办事项组件中 ,组件分别被分发到了todo组件的t-title和t-items插槽中,并且绑定组件中的参数 -->
        <todo>
            <todo-title slot="t-title" v-bind:name="message"></todo-title>
            <todo-items slot="t-items" v-for="temp in items" v-bind:item="temp"></todo-items>
        </todo>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    <script type="text/javascript">
        /*1.在待办事项组件中 留两个插槽*/
        Vue.component("todo",{
            template: '<div>\
                        <slot name="t-title"></slot>\
                        <ul>\
                              <slot name="t-items"></slot>\
                        </ul>\
                    </div>'
        });

        /*2. 编写 标题和内容组件,通过传入参数,可以实现动态绑定 */
        Vue.component("todo-title",{
            props:['name'],
            template: '<div>{{name}}</div>'
        });
        Vue.component("todo-items",{
            props:['item'],
            template:'<li>{{item}}</li>'
        });
	/*3. 实例化Vue并初始化数据*/
        var vm = new Vue({
            el:"#app",
            data:{
                message:"秦老师课程",
                items:['狂神说Java',"狂神说Mybatis","狂神讲故事"]
            }
        });
    </script>
</body>
</html>

七、自定义事件

实现功能: 数据项在Vue的实例中, 但删除操作要在组件中完成, 那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了, Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题; 使用this.$emit(‘自定义事件名’, 参数)

<!DOCTYPE html>
<html lang="en" >
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <div id="app">

        <todo>
            <todo-title slot="t-title" v-bind:name="message"></todo-title>
            <!--4. 遍历出下标 增加自定义事件remove(可以和组件方法绑定):绑定到Vue方法 -->
            <todo-items slot="t-items" v-for="(temp1,temp2) in items"
                        v-bind:item="temp1" v-bind:index="temp2"
                        v-on:remove="removeItems(temp2)" ></todo-items>
        </todo>
    </div>


    <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
    <script type="text/javascript">

        Vue.component("todo",{
            template: '<div>\
                        <slot name="t-title"></slot>\
                        <ul>\
                              <slot name="t-items"></slot>\
                        </ul>\
                    </div>'
        });


        Vue.component("todo-title",{
            props:['name'],
            template:'<div>{{name}}</div>'
        });
        Vue.component("todo-items",{
            props:['item','index'],
            /*2. 删除按钮 绑定响应事件*/
            template:'<li>{{item}}<button v-on:click="removeMethods">删除</button></li>',

            methods:{
                removeMethods:function () {
                    /*3. 自定义事件的名称*/
                    this.$emit("remove");
                }
            }
        });

        var vm = new Vue({
            el:"#app",
            data:{
                message:"秦老师课程",
                items:['狂神说Java',"狂神说Mybatis","狂神讲故事"]
            },

            /*1. 删除数据的方法,传入index下标*/
            methods:{
                removeItems:function (index) {
                    console.log("删除了"+this.items[index]+": ");
                    this.items.splice(index,1);//从index开始 删除1个元素
                }
            }
        });
    </script>
</body>
</html>

在这里插入图片描述

八、第一个Vue-cli程序

vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;预先定义好的目录结构及基础代码,就好比在创建Maven项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;

项目的功能

  • 统一的目录结构
  • 本地调试
  • 热部署
  • 单元测试
  • 集成打包上线

安装环境:

  • Node.js:http://nodejs.cn/download/
    安装就是无脑的下一步就好,安装在自己的环境目录下
  • Git:https://git-scm.com/doenloads
    镜像:https://npm.taobao.org/mirrors/git-for-windows/

确认安装成功

  • cmd下输入node -v,查看是否能够正确打印出版本号即可!
  • cmd下输入npm -v,查看是否能够正确打印出版本号即可!
    这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
      安装Node.js淘宝镜像加速器(cnpm)
# -g 就是全局安装
npm install cnpm -g

# 或使用如下语句解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org

安装的位置:C:\Users\administrator\AppData\Roaming\npm

安装Vue-cli

cnpm install vue-cli-g
#测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list

新建Vue项目

  • 新建一个文件夹
    在这里插入图片描述
  • 使用命令行进入VueCli文件夹,创建一个基于webpack模板的vue程序
#1、首先需要进入到对应的目录 cd D:\Project\vue-study
#2、这里的myvue是顶日名称,可以根据自己的需求起名
vue init webpack myvue

在这里插入图片描述
初始化并运行

cd myvue
npm install
npm run dev

如果出现问题,根据提示处理

九、webpack

  webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler)

  Webpack是当下最热门的前端资源模块化管理和打包工具, 它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。

模块化的演进

  • scrpit标签
	<script src = "module1.js"></script>
	<script src = "module2.js"></script>
	<script src = "module3.js"></script>

这是最原始的JavaScript文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在window对象中,不同模块的调用都是一个作用域

容易造成变量冲突

  • commonJS
      服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块 ,然后通过exports或module.exports来导出需要暴露的接口。
require("module");
require("../module.js");
export.doStuff = function(){};
module.exports = someValue;

虽然模块化便于重用,但是同步加载容易阻塞,用户体验不好

  • AMD
    Asynchronous Module Definition规范其实主要一个主要接口define(id?,dependencies?,factory);它要在声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行。
    可以异步并行加载模块,但是开发成本高

  • CMD

  • ES6规范
    EcmaScript 6标准增加了JavaScript语言层面的模块体系定义。ES 6模块的设计思想, 是尽量静态化, 使编译时就能确定模块的依赖关系, 以及输入和输出的变量。Commons JS和AMD模块,都只能在运行时确定这些东西。

安装webpack

WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用

安装命令

npm install webpack -g
npm install webpack-cli -g

检查是否安装成功

webpack -v
webpack-cli -v

配置
创建 webpack.config.js配置文件

entry:入口文件, 指定Web Pack用哪个文件作为项目的入口
output:输出, 指定WebPack把处理完成的文件放置到指定路径
module:模块, 用于处理各种类型的文件
plugins:插件, 如:热更新、代码重用等
resolve:设置路径指向
watch:监听, 用于设置文件改动后直接打包

module.exports = {
	entry:"",
	output:{
		path:"",
		filename:""
	},
	module:{
		loaders:[
			{test:/\.js$/,;\loade:""}
		]
	},
	plugins:{},
	resolve:{},
	watch:true
}

直接运行webpack命令打包

使用webpack

创建一个项目
在这里插入图片描述

在项目中创建moudles目录,用来放js模块资源

在modules下创建hello.js页面

/*暴露 sayHi方法 */
exports.sayHi = function () {
    document.write("<h1>hello 暴露出 sayHi方法</h1>")
}

在modules下创建main.js页面作为入口文件

var hello = require("./hello"); /*导入hello模块 从而调用该模块中的方法*/
document.write("主页面调用hello:");
hello.sayHi();

项目目录下创建webpack.config.js配置文件,使用webpack命令打包

module.exports={
    entry:"./modules/main.js",
    output:{
        filename:"./js/bundle.js"
    }
}

在这里插入图片描述
在这里插入图片描述

在项目下创建index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script src="./dist/js/bundle.js"></script>
</body>
</html>

运行即可

监听变化

# 参数--watch 用于监听变化
webpack --watch

实时监听js页面的拜年话,当页面内容改变时,就会重新打包

十、vue-router路由

安装

vue-router是一个插件包, 所以我们还是需要用n pm/cn pm来进行安装的

npm install vue-router --save-dev

在这里插入图片描述

测试

在components下自己定义一个内容组件content.vue

<template>
    <div>这是内容vue组件(内容页面)</div>
</template>

<script>
    export default {
        name: 'content'
    }
</script>



自定义组件title.vue

<template>
  <div>这是title标题组件(首页)</div>
</template>

<script>
    export default {
        name: 'title'
    }
</script>




src目录下,新建router文件夹,配置路由index.js
在这里插入图片描述

import Vue from 'vue'
/*导入路由插件*/
import Router from 'vue-router'
/*导入自定义组件*/
import content from '../components/content'
import title from '../components/title'

/*安装路由
如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功能:
*/
Vue.use(Router)

/*配置路由*/


export default new Router({
  routes:[
    {
      /*路由路径*/
      path:'/content',
      /*【路由名称】可以不写*/
      name:'content',
      /*跳转组件*/
      component:Content
    },{
      path:'/test',
      component:test
    },{
      path:'/title',
      component:title
    }
  ]
});



main.js中配置路由

import Vue from 'vue'
import App from './App'

/*导入路由配置目录 自动扫描路由配置*/
import router from './router'


Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,/*配置路由*/
  components: { App },
  template: '<App/>'
})



在AppVue中使用路由

<template>
    <div id="app">
      你好 appVue<br/>
      <!--
           router-link:默认会被渲染成一个<a>标签,to属性为指定链接
           router-view:用于渲染路由匹配到的组件,显示组件内容
       -->
      <router-link to="/title">首页</router-link>
      <router-link to="/content">内容</router-link>
      <router-view></router-view>

    </div>

</template>

<script>
export default {
  name: 'App',
  components: {
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行起来

npm run dev

十一、掌握Vue

创建工程

#创建工程
vue init webpack  hello-vue

创建依赖

#进入工程目录
cd hello-vue
#安装vue-routern 
npm install vue-router --save-dev
#安装element-ui
npm i element-ui -S
#安装依赖
npm install
# 安装SASS加载器
cnpm install sass-loader node-sass --save-dev
#启功测试
npm run dev

创建目录结构
在这里插入图片描述

创建首页组件

<template>
  <div>首页</div>
</template>

<script>
    export default {
        name: "Main"
    }
</script>

创建登录页面

创建登录页面组件,其中el-*的元素为ElementUI组件

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
      <h3 class="login-title">欢迎登录</h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
      </el-form-item>
    </el-form>

    <el-dialog title="温馨提示" :visible.sync="dialogVisiable" width="30%" :before-close="handleClose">
      <span>请输入账号和密码</span>
      <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="dialogVisible = false">确定</el-button>
        </span>
    </el-dialog>
  </div>
</template>

<script>
  export default {
    name: "Login",
    data(){
      return{
        form:{
          username:'',
          password:''
        },
        //表单验证,需要在 el-form-item 元素中增加prop属性
        rules:{
          username:[
            {required:true,message:"账号不可为空",trigger:"blur"}
          ],
          password:[
            {required:true,message:"密码不可为空",tigger:"blur"}
          ]
        },

        //对话框显示和隐藏
        dialogVisible:false
      }
    },
    methods:{
      onSubmit(formName){
        //为表单绑定验证功能
        this.$refs[formName].validate((valid)=>{
          if(valid){
            //使用vue-router路由到指定界面,该方式称为编程式导航
            this.$router.push('/main');
          }else{
            this.dialogVisible=true;
            return false;
          }
        });
      }
    }
  }
</script>

<style lang="scss" scoped>
  .login-box{
    border:1px solid #DCDFE6;
    width: 350px;
    margin:180px auto;
    padding: 35px 35px 15px 35px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    box-shadow: 0 0 25px #909399;
  }
  .login-title{
    text-align:center;
    margin: 0 auto 40px auto;
    color: #303133;
  }
</style>

创建路由

在Router下创建名为index.js的路由配置文件

/*导入组件*/
import Vue from 'vue'
import vueRouter from 'vue-router'
/*导入组件*/
import Main from '../views/Main'
import Login from '../views/Login'

/*使用*/
Vue.use(vueRouter);

export default new vueRouter({
  routes:[
    {
      path:'/main',
      component:Main
    },{
      path:'/Login',
      component:Login
    }
  ]
})


【vue run 错误1 】
注意:package.json中的配置文件会发生变化在这里插入图片描述

Module build failed: Error: Node Sass version 5.0.0 is incompatible with ^4.
sass-loader

卸载当前版本   npm uninstall sass-loader
安装     npm install sass-loader@7.3.1 --save-dev

【vue run错误2】

//卸载 node-sass
npm uninstall node-sass
//然后安装最新版本(5.0之前):但是安装之后仍然是5.0.0,注意使用淘宝镜像下载
cnpm install node-sass@4.14.1

嵌套路由

嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。

  • ①在views下面创建一个user文件夹
  • ②创建一个Profile.vue的视图组件
<template>
  <div>用户信息 profile组件</div>
</template>

<script>
    export default {
        name: "userProfile"
    }
</script>

  • ③ user目录下创建一个List.vue
<template>
    <div>用户列表 list组件</div>
</template>

<script>
    export default {
        name: "userList"
    }
</script>

  • ④ 使用ElementUI修改主页视图
<template>
    <div>
      <el-container>
        <el-aside width="200px">
          <el-menu :default-openeds="['1']">
            <el-submenu index="1">
              <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
              <el-menu-item-group>
                <el-menu-item index="1-1">
                <!--插入的地方-->
                  <router-link to="/user/profile">个人信息</router-link>
                </el-menu-item>
                <el-menu-item index="1-2">
                <!--插入的地方-->
                  <router-link to="/user/list">用户列表</router-link>
                </el-menu-item>
              </el-menu-item-group>
            </el-submenu>
            <el-submenu index="2">
              <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
              <el-menu-item-group>
                <el-menu-item index="2-1">分类管理</el-menu-item>
                <el-menu-item index="2-2">内容列表</el-menu-item>
              </el-menu-item-group>
            </el-submenu>
          </el-menu>
        </el-aside>

        <el-container>
          <el-header style="text-align: right; font-size: 12px">
            <el-dropdown>
              <i class="el-icon-setting" style="margin-right: 15px"></i>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item>个人信息</el-dropdown-item>
                <el-dropdown-item>退出登录</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </el-header>
          <el-main>
          <!--在这里展示视图-->
            <router-view />
          </el-main>
        </el-container>
      </el-container>
    </div>
</template>
<script>
    export default {
        name: "Main"
    }
</script>
<style scoped lang="scss">
  .el-header {
    background-color: #B3C0D1;
    color: #333;
    line-height: 60px;
  }
  .el-aside {
    color: #333;
  }
</style>

  • ⑤ 配置嵌套路由
//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";

import list from "../views/user/List";
import profile from "../views/user/Profile";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
  routes: [
    {
      //登录页
      path: '/main',
      component: Main,
      
      /*配置嵌套路由*/
      children:[
        {path:'/user/profile',component:profile},
        {path:'/user/list',component:list}
      ]
      
    },
    //首页
    {
      path: '/login',
      component: Login,
    },
  ]

})


在这里插入图片描述

参数传递

方式一

  1. 修改路由配置文件index.js,增加 :id 占位符
    在这里插入图片描述

  2. 修改主页面 Main.vue
    :to 是修改为绑定属性,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径

  <router-link :to="{name:'userProfile',params:{id:1}}">个人信息</router-link>
  1. Profile.vue
<template>
  <div>
    <h1>用户信息 profile组件</h1>
    {{$route.params.id}}
  </div>
</template>

<script>
    export default {
        name: "userProfile"
    }
</script>

在这里插入图片描述
【多个参数传递】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

方式二
使用props减少耦合

  1. 修改路由配置 index.js
    在这里插入图片描述

  2. 修改Main.vue中view-link(与方式一相同)

  3. 修改Profile.vue

<template>
  <div>
    <h1>用户信息 profile组件</h1>
   id:{{id}}


  </div>
</template>

<script>
    export default {
      props:['id'],
        name: "userProfile"
    }
</script>


【传递多个参数】

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

组件重定向

在这里插入图片描述

在这里插入图片描述

路由模式

路由模式有两种:

  • hash:路径带 # 符号,如 http://localhost/#/login
  • history:路径不带 # 符号,如 http://localhost/login

在这里插入图片描述
页面丢失404

  • 创建NotFound.vue组件
<template>
    <div><h1>404,页面走失了</h1></div>
</template>

<script>
    export default {
        name: "NotFound"
    }
</script>
  • 导入组件,配置路由
    在这里插入图片描述

钩子和Axios

beforeRouteEnter:在进入路由前执行
beforeRouteLeave:在离开路由前执行

Profile.vue

<template>
  <div>
    <h1>用户信息 profile组件</h1>
    {{id}}
    {{age}}
  </div>
</template>

<script>
    export default {
      props:['id','age'],
      name: "userProfile",

      beforeRouteEnter:(to,from,next)=>{
          console.log("进入路由之前 个人信息页");
          next();
      },
      beforeRouteLeave:(to,from,next)=>{
        console.log("离开路由之前 个人信息页");
        next();
      }
    }
</script>

参数说明:

to:路由将要跳转的路径信息
from:路径跳转前的路径信息
next:路由的控制参数
next() 跳入下一个页面
next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
next(false) 返回原来的页面
next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例

钩子函数中使用Axios

  1. 安装 Axios
  2. main.js导入Axios
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
  1. 在static文件夹中建立mock文件夹,mock中建立data.json,可以使用上面的json数据
http://localhost:8080/static/mock/data.json
  1. 在 beforeRouteEnter 中进行异步请求

Profile.vue

<template>
  <div>
    <h1>用户信息 profile组件</h1>
    {{id}}
    {{age}}
  </div>
</template>

<script>
    export default {
      props:['id','age'],
      name: "userProfile",

      beforeRouteEnter:(to,from,next)=>{
          console.log("进入路由之前 个人信息页");
          next(vm=>{
              vm.getData();
          });
      },
      beforeRouteLeave:(to,from,next)=>{
        console.log("离开路由之前 个人信息页");
        next();
      },
      methods:{
        getData:function () {
            this.axios({
              method:'get',
              url:'http://localhost:8080/static/mock/data.json',
            }).then(function (response) {
              console.log(response);
            });
        }
      }
    }
</script>

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值