1:概述
官网地址:https://cn.vuejs.org/
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
2-2:代码编写
<html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序title> head> <body> <div id="myId"> { {message}} div> <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程序
<html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序title> head> <body> <div id="myId"> { {message}} div> <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>
3-3:解决方案
代码
<html lang="en"> <head> <meta charset="UTF-8"> <title>第一个Vue程序title> <style> [v-clock]{ display: none; } style> head> <body> <div id="myId" v-clock> { {message}} div> <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"
<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"> <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:"#myId", data:{ message:"页面加载于 "+new Date().toLocaleDateString() } }); script> body> html>
如果你再次打开浏览器的JavaScript控制台,输入vm.message=新消息,就会看到这个绑定了title特性大的HTML已经进行了更新
4-2:判断:v-if,v-else-if,v-else
代码
<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"> <h1 v-if="ok">是h1> <h1 v-else>否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:{ ok: true } }); script> body> 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"> <h1 v-if="type==='A'">是Ah1> <h1 v-else-if="type==='B'">Bh1> <h1 v-else>Ch1> 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:{ type: "A" } }); script> body> html>
4-3:循环:for
Vue的for循环优先类似python的循环
代码
<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"> <li v-for="(item,index) in students"> 索引:{ {index}}---信息:{ {item.name}}-{ {item.age}} li> 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:{ 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"
<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> <div id="myId"> <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指令在表单、及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意:v-model会忽略所有表单元素的value、checked、selected特性的初始值,而总是将Vue实例的数据作为数据来源。你应该通过JavaScrip在组件的data选项中声明初始值!
6-3:单行文本
代码
<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:单选按钮
代码
<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:复选框
代码
<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 事件。因此,更推荐像上面这样提供一个值为空的禁用选项。
代码
<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:下拉多选框
代码
<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 根实例,也包括其组件树中的所有子组件的模板中。
如我们这里注册了一个主键,并且我们的命名最好是小写,大写有可能出错识别不出,代码
<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> div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script> <script> /*定义一个名为 mycomponent 的新组件,template封装了一些标签*/ Vue.component('mycomponent', { template: '
林某 ' }); var vm = new Vue({ el:"#myId", data:{ } }); script> body> 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> div> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script> <script> /*定义一个名为 mycomponent 的新组件,template封装了一些标签*/ Vue.component('mycomponent', { template: '
林某 徐某 ' /*这里只会识别第一个标签林某,而第二个徐某不会识别 */ }); var vm = new Vue({ el:"#myId", data:{ } }); script> body> 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> 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包住 */ }); var vm = new Vue({ el:"#myId", data:{ } }); script> body> html>林某 徐某
7-3:组件的值传递,通过 Prop 向子组件传递数据
父组件向子组件传递数据,使用 Prop,基于上面的组件,我想数据是从外面传进来了,而不是再组件里写死的,这样组件就能最大化的实现复用,我就是一
的组件,至于数据多少,有外部传进来的数据决定,那么我们可以使用Prop 向子组件传递数据
代码
<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 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: '
{ {name1}}---{ {name2}} ' }); var vm = new Vue({ el:"#myId", data:{ nameData: [ "林某","徐某","吴某","周某" ] } }); script> body> html>
7-4:子组件自定义变量data
子组件也想有自己定义的变量,组件内使用,使用data定义
代码
<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"> <myselect v-bind:myoption="dataOptions1">myselect> <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: '
' + ' + ' \n' + ' \n' + ' + ' { { option.text }}\n' + ' \n' + ' ' + <!-- 输出自定义遍历 --> ' 选择了:{ {game}},改变次数{ {count}}' }); 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异步通信
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,我们线上引入
示例代码
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Axios异步通信title> <style> [v-clock]{ display: none; } style> head> <body> <div id="myId" v-clock> { {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>
自己本地写一个接口,演示一下请求接口的数据
测试代码
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Axios异步通信title> <style> [v-clock]{ display: none; } style> head> <body> <div id="myId" v-clock> { {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>
9:计算属性computed
计算属性的重点突出在属性两字上(属性是名词),首先它是个属性,其次这个属性有计算的能力(计算是动词),在这里计算就是个函数,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的 属性),仅此而已,可以想象为缓存
上代码,注意看我们的func1和func2定义的位置
<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中,我们可以使用
元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中,通过插槽的name属性来确定插入的位置
示例代码
<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> <title_component slot="title_name" v-bind:inner_title="title">title_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: "
\" }); /*定义一个组件title_component*/ Vue.component("title_component",{ props:["inner_title"], <!-- 定义一个模板 --> template: "标题:
\\ 数据:
\\
\\ { {inner_title}}" }); /*定义一个组件item_component*/ Vue.component("item_component",{ props:["inner_item"], <!-- 定义一个模板 --> template: "{ {inner_item}} " }); var vm = new Vue({ el:"#myId", <!-- 定义数据title和books --> data:{ title: "好书集合!", books:["花季少年","雨后的故事",'放学后的教室'] } }); script> body> html>
11:自定义事件
通过以上插槽的代码中,我们不难发现,数据项在Vue的实例中,但删除操作要在组件中完成,那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数的传递与事件分发了,Vue为我们提供了自定义事件的功能,很好的帮助我们解决了这个问题。使用this.$emit(‘自定义事件名’,参数),操作过程如下
代码
<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> <title_component slot="title_name" v-bind:inner_title="title">title_component> <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: "
\" }); /*定义一个组件title_component*/ Vue.component("title_component",{ props:["inner_title"], <!-- 定义一个模板 --> template: "标题:
\\ 数据:
\\
\\ { {inner_title}}" }); /*定义一个组件item_component*/ Vue.component("item_component",{ props:["inner_item"], <!-- 定义一个模板,点击删除会执行inner_remove方法 --> template: "{ {inner_item}} ", 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中文网
换到NodeJs官网
查看是否安装成功
- cmd下输入node -v,查看是否能够正确打印出版本号即可
- cmd下输入nmp -v,查看是否能够正确打印出版本号即可
我的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
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:初始化并运行
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对象中,不同模块的调用都是一个作用域。
这些原始的加载方式暴露了一些显而易见的弊端:
- 全局作用域下容易造成变量冲突
- 文件只能按照