这份Vue.js你值得拥有,写完老板叫我转前端
Vue.js概述MVVM模式的实现者为什么要使用Vue.js第一个Vue程序下载地址代码编写Vue的生命周期生命周期图示Vue的闪烁问题解决方案Vue的基本语法v-bind判断:v-if,v-else-if,v-else循环:forVue的绑定事件v-onVue双向绑定为什么要实现数据的双向绑定在表单中使用双向数据绑定单行文本多行文本单选按钮复选框下拉单选框下拉多选框Vue组件组件的组织组件的注册
Vue.js
Idea安装Vue.js插件
1:概述
Vue(读音 /vju/ ,类似于view) 是一套用于构建用户界面的渐进式框架,发布于2014年2月。与其他大型框架不同的是,Vue被社会组为可以自底向上逐层应用。集于Angular的模型层Vue的核心只关注视图层,不仅易于上手,还便于与第三方库(如:vue-router,vue-resourcee,vuex)或既有项目整合
1-1:MVVM模式的实现者
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用,其作用如下:
- Model:模型层,在这里表示JavaScript对象
- View:视图层,在这里表示DOM(HTML操作的元素)
- ViewModel:连接视图和数据的中间件,Vue.js就是MVVM中的ViewModel层的实现者,能够观察到数据的变化,并对视图对应的内容进行变更,能够监听到视图的变化,并能够通知数据繁盛改变
1-2:为什么要使用Vue.js
- 轻量级,体积小是一个重要指标。Vue.js压缩后只有20多kb(Angular压缩后56kb+React压缩后44kb+)
- 移动优先,更适合移动端,比如移动端的Touch事件
- 易上手,学习曲线平稳,文档齐全
2:第一个Vue程序
【说明】IDEA可以安装Vue的插件
- 注意:Vue不支持IE8及以下版本,因为Vue使用了IE8无法模拟的ECMAScript5特性。但它支持所有兼容ECMAScript5的浏览器。
2-1:下载地址
开发版本
- 包含完整的警告和调试模式:https://vuejs.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 src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js”>
2-2:代码编写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序</title> </head> <body> <!-- view层 模板 --> <div id="myId"> {{message}} </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", <!-- model:数据 --> data:{ message:"hello,vue!" } }); </script> </body> </html>
效果
#:3:Vue的生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如 created 钩子可以用来在一个实例被创建之后执行代码:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 实例 console.log('a is: ' + this.a) } }) // => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mounted、updated 和 destroyed。生命周期钩子的this 上下文指向调用它的 Vue 实例。
不要在选项 property 或回调上使用箭头函数,比如 created: () => console.log(this.a) 或vm.$watch(‘a’, newValue => this.myMethod()) 。因为箭头函数并没有this ,this 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之类的错误。
##:3-1:生命周期图示
下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。
3-2:Vue的闪烁问题
了解Vue的生命周期后,知道Vue是要经过一系列的操作,先加载了模板,才渲染数据,还是我们的第一个Vue程序
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序</title> </head> <body> <!-- view层 模板 --> <div id="myId"> {{message}} </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", <!-- model:数据 --> data:{ message:"hello,林某!" } }); </script> </body> </html>
我们把浏览器的缓存清掉,然后把网速改为Slow 3G
效果
3-3:解决方案
可以让页面加载完数据后再显示
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序</title> <!-- v-clock解决闪烁问题 --> <style> [v-clock]{ display: none; } </style> </head> <body> <!-- view层 模板,v-clock解决闪烁问题 --> <div id="myId" v-clock> {{message}} </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", <!-- model:数据 --> data:{ message:"hello,林某!" } }); </script> </body> </html>
4:Vue的基本语法
我们已经成功创建了第一个Vue应用!看起来跟渲染一个字符串模板非常类似,但是Vue有在背后做了大量工作。现在数据和DOM已经建立了关联,所有东西都是响应式的。我们在控制台操作对象属性,界面可以实时更新!
4-1:v-bind
我们还可以使用v-bind来绑定元素特性,v-bind也可以省略,如我们下面的例子中,v-bind:title="message"也可以写成:title="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> <!-- view层 模板 --> <div id="myId"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的提示信息! </span> </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ message:"页面加载于 "+new Date().toLocaleDateString() } }); </script> </body> </html>
效果
如果你再次打开浏览器的JavaScript控制台,输入vm.message=新消息,就会看到这个绑定了title特性大的HTML已经进行了更新
4-2:判断:v-if,v-else-if,v-else
代码
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Vue的基本语法</title> </head> <body> <!-- view层 模板 --> <div id="myId"> <h1 v-if="ok">是</h1> <h1 v-else>否</h1> </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ ok: true } }); </script> </body> </html>
效果
代码
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Vue的基本语法</title> </head> <body> <!-- view层 模板 --> <div id="myId"> <h1 v-if="type==='A'">是A</h1> <h1 v-else-if="type==='B'">B</h1> <h1 v-else>C</h1> </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ type: "A" } }); </script> </body> </html>
效果
4-3:循环:for
Vue的for循环优先类似python的循环
代码
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Vue的基本语法</title> </head> <body> <!-- view层 模板 --> <div id="myId"> <li v-for="(item,index) in students"> 索引:{{index}}---信息:{{item.name}}-{{item.age}} </li> </div> <!-- 导入Vue.js --> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ students:[ {name: '林某',age: 27}, {name: '徐某',age: 26}, {name: '吴某',age: 29} ] } }); </script> </body> </html>
效果
5:Vue的绑定事件v-on
代码,v-on也可以用@代替,如我们下面的例子中,v-on:click="myFuntion1"也可以写成@:click="myFuntion1"
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Vue的基本语法</title> </head> <body> <!-- view层 模板 --> <div id="myId"> <!-- 绑定事件,绑定什么事件:v-on:事件="方法名" --> <button v-on:click="myFuntion1">单击变</button> <button v-on:mouseover="myFuntion2">鼠标移动到此变</button> <h1> {{message}} </h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ message: "林某最帅!" }, <!-- 方法一定要定义在methods中 --> methods:{ <!-- 定义方法 --> myFuntion1: function () { this.message="徐某也帅!" }, myFuntion2: function () { this.message="还是林某最帅!" } } }); </script> </body> </html>
效果
6:Vue双向绑定
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定 。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex,那么数据流也是单向的,这时就会和双向数据绑定有冲突
6-1:为什么要实现数据的双向绑定
在Vue.js中,如果使用vuex,实际上数据还是单向的,之所以说是数据双向绑定,这里用的UI控件来说,对于我们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单向。方便跟踪;局部性数据使用双向,简单易操作
6-2:在表单中使用双向数据绑定
你可以用v-model指令在表单<input>、<textarea>及<select>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意:v-model会忽略所有表单元素的value、checked、selected特性的初始值,而总是将Vue实例的数据作为数据来源。你应该通过JavaScrip在组件的data选项中声明初始值!
6-3:单行文本
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue的双向绑定</title> </head> <body> <div id="myId"> <input type="text" v-model="ms"> <h2>{{ms}}</h2> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ ms: "林某最帅!" } }); </script> </body> </html>
效果
6-4:多行文本
代码
<html lang="en"> <head> <meta charset="UTF-8"> <title>Vue的双向绑定</title> </head> <body> <div id="myId"> <textarea rows="10" cols="30" v-model="ms"></textarea> <h2>{{ms}}</h2> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ ms: "林某最帅!" } }); </script> </body> </html>
效果
6-5:单选按钮
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue的双向绑定</title> </head> <body> <div id="myId"> 性别: <input type="radio" name="gender" value="1" v-model="ms"> 男 <input type="radio" name="gender" value="0" v-model="ms"> 女 <h1>{{ms}}</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ // 默认是0,为女 ms: "0" } }); </script> </body> </html>
效果
6-6:复选框
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue的双向绑定</title> </head> <body> <div id="myId"> 爱好: <input type="checkbox" value="running" v-model="checkedNames" >跑步 <input type="checkbox" value="reading" v-model="checkedNames" >阅读 <input type="checkbox" value="lookGirl" v-model="checkedNames" >看妞 <input type="checkbox" value="shopping" v-model="checkedNames" >购物 <br/><h1>选择了:{{checkedNames}}</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ // 多选框是一个数组,默认选择有看妞 checkedNames: ["lookGirl"] } }); </script> </body> </html>
效果
6-7:下拉单选框
如果 v-model 表达式的初始值未能匹配任何选项, 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像上面这样提供一个值为空的禁用选项。
代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue的双向绑定</title> </head> <body> <div id="myId"> 下拉单选框: <select v-model="game"> <option value="" disabled="disabled">--请选择--</option> <option value="LOL" >英雄联盟</option> <option value="WOW" >魔兽世界</option> <option value="Dota" >刀塔</option> </select> <br/><h1>选择了:{{game}}</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ // 下拉单选是一个值 game: "" } }); </script> </body> </html>
效果
6-8:下拉多选框
代码
<!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="myId"> 下拉多选框: <select v-model="game" multiple="multiple" style="width: 150px;"> <option value="" disabled="disabled">--请选择--</option> <!-- 可以动态加载数据 --> <option v-for="option in gameOptions" v-bind:value="option.value"> {{ option.text }} </option> </select> <br/><h1>选择了:{{game}}</h1> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> var vm = new Vue({ el:"#myId", data:{ // 下拉多选是一个数组 game: [], gameOptions: [ { text: '英雄联盟', value: 'LOL' }, { text: '魔兽世界', value: 'WOW' }, { text: '刀塔', value: 'Dota' } ] } }); </script> </body> </html>
效果
7:Vue组件
所谓的组件,只是把一些复用的代码封装起来,这样方便调用复用
7-1:组件的组织
通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
7-2:组件的注册
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:我们这里只演示全局注册
Vue.component('my-component-name', { // ... options ... })
全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。
如我们这里注册了一个主键,并且我们的命名最好是小写,大写有可能出错识别不出,代码
<!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="myId"> <!-- 使用mycomponent组件,当成标签使用 --> <mycomponent></mycomponent> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> /*定义一个名为 mycomponent 的新组件,template封装了一些标签*/ Vue.component('mycomponent', { template: '<li>林某</li>' }); var vm = new Vue({ el:"#myId", data:{ } }); </script> </body> </html>
效果
如果我们定义的主键模板封装了很多标签在里面,那么就需要用一个标签把所有的括起来,不然只会识别第一标签
代码,只识别第一个
<!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="myId"> <!-- 使用mycomponent组件,当成标签使用 --> <mycomponent></mycomponent> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> /*定义一个名为 mycomponent 的新组件,template封装了一些标签*/ Vue.component('mycomponent', { template: '<li>林某</li><li>徐某</li>' /*这里只会识别第一个标签林某,而第二个徐某不会识别 */ }); var vm = new Vue({ el:"#myId", data:{ } }); </script> </body> </html>
正确的做法,外面用一个标签再包住,代码
<!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="myId"> <!-- 使用mycomponent组件,当成标签使用 --> <mycomponent></mycomponent> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> /*定义一个名为 mycomponent 的新组件,template封装了一些标签*/ Vue.component('mycomponent', { template: '<div><li>林某</li><li>徐某</li></div>' /*外面用一个div包住 */ }); var vm = new Vue({ el:"#myId", data:{ } }); </script> </body> </html>
7-3:组件的值传递,通过 Prop 向子组件传递数据
父组件向子组件传递数据,使用 Prop,基于上面的组件,我想数据是从外面传进来了,而不是再组件里写死的,这样组件就能最大化的实现复用,我就是一<li>的组件,至于数据多少,有外部传进来的数据决定,那么我们可以使用Prop 向子组件传递数据
代码
<!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="myId"> <!--遍历外部数据nameData,赋予item--> <!--内部的name1和name2绑定tem--> <mycomponent v-for="item in nameData" v-bind:name1="item" v-bind:name2="item"></mycomponent> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> Vue.component('mycomponent', { <!--内部定义name1和name2--> props:["name1","name2"], <!--内部name1和name2获取值--> template: '<li>{{name1}}---{{name2}}</li>' }); var vm = new Vue({ el:"#myId", data:{ nameData: [ "林某","徐某","吴某","周某" ] } }); </script> </body> </html>
效果
7-4:子组件自定义变量data
子组件也想有自己定义的变量,组件内使用,使用data定义
代码
<!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="myId"> <!-- 使用数据dataOptions1,这是一个一维数组,赋值给myoption --> <myselect v-bind:myoption="dataOptions1"></myselect> <!-- 使用数据dataOptions2,这是一个二维数组,遍历赋予items--> <!-- items获取dataOptions2data,获取到的是一维数组,赋值给myoption--> <myselect v-for="items in dataOptions2" v-bind:myoption="items.dataOptions2data"></myselect> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> // 定义一个名为 button-counter 的新组件 Vue.component('myselect', { props: ['myoption'], methods:{ <!-- 定义方法,使用组件内的变量计算 --> myFuntion1: function () { this.count+=1; }, }, <!-- data定义变量 --> data: function () { return { count: 0, game:[] } }, <!-- 定义模板,下拉多选框 --> template: '<div>' + '<select v-model="game" multiple="multiple" style="width: 150px;" v-on:click="myFuntion1">\n' + ' <option value="" disabled="disabled">--请选择--</option>\n' + ' <!-- 可以动态加载数据 -->\n' + ' <option v-for="option in myoption" v-bind:value="option.value">\n' + ' {{ option.text }}\n' + ' </option>\n' + ' </select>' + <!-- 输出自定义遍历 --> ' 选择了:{{game}},改变次数{{count}}</div>' }); var vm = new Vue({ el:"#myId", data:{ dataOptions1: [ { text: '英雄联盟', value: 'LOL' }, { text: '魔兽世界', value: 'WOW' }, { text: '刀塔', value: 'Dota' } ], dataOptions2: [ { dataOptions2data:[ { text: '1', value: '11' }, { text: '2', value: '22' }, { text: '3', value: '33' } ] }, { dataOptions2data:[ { text: '4', value: '44' }, { text: '5', value: '55' }, { text: '6', value: '66' } ] } ] } }); </script> </body> </html>
效果
8:Axios异步通信
使用Axios异步通信,Idea的JavaScript的版本必须是ES6+的,以为是基于ES6+的
8-1:什么是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/
8-2:为什么要使用Axios
由于Vue.Js是一个视图层框架,并且作者(尤雨溪)严格遵守Soc关注度分离原则),所以Vue.Js并不包含AJAX的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0版本会后停止了对改插件的维护并推荐了Axios框架。少用JQuery,因为它操作Dom才频繁。
8-3:第一个Axios应用程序
咱们开发的接口大部分都是采用JSON格式,可以先在项目里模拟一段JSON数据,数据内容如下:创建一个名为myData.json的文件并填入上面的内容,放在项目的根目录下
{ "name":"林某人", "url": "https://lingaolu.blog.csdn.net/", "page": "1", "isNonProfit":"true", "address": { "street": "海头港", "city":"海南儋州", "country": "中国" }, "links": [ { "name": "B站", "url": "https://www.bilibili.com/" }, { "name": "4399", "url": "https://www.4399.com/" }, { "name": "百度", "url": "https://www.baidu.com/" } ] }
使用Axios我们需要引入js,我们线上引入
<script src=“https://unpkg.com/axios/dist/axios.min.js”>
示例代码
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Axios异步通信</title> <!-- v-clock解决闪烁问题 --> <style> [v-clock]{ display: none; } </style> </head> <body> <!-- view层 模板,v-clock解决闪烁问题 --> <div id="myId" v-clock> <!-- 输出info的信息 --> {{info}} <h1>姓名:{{info.name}},地址:{{info.address.country}}{{info.address.city}}{{info.address.street}}</h1> <h1>博客主页:<a v-bind:href="info.url">主页</a></h1> </div> <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:"#myId", <!-- 定义变量 --> data(){ return{ info:{} } }, <!-- 异步获取myData.json里的数据,赋值给info --> mounted(){ <!-- 钩子函数,链式编程 --> axios.get('../myData.json').then(response=>(this.info=response.data)) } }); </script> </body> </html>
效果
自己本地写一个接口,演示一下请求接口的数据
接口地址和请求得到的数据
测试代码
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Axios异步通信</title> <!-- v-clock解决闪烁问题 --> <style> [v-clock]{ display: none; } </style> </head> <body> <!-- view层 模板,v-clock解决闪烁问题 --> <div id="myId" v-clock> <!-- 输出info的信息 --> {{info}} </div> <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:"#myId", <!-- 定义变量 --> data(){ return{ info:{} } }, <!-- 异步获取myData.json里的数据,赋值给info --> mounted(){ <!-- 钩子函数,链式编程,访问自己的接口 --> axios.get('http://localhost:8080/studentManafer/api/student/v1.0/students/1').then(response=>(this.info=response.data)) } }); </script> </body> </html>
如果出现以下内容,说明是跨域的问题,让服务端端口解决跨域就可以了ssm整合,这里面有一个拦截器,里面有跨域的设置
跨域问题解决后,展示的结果
9:计算属性computed
计算属性的重点突出在属性两字上(属性是名词),首先它是个属性,其次这个属性有计算的能力(计算是动词),在这里计算就是个函数,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的 属性),仅此而已,可以想象为缓存
上代码,注意看我们的func1和func2定义的位置
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>计算属性</title> </head> <body> <div id="myId" v-clock> <h1>方法:{{func1}}</h1> <!-- 通过方法调 --> <h1>方法:{{func1()}}</h1> <!-- 通过属性调 --> <h1>属性:{{func2}}</h1> </div> <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:"#myId", data:{ message: "hello,vue!" }, methods:{ func1: function () { <!-- 返回时间戳 --> return Date.now(); } }, computed: { func2: function () { this.message; <!-- 返回时间戳 --> return Date.now(); } } }); </script> </body> </html>
效果
10:插槽slot
在Vue.js中,我们可以使用<slot>元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中,通过插槽的name属性来确定插入的位置
示例代码
<!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="myId"> <!-- 使用组件my_component --> <my_component> <!-- 使用组件my_component,绑定title数据绑定到组件的inner_title --> <!-- 并且通过插槽名字title_name插入my_component的相应位置 --> <title_component slot="title_name" v-bind:inner_title="title"></title_component> <!-- 使用组件my_component,遍历数据books为book,绑定book数据绑定到组件的inner_item --> <!-- 并且通过插槽名字item_name插入my_component的相应位置 --> <item_component slot="item_name" v-for="book in books" v-bind:inner_item="book"></item_component> </my_component> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> /*定义一个组件my_component*/ Vue.component("my_component",{ <!-- 定义一个模板,里面定义2个插槽,名字分别为title_name和item_name --> template: "<div>\ <h1>标题:</h1>\ <slot name='title_name'></slot>\ <h1>数据:</h1>\ <ul>\ <slot name='item_name'></slot>\ </ul>\ </div>" }); /*定义一个组件title_component*/ Vue.component("title_component",{ props:["inner_title"], <!-- 定义一个模板 --> template: "<div>{{inner_title}}</div>" }); /*定义一个组件item_component*/ Vue.component("item_component",{ props:["inner_item"], <!-- 定义一个模板 --> template: "<li>{{inner_item}}</li>" }); var vm = new Vue({ el:"#myId", <!-- 定义数据title和books --> data:{ title: "好书集合!", books:["花季少年","雨后的故事",'放学后的教室'] } }); </script> </body> </html>
效果
11:自定义事件
通过以上插槽的代码中,我们不难发现,数据项在Vue的实例中,但删除操作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数的传递与事件分发了,Vue为我们提供了自定义事件的功能,很好的帮助我们解决了这个问题。使用this.$emit(‘自定义事件名’,参数),操作过程如下
代码
<!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="myId"> <!-- 使用组件my_component --> <my_component> <!-- 使用组件my_component,绑定title数据绑定到组件的inner_title --> <!-- 并且通过插槽名字title_name插入my_component的相应位置 --> <title_component slot="title_name" v-bind:inner_title="title"></title_component> <!-- 使用组件my_component,遍历数据books为book,绑定book数据绑定到组件的inner_item --> <!-- 并且通过插槽名字item_name插入my_component的相应位置 --> <!-- 通过插自定义的self_remove去找外部Vue实例的removeItems方法 --> <item_component slot="item_name" v-for="(book,for_index) in books" v-bind:inner_item="book" v-on:self_remove="removeItems(for_index)"></item_component> </my_component> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script> /*定义一个组件my_component*/ Vue.component("my_component",{ <!-- 定义一个模板,里面定义2个插槽,名字分别为title_name和item_name --> template: "<div>\ <h1>标题:</h1>\ <slot name='title_name'></slot>\ <h1>数据:</h1>\ <ul>\ <slot name='item_name'></slot>\ </ul>\ </div>" }); /*定义一个组件title_component*/ Vue.component("title_component",{ props:["inner_title"], <!-- 定义一个模板 --> template: "<div>{{inner_title}}</div>" }); /*定义一个组件item_component*/ Vue.component("item_component",{ props:["inner_item"], <!-- 定义一个模板,点击删除会执行inner_remove方法 --> template: "<li>{{inner_item}}<button @click='inner_remove'>删除</button></li>", methods: { <!-- 组件item_component内部的方法, --> inner_remove: function () { <!-- this.$emit()自定义事件self_remove分发,回去前端找self_remove --> this.$emit("self_remove") } } }); var vm = new Vue({ el:"#myId", <!-- 定义数据title和books --> data:{ title: "好书集合!", books:["花季少年","雨后的故事",'放学后的教室'] }, methods: { removeItems: function (fc_index) { console.log("删除的数据:"+this.books[fc_index]); <!-- splice是js的方法,可以有:多个参数,分别为:1:当前的数组下标,2:从当前下标开始,要删除的个数,3以上:把后面的数据加到数组中 --> this.books.splice(fc_index,1) } } }); </script> </body> </html>
效果
12:第一个vue-cli项目
先说明:以下涉及的安装,如果出现问题,基本上是版本不兼容,适当调整NodeJS的版本,NodeJS在下面会说到
12-1:什么是vue-cli
vue-cli是官方提供的一个脚手架,用于快速生成一个vue的项目模板
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个估计项目就是脚手架,我们的开发更加的快速
主要的额功能:
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包上线
12-2:需要的环境
12-2-1:Node.js
Node.js就是服务器,类似后端的服务器tomcat
-Node.js的安装教程NodeJs的下载安装与环境变量配置
下载地址:NodeJs中文网
根据自己的环境选择,我选择window64位
下载完安装
提示版本不支持,因为我们下载是最新版本,而我的电脑是win7的,版本不支持
换到NodeJs官网
至于什么版本看你们自己,我选择10.10.0的
安装,无脑下一步
查看是否安装成功
- cmd下输入node -v,查看是否能够正确打印出版本号即可
- cmd下输入nmp -v,查看是否能够正确打印出版本号即可
如果出现这样的问题,这里说明我们的npm没有配置环境变量。这是我之前安装8.1.12版本遇到的,没问题那最好
我的nodejs安装的目录为
D:\Software\Development\NodeJs
里面有npm
新建一个环境变量,变量名为APPDATA,值为npm的路径
D:\Software\Development\NodeJs\node_modules\npm
安装成功
12-2-2:npm命令解释
- npm install moduleName:安装模块到项目目录下,install可以缩写为i
- npm install -g moduleName:-g的意思死将模块安装到全局,具体安装到磁盘哪个位置,要看npm config prefix的位置
- npm install -save moduleName:–save的与意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖,-S为该命令的缩写
- npm install -save-dev moduleName:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令的缩写
12-2-3:安装淘宝镜像加速器(cnpm)
安装Node.js淘宝镜像加速器(cnpm)
这样子的话,下载会快很多,但是淘宝镜像加速器(cnpm)可能在打包上会有问题,所以不要太依赖,一般先使用Node.js原本的npm,如果太慢的话就考虑用cnpm
- -g就是个全局安装
- npm install cnpm -g
- 或者使用如下语句解决npm速度慢的问题
- npm install --registry=https://registry.npm.taobao.org
安装成功
配置环境变量
cnpm回车,配置成功
12-2-4:Git
- Git下载地址:https//git-scm.com/downloads
- 镜像:https://npm.taobao.org/mirrors/git-for-windows
12-2-5:vue-cli
安装vue-cli
cnpm install vue-cli -g
安装完后可以使用这个命令vue list
- 测试是否安装成功
- 查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
安装成功
12-3:第一个vue-cli应用程序
12-3-1:创建vue-cli项目
- 1.创建第一个Vue项目,我们随便建立一个空的文件夹在电脑上,我这里在D盘下新建一个目录:D:\Data\IdeaWorkSpaceStudy\Vuecli
- 2.在第一步的目录下,创建一个基于webpack模板的vue应用程序
这里的myclivue是项目名称,可以根据自己的需求取名
cmd执行命令:vue init webpack myclivue
一路都选择no即可
创建成功
说明:
- Project name:项目名称,默认回车即可
- Project description:项目描述,默认回车即可
- Author:项目作者,默认回车即可
- Vue build standalone:(运行时 + 编译器)模式
- Install vue-router:是否安装vue-router,选择n不安装(后期需要再手动添加)
- Use ESLint to lint your code:是否使用ESLint做代码检查,选择n不安装(后期需要再手动添加)
- Set up unnit tests:单元测试相关,选择n不安装(后期需要再手动添加)
- Setup e2e tests with Nightwath:单元测试相关,选择n不安装(后期需要再手动添加)
- Should we run npm install for you after the project has been created:创建完成后直接初始化,选择n,我们手动执行运行结果!
12-3-2:初始化并运行
进入到项目的目录
安装所有的依赖环境
npm install
启动项目
npm run dev
使用diea打开我们的项目
npm run dev 启动访问
使用diea的Terminal执行>npm run dev不起作用的原因是因为权限不够,可以修改其权限
运行成功
基本目录介绍,有些语法看不懂没关系,是一些webpack的语法,在下一节会介绍
12-4:Webpack
12-4-1:什么是Webpack
本质上,webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle
webpack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再按照异步加载。通过loader转换,任何像是的资源都可以当做模块,比如CommonsJS、AMD、ES6、CSS、JSON、CoffeeScript、LESS等;
伴随着移动你那个互联网的大潮,当今越来越多的网站已经从网页模块进化到了WebApp模式。他们运行在现代浏览器里,使用HTML5、CSS3、ES6等新技术来开发丰富的功能,网页已经不仅仅是完成浏览器的基本需求;WebApp通常是一个SPA(单页面应用),每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的JS代码,这给前端的开发流程和资源组织带来了巨大挑战。
前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的 编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。
12-4-2:模块化的演进
一、Script标签
<script src="module1.js"></script> <script src="module2.js"></script> <script src="module3.js"></script> <script src="module4.js"></script>
这是最原始的JavaScript文件加载方式,如果把每一个文件看成是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在window对象中,不同模块的调用都是一个作用域。
这些原始的加载方式暴露了一些显而易见的弊端:
- 全局作用域下容易造成变量冲突
- 文件只能按照<script>的书写顺序进行加载
- 开发人员必须主观解决模块和代码库的依赖关系
- 在大型项目中个纵横资源难以管理,长期积累的问题导致代码库混乱不堪
二、CommonsJS
服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其他模块,然后通过exports或module.exports来导出需要暴露的接口。
require("module"); require("../module.js"); export.doStuff = function(){}; module.export = myValue;
优点:
- 服务器端模块便于重用
- NPM中已经有超过45万个可以使用的模块包
- 简单易用
缺点:
- 同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的
- 不能非阻塞的并行加载多个模块
实现:
- 服务端的NodeJS
- Browserify,浏览器端的CommonsJS实现,可以使用NPM的模块,但是编译打包后的文件体积较大
- modules-webmake,类似Browserify,但不如Browserify灵活
- wreq,Browserify的前身
三、AMD
Asynchronous Module Definition规范其实主要是一个主要接口define(id?,dependencies?,factory);它要在声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行。
define("module",["dep1","dept2"],function(d1,d2){ return someExportedValue; }); require(["module","../file.js"].function(module,file)[])
优点:
- 适合在浏览器环境中异步加载模块
- 可以并行加载多个模块
缺点:
- 提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义不畅
- 不符合通用的模块化思维方式,是一种妥协的实现
实现:
- RequireJS
- curl
四、CMD
Commons Module Definition规范和AMD很相似,尽量保持简单,并与CommonsJS和NodeJS的Modules规范保持了很大的兼容性。
define(function(require, exports, module){ var $ = require("jquery"); var spinning = require("./spinning "); exports.doSomething = ...; module.exports = ...; });
优点:
- 依赖很近,延迟执行
- 可以很容易在NodeJS中运行
缺点:
- 依赖SPM打包,模块的加载逻辑偏重
实现:
- Sea.js
- coolie
五、ES6模块
EcmaScript6标准增加了JavaScript语言层面的模块体系定义。ES6模块的设计思想,是尽量静态化,使编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonsJS和AMD模块,都只能在运行时确定这些东西
import "jqueryu" export function doStuff(){] module "locaModule"{}
优点:
- 容易进行静态分析
- 面向未来的EcmaScript标准
缺点:
- 原生浏览器端还没有实现该标准
- 全新的命令,新版的NodeJS才支持
实现:
- Babel
大家期望的模块系统
可以兼容多种模块风格,尽量可以利用已有的代码,不仅仅只是JavaScript模块化,还有CSS、图片、字体等资源也需要模块化。
12-4-3:安装Webpack
Webpack是一款模块加载器兼打包工具,它能把各种资源,如JS、JSX、ES6、SASS、LESS、图片等都作为模块来处理和使用
安装:
npm install webpack -g
npm install webpack-cli -g
- webpack 是打包工具
- webpack-cli是客户端
测试安装成功:
- webpack -v
- webpack-cli -v
如果测试安装有问题的,可以降低版本,查看版本的命令
- npm view webpack versions --json
4+版本以上的,需要安装cli客户端,以下的不需要
指定版本安装cnpm i -g webpack@3.6.0
安装成功
12-4-4:配置
这一步不懂的可以跳过,下一步会讲,创建webpack.config.js配置文件
- entry:入口文件,指定WebPack用哪个文件作为项目的入口
- output:输出,指定WebPack把处理完成的文件放置到指定路径
- module:模块,用于处理各种类型的文件
- plugins:插件,如:热更新、代码重用等
- resolve:设置路径指向
- watch:监听,用于设置文件改动后直接打包
12-4-5:使用webpack
1:创建项目
创建一个文件夹,用idea打开,名字随便取
2:创建一个名为module的目录,名字随便取,用于放置JS模块等资源文件
3:在modules下创建模块文件,如girlFriend.js,用于编写JS模块相关代码
// 暴露方法 exports.say = function () { document.write("<h1>我爱你</h1>") }; exports.boyFriend = function () { document.write("<h1>林某人</h1>") };
4:在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
// require导入一个模块,就可以调用这个模块中的方法了 var girlFriend = require("./girlFriend"); girlFriend.say(); girlFriend.boyFriend();
5:在项目目录下创建webpack.config.js配置文件,使用webpack命令打包
module.exports = { entry: './modules/main.js', output: { filename: "./js/bundle.js" } };
6:新建index.html页面,引入第5步打包后的js文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="js/bundle.js"></script> </body> </html>
7:运行HTML看效果
8:监听电话
参数:–watch 用于监听变化,只要改变代码,就会监听重新打包
webpack --watch
13:vue-router路由
13-1:说明
Vue Router是Vue.js官方的路由控制器。它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于Vue.js过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的CSS class的链接
- HTML5历史模式或hash模式,在IE中自动降级
- 自定义的滚动条行为
13-2:安装
vue-router是一个插件包,所以我们还是需要npm/cnpm来进行安装的。打开命令行工具,这个是要安装在项目里面的,所以进入你的项目目录,输入下面命令
- npm install vue-router --save-dev
- –save-dev表示保存我们的开发配置里面
安装前先看我们的项目到底是否已经有vue-router,我们使用第一个vue-cli项目来演示
我们的项目没有,那安装一下
安装完就有了
13-3:使用
如果在一个模块化工程中使用它,必须要通过Vue.use()明确的安装路由功能:
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter );
1:我们搞2个组件
studyJava.vue
<template> <h1>林某学java</h1> </template> <script> export default { name: 'StudyJava', data () { return { msg: 'Welcome to StudyJava' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
studyVue.vue
<template> <h1>林某学Vue</h1> </template> <script> export default { name: 'StudyVue', data () { return { msg: 'Welcome to StudyVue' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
2:在根目录下建立router的配置文件
index.js// 导入官方vue和vue-router组件 import Vue from 'vue' import VueRouter from 'vue-router' // 导入我们定义的组件 import StudyJava from '../components/studyJava' import StudyVue from '../components/studyVue' // 安装路由 Vue.use(VueRouter); // 配置导出路由 export default new VueRouter({ routes: [ { // 路由路径 path: '/java', // name可有可无 name: 'java', component:StudyJava }, { // 路由路径 path: '/vue', component:StudyVue } ] });
3:入口导入路由配置
4:路由使用
<template> <div id="app"> <router-link to="/java">java模块</router-link> <router-link to="/vue">Vue模块</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App', } </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>
效果
14:vue+elementUI
elementUI为我们提供了多种多样的样式模板,下面就简单介绍怎么集合vue使用,更多的使用方式请结合官网elementUI官网
14-1:创建工程
注意:命令行都要使用管理员模式运行
1:创建一个名为eleuidemo的工程
vue init webpack eleuidemo
2:安装依赖,我们需要安装vue-router、element-ui、sass-loader和node-sass四个插件
2-1:进入工程目录
cd eleuidemo
2-2:安装vue-router
npm install vue-router --save-dev
2-3:安装element-ui
npm install element-ui -s
2-4:安装依赖
npm install
2-5:安装SASS记载器sass-loader
cnpm install sass-loader --save-dev
2-6:安装SASS记载器node-sass
cnpm install node-sass --save-dev
3:启动测试
npm run dev
14-2:使用elementUI
14-2-1:idea打开我们所建项目
14-2-2:配置好路由
新建demo.vue
配置路由
// 导入官方vue和vue-router组件 import Vue from 'vue' import VueRouter from 'vue-router' // 导入我们定义的组件 import Demo from '../components/demo' // 安装路由 Vue.use(VueRouter); // 配置导出路由 export default new VueRouter({ routes: [ { // 路由路径 path: '/demo', // name可有可无 name: 'demo', component:Demo } ] });
入口引入路由
路由启动成功
14-2-3:使用elementUI
随便找官网的一段组件代码,替换我们的demo.vue
<template> <el-form :model="dynamicValidateForm" ref="dynamicValidateForm" label-width="100px" class="demo-dynamic"> <el-form-item prop="email" label="邮箱" :rules="[ { required: true, message: '请输入邮箱地址', trigger: 'blur' }, { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] } ]" > <el-input v-model="dynamicValidateForm.email"></el-input> </el-form-item> <el-form-item v-for="(domain, index) in dynamicValidateForm.domains" :label="'域名' + index" :key="domain.key" :prop="'domains.' + index + '.value'" :rules="{ required: true, message: '域名不能为空', trigger: 'blur' }" > <el-input v-model="domain.value"></el-input><el-button @click.prevent="removeDomain(domain)">删除</el-button> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('dynamicValidateForm')">提交</el-button> <el-button @click="addDomain">新增域名</el-button> <el-button @click="resetForm('dynamicValidateForm')">重置</el-button> </el-form-item> </el-form> </template> <script> export default { data() { return { dynamicValidateForm: { domains: [{ value: '' }], email: '' } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); }, removeDomain(item) { var index = this.dynamicValidateForm.domains.indexOf(item) if (index !== -1) { this.dynamicValidateForm.domains.splice(index, 1) } }, addDomain() { this.dynamicValidateForm.domains.push({ value: '', key: Date.now() }); } } } </script>
导入elementUI
启动看效果
15:路由嵌套,参数传递及重定向
路由嵌套又称子路由,在实际应用中,通常有多层嵌套的组件组合而成。同样的。URL中各段动态路径也按某种结构对应嵌套的各层组件
15-1:路由嵌套
下面我们举例一下,默认你已经会路由router,以及会使用ElementUI了
我们定义一些组件
main.vue,使用了ElementUI的样式<template> <div> <el-aside width="200px"> <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;"> <el-radio-button :label="false">展开</el-radio-button> <el-radio-button :label="true">收起</el-radio-button> </el-radio-group> <el-menu default-active="1-4-1" class="el-menu-vertical-demo" @open="handleOpen" @close="handleClose" :collapse="isCollapse"> <el-submenu index="1"> <template slot="title"> <i class="el-icon-location"></i> <span slot="title">学习资料</span> </template> <el-menu-item-group> <span slot="title">前端</span> <el-menu-item index="1-1">Vue</el-menu-item> <el-menu-item index="1-2"> <router-link to="/elementUI">ElementUI</router-link> </el-menu-item> </el-menu-item-group> <el-menu-item-group title="后端"> <el-menu-item index="1-3">Java</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <span slot="title">Spring</span> <el-menu-item index="1-4-1"> <router-link to="/springBoot">SpringBoot</router-link> </el-menu-item> </el-submenu> </el-submenu> <el-menu-item index="2"> <i class="el-icon-menu"></i> <span slot="title">导航二</span> </el-menu-item> <el-menu-item index="3" disabled> <i class="el-icon-document"></i> <span slot="title">导航三</span> </el-menu-item> <el-menu-item index="4"> <i class="el-icon-setting"></i> <span slot="title">导航四</span> </el-menu-item> </el-menu> </el-aside> <el-main> <router-view/> </el-main> </div> </template> <style> .el-menu-vertical-demo:not(.el-menu--collapse) { width: 200px; min-height: 400px; } </style> <script> export default { data() { return { isCollapse: true }; }, methods: { handleOpen(key, keyPath) { console.log(key, keyPath); }, handleClose(key, keyPath) { console.log(key, keyPath); } } } </script>
studyElementUI.vue
<template> <h1>ElementUI资料</h1> </template> <script> export default { name: 'ElementUI资料', data () { return { msg: 'Welcome to ElementUI资料' } } } </script> <style scoped> h1 { font-weight: normal; } </style>
studySpringBoot.vue
<template> <h1>SpringBoot资料</h1> </template> <script> export default { name: 'SpringBoot资料', data () { return { msg: 'Welcome to SpringBoot资料' } } } </script> <style scoped> h1 { font-weight: normal; } </style>
路由配置
// 导入官方vue和vue-router组件 import Vue from 'vue' import VueRouter from 'vue-router' // 导入我们定义的组件 import Main from '../components/main' import ElementUI from '../components/studyElementUI' import SpringBoot from '../components/studySpringBoot' // 安装路由 Vue.use(VueRouter); // 配置导出路由 export default new VueRouter({ routes: [ { // 路由路径 path: '/main', // name可有可无 name: 'main', component:Main, children :[ {path: '/elementUI',component:ElementUI}, {path: '/springBoot',component:SpringBoot} ] } ] });
入口页面空页面,只给视图展示
<template> <div id="app"> <router-view/> </div> </template> <script> export default { name: 'App', } </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>
入口文件引入路由配置和ElementUI
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.config.productionTip = false Vue.use(ElementUI); /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, render: h => h(App) })
效果展示
15-2:参数传递
前端接收参数
方式1:路由对象引用
方式2:组件方式props接收参数
效果
15-3:重定向
举例访问goHome重定向到main
效果
15-4:路由模式
我们访问的时候,路径总是含有#号,这是路由的一种默认模式
路由的模式有两种
- hash:路径带#符号,如http://localhost:8080/#/main
- history:路径不带#符号,如http://localhost:8080/main
修改路由配置如下
export default new Router({ mode: 'history', routes:[ ] });
15-5:404页面
新建一个404页面
<template> <div> <h1>您已访问到火星了......</h1> </div> </template> <script> export default { name: 'erroePage', data () { return { msg: 到达火星' } } } </script> <style scoped> h1 { font-weight: normal; } </style>
路由配置访问路径为*,这样只要访问不存在的路径,都会跑到404组件页面
15-6:路由钩子,结合axios模拟实现腾讯的404找人页面
要使用axios,就得在项目中导入axios组件,axios整合vue的官网
cnpm install axios vue-axios --save-dev
在项目中引入并使用组件
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios);
在我们的404页面,使用axios访问后台数据
<template> <div> <h1>您已荣幸的访问到火星......</h1> <h1>寻找丢失儿童</h1> <h1>姓名:{{info.name}}</h1> <h1>年龄:{{info.ageNum}}</h1> </div> </template> <script> export default { name: 'errorPage', data () { return { // 定义变量接收返回值 info:{} } }, // 路由钩子函数 beforeRouteEnter:(to,form,next)=>{ console.log("进入路由之前"); next(vm=>{ // 调用我们的方法 vm.getData(); }); }, beforeRouteLeave:(to,form,next)=>{ console.log("离开路由之前"); }, methods:{ getData:function () { // 访问我自己后端的接口 this.axios({ method: 'get', url: 'http://localhost:8080/studentManafer/api/student/v1.0/students/1' }).then(response=>(this.info=response.data)); } } } </script> <style scoped> h1 { font-weight: normal; } </style>
接口数据
效果
更多推荐
所有评论(0)