一、vue
官网:https://cn.vuejs.org/index.html
1.1Vue的简单概述
1.1.1、介绍:
Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
1.1.2、优点:
-
体积小
-
压缩后只有33k
-
-
更高的运行效率
-
基于虚拟dom,一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化的技术,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM。
-
-
双向数据绑定
-
开发者可以将中心投入到业务层,将业务更加的完善
-
-
生态丰富,易上手
-
市场上拥有大量成熟、稳定的基于vue.js的ui框架、常用组件,拿来即用实现快速开发!
-
对初学者友好、入门容易、学习资料多;
-
1.2、MVVM模式
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处
-
低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
-
可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
-
独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
-
可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
(1)View
View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。
(2)Model
Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
(3)ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。 需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的
-
比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
-
页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了View Model里。这样的封装使得View Model可以完整地去描述View层。由于实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。 MVVM框架已经把最脏最累的一块做好了, 我们开发者只需要处理和维护View Model, 更新数据视图就会自动得到相应更新,真正实现事件驱动编程。 View层展现的不是Model层的数据, 而是ViewModel的数据, 由ViewModel负责与Model层交互, 这就完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
1.3、安装和部署Vue.JS
1.3.1、通过CDN引入vue的全局变量
-
直接下载并用
<script>
标签引入(像引入JavaScript一样直接引入),Vue
会被注册为一个全局变量。
1.3.2、通过CDN引入vue的全局变量
-
对于制作原型或学习,你可以这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
-
对于生产环境,推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
-
原生 ES Modules,通过兼容 ES Module 的构建文件:
<script type="module">
import Vue from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.esm.browser.js'
</script>
请确认了解不同构建版本并在你发布的站点中使用生产环境版本,把 vue.js
换成 vue.min.js
。这是一个更小的构建,可以带来比开发环境下更快的速度体验。
1.3.3、通过npm引入vue的全局变量
在用 Vue 构建大型应用时推荐使用 NPM 安装[1]。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件
1.4、我的第一个Vue程序
1.4.1、双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--1.引入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<!--view层,模板-->
<div id="app">
{{message}}
</div>
<script type="text/javascript">
//创建Vue的对象
var vm = new Vue({
//通过id获取到模板中的节点 el: '#vue':绑定元素的ID
el:"#app",
//存储的数据值data:{message:'Hello World!'}:数据对象中有一个名为message的属性,并设置了初始值 Hello World!
data:{
message:"hello,World!"
}
});
</script>
</body>
</html>
在控制台中,通过vm对象对message进行赋值,页面中的数据同时同步更改,体现Vue的双向绑定的思想
1.5、数据与算法
-
当一个 Vue 实例被创建时,它将
data
对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="MyMethod">
{{a}}---{{b}}
</div>
<script type="text/javascript">
var data = { a: 1 }
//使用 Object.freeze()会阻止修改现有的 property,也意味着响应系统无法再追踪变化,相当于Java程序中被finally修饰,不可以再进行更改值。
Object.freeze(data)
// 该对象被加入到一个 Vue 实例中
var vm = new Vue({
el:"#MyMethod",
data: data
})
// vm.a = 2 //=>2
// data.a="test" // => test
// data.b="test"//数据添加失败,需要添加的数据要提前进行生命
</script>
</body>
</html>
案例:
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="MyMethod">
<div id="app">
<p>{{ foo }}</p>
<!-- v-on是对事件进行绑定的关键字-->
<button v-on:click="foo = 'success'">Change it</button>
</div>
</div>
<script type="text/javascript">
var obj = {
foo: 'bar'
}
Object.freeze(obj) //如果启动freeze()点击按钮不会进行更换,关闭之后点击按钮替换成success
new Vue({
el: '#app',
data: obj
})
</script>
</body>
</html>
1.6、生命周期
1.6.1组件
组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:
案例:
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/XSL/Transform">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app-7">
<ol>
<todo-item
v-for="item in groceryList"
v-bind:todo="item"
></todo-item>
</ol>
<ul>
<demo
<!--通过v-for对Vue对象中的数据进行遍历,再通过模板进行视图层的渲染-->
v-for="item in groceryList"
<!--通过v-bind组件中的props中的形参进行绑定传参-->
v-bind:tex="item"
></demo>
</ul>
</div>
<script type="text/javascript">
Vue.component('todo-item', {
props: ['todo'],
template: '<li>{{ todo.text }}</li>'
})
Vue.component("demo", {
props: ['tex'],
template: "<li>{{ tex.text }}</li>"
})
var app7 = new Vue({
el: '#app-7',
data: {
groceryList: [
{id: 0,text: '蔬菜' },
{id: 1,text: '奶酪' },
{id: 2,text: '随便其它什么人吃的东西' }
]
}
})
</script>
</body>
</html>
-
Vue.component():注册组件
-
demo:自定义组件的名字
-
template:组件的模板
-
v-for="item in groceryList":遍历Vue实例中定义的名为groceryList的数组,并创建同等数量的组件
-
v-bind:tex="item":将遍历的 groceryList 项绑定到组件中props定义名为item属性上;= 号左边的tex为props定义的属性名,右边的为item in groceryList中遍历的item项的值
在一个大型应用中,有必要将整个应用程序划分为组件,以使开发更易管理。以展示使用了组件的应用模板:
<div id="app">
<app-nav></app-nav>
<app-view>
<app-sidebar></app-sidebar>
<app-content></app-content>
</app-view>
</div>
1.6.1.1与自定义组件关系
你可能已经注意到 Vue 组件非常类似于自定义元素——它是 Web 组件规范的一部分,这是因为 Vue 的组件语法部分参考了该规范。例如 Vue 组件实现了 Slot API 与 is
attribute。但是,还是有几个关键差别:
-
Web Components 规范已经完成并通过,但未被所有浏览器原生实现。目前 Safari 10.1+、Chrome 54+ 和 Firefox 63+ 原生支持 Web Components。相比之下,Vue 组件不需要任何 polyfill,并且在所有支持的浏览器 (IE9 及更高版本) 之下表现一致。必要时,Vue 组件也可以包装于原生自定义元素之内。
-
Vue 组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。
虽然 Vue 内部没有使用自定义元素,不过在应用使用自定义元素、或以自定义元素形式发布时,依然有很好的互操作性。Vue CLI 也支持将 Vue 组件构建成为原生的自定义元素。
1.6.2、生命周期图示
1.7、模板语法-指令
指令带有前缀 v-*,以表示它们是 Vue 提供的特殊 attribute,它们会在渲染的 DOM 上应用特殊的响应式行为。
1.7.1、v-bind
我们已经成功创建了第一个Vue应用!看起来这跟渲染一个字符串模板非常类似, 但是Vue在背后做了大量工作。现在数据和DOM已经被建立了关联, 所有东西都是响应式的。我们在控制台操作对象属性,界面可以实时更新! 我们还可以使用v-bind来绑定元素特性! 案例
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
</span>
</div>
<script type="text/javascript">
var app2 = new Vue({
el: '#app-2',
data: {
//new Date().toLocaleString()获取当前时间转成字符串
message: '页面加载于 ' + new Date().toLocaleString()
}
})
</script>
</body>
</html>
你看到的v-bind等被称为指令。指令带有前缀v以表示它们是Vue提供的特殊特性。可能你已经猜到了, 它们会在渲染的DOM上应用特殊的响应式行为在这里,该指令的意思是:“将这个元素节点的title特性和Vue实例的message属性保持一致”。 如果你再次打开浏览器的JavaScript控制台, 输入app, message=‘新消息’,就会再一次看到这个绑定了title特性的HTML已经进行了更新。
1.7.2、v-if, v-else
条件判断语句,以下两个属性!
-
v-if
-
v-else
案例
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1 v-if="type">Yes</h1>
<h1 v-else>No</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
type: true
}
});
</script>
</body>
</html>
-
1.在浏览器上运行,打开控制台!
-
2.在控制台输入
vm.type=false
然后回车,浏览器中显示的内容会直接变成NO 注:使用v-*
属性绑定数据是不需要双花括号
包裹的
v-else-if
-
v-if
-
v-else-if
-
v-else 注:
===
三个等号在JS中表示绝对等于(就是数据与类型都要相等)上代码:
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<h1 v-if="type==='A'">A</h1>
<h1 v-else-if="type==='B'">B</h1>
<h1 v-else-if="type==='D'">D</h1>
<h1 v-else>C</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
type: 'A'
}
});
</script>
</body>
</html>
-
类同Java中的if-else if -else
1.7.3、v-for
-
v-for
格式说明
<div id="app-4">
<ol>
<li v-for="item in items">
{{item.message}}
</li>
</ol>
</div>
注:items
是数组,item
是数组元素迭代的别名。 案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--1.导入Vue.js-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<ol>
<li v-for="item in items">
{{item.message}}
</li>
</ol>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
items:[
{message:'Java从入门到放弃'},
{message:'Vue前端'},
{message:'ElementUI'}
]
}
});
</script>
</body>
</html>
测试:在控制台输入vm.items.push({message:'数据库从删库到跑路'})
,你会发现列表最后添加了一个数据库从删库到跑路。
1.7.4、v-on
v-on
监听事件 emsp;事件有Vue的事件、和前端页面本身的一些事件!我们这里的click
是vue的事件, 可以绑定到Vue中的methods
中的方法事件! 案例:
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<button v-on:click="hello">点我</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:'Hello World'
},
methods:{
//方法定义在Vue的methods对象中 方法名:function(){}
hello:function(){
//通过this调用vm对象中的值
alert(this.message);
}
}
});
</script>
</body>
</html>
v-on:事件名="事件函数名"
-
blur:失去焦点事件
-
focus:聚焦事件
-
click:点击事件
-
keyup:键盘弹起事件
-
keydown:键盘按下事件
1.7.5、V-model
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app-6">
<p>{{ message }}</p>
<input v-model="message">
</div>
<script type="text/javascript">
var app6 = new Vue({
el: '#app-6',
data: {
message: 'Hello Vue!'
}
})
</script>
</body>
</html>
-
Vue 还提供了
v-model
指令,实现表单输入和应用状态之间的双向绑定。
1.8、模板语法-插值
1.8.1、文本插值
数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg
property 的值。无论何时,绑定的数据对象上 msg
property 发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
<span v-once>这个将不会改变: {{ msg }}</span>
1.8.2、原始 HTML
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
指令:
<!DOCTYPE html>
<html lang="en" xmlns:v-html="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<span v-once>{{message}}</span>
<p v-html='rehtml'></p>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:"hello,vue!",
rehtml:'<span >Welcome to MyWorld!</span>'
}
});
</script>
</body>
</html>
这个 span
的内容将会被替换成为 property 值 rawHtml
,会在<p>标签中添加一个<span>的节点,直接作为 HTML——会忽略解析 property 值中的数据绑定。注意,你不能使用 v-html
来复合局部模板,因为 Vue 不是基于字符串的模板引擎。反之,对于用户界面 (UI),组件更适合作为可重用和可组合的基本单位。
1.8.3、Attribute
Mustache 语法不能作用在 HTML attrib ute 上,遇到这种情况应该使用 v-bind
指令:
<div v-bind:id="dynamicId"></div>
对于布尔 attribute (它们只要存在就意味着值为 true
),v-bind
工作起来略有不同,在这个例子中:
<button v-bind:disabled="isButtonDisabled">Button</button>
如果 isButtonDisabled
的值是 null
、undefined
或 false
,则 disabled
attribute 甚至不会被包含在渲染出来的 <button>
元素中。
<!DOCTYPE html>
<html lang="en" xmlns:v-html="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<span v-once>{{message}}</span>
<p v-html='rehtml'></p>
<div v-bind:class="color">demo</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
message:"hello,vue!",
rehtml:'<span >Welcome to MyWorld!</span>',
color:"red"
}
});
</script>
<style type="text/css">
.red{color:red;}
</style>
</body>
</html>
1.8.4、使用 JavaScript 表达式
迄今为止,在我们的模板中,我们一直都只绑定简单的 property 键值。但实际上,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="demo">
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#demo",
data:{
number:10,
ok:false,
message:"hello world"
}
});
</script>
</body>
</html>
参数绑定
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="demo">
<p v-if:seen>huanying</p>
<a v-bind:href="url">...</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#demo",
data:{
seen:true,
url : "www.baidu.com"
}
});
</script>
</body>
</html>
1.9、class与style绑定
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是 attribute,所以我们可以用 v-bind
处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
1.9.1、class绑定
-
v-bind:class
指令也可以与普通的 class attribute 共存 -
在对象中传入更多字段来动态切换多个 class
-
我们可以把一个数组传给
v-bind:class
,以应用一个 class 列表,这个时候应用的就是数组中的所有CSS样式:<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <div v-bind:class="['active','green']" >你好,世界</div> </div> <script type="text/javascript"> var vm = new Vue({ el:"#demo", data:{ active:true } }); </script> <style type="text/css"> .active{background: red} .green{font-size: 50px} </style> </body> </html>
1.9.2、style绑定
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <div v-bind: >你好,世界</div> </div> <script type="text/javascript"> var vm = new Vue({ el:"#demo", data:{ color:'red', fontsize:'50px', isTrue:true } }); </script> </body> </html>
1.9.3、在组件中进行渲染样式
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <my-component : > </my-component> </div> <script type="text/javascript"> Vue.component('my-component', { template: '<p class="foo bar">Hi</p>' }) var vm = new Vue({ el:"#demo", data:{ color:'red', fontsize:'50px', isTrue:true } }); </script> </body> </html>
1.10、条件渲染
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div> </div> </body> </html>
1.10.1、v-if vs v-show
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
1.10.2、在模板进行条件渲染
因为 v-if
是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 <template>
元素当做不可见的包裹元素,并在上面使用 v-if
。最终的渲染结果将不包含 <template>
元素。
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="demo">
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#demo",
data:{
ok:true
}
});
</script>
</body>
</html>
1.10.3、点击按钮,通过点击事件切换样式
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template> <button @click="demo">dianji</button> </div> <script type="text/javascript"> var vm = new Vue({ el:"#demo", data:{ loginType:"username", ok:true }, methods:{ demo:function () { if (this.loginType==='username'){ this.loginType="email" }else{ this.loginType="username" } } } }); </script> </body> </html>
1.10、列表渲染
1.10.1、遍历数组中的值
-
用
v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用item in items
形式的特殊语法,其中items
是源数据数组,而item
则是被迭代的数组元素的别名。
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <ul > <li v-for="item in items" :key="item.message"> {{ item.message }} </li> </ul> </div> <script type="text/javascript"> var example1 = new Vue({ el: '#demo', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) </script> </body> </html>
1.10.2、在 v-for 里使用对象
-
通过class的名字对dom对象进行定位,获取对象中的value值
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="demo"> <ul class="demo"> <li v-for="value in object"> {{ value }} </li> </ul> </div> <script type="text/javascript"> var example1 = new Vue({ el: '.demo', data: { object: { title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' } } }) </script> </body> </html>
-
获取对象中的key--value值
<li v-for="(value,name) of object"> ("value值","键值") {{ name }}--{{value}} </li>
将对象进行遍历,案例
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-if="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="demo">
<ul class="demo">
<li v-for="(value,name) of object">
{{ name }}--{{value}}
</li>
</ul>
</div>
<script type="text/javascript">
var example1 = new Vue({
el: '.demo',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})
</script>
</body>
</html>
1.10.3、数组更新检测
example1.items.push({ message: 'Baz' })
Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
-
push()
===>Combines two or more arrays.组合两个或多个数组。 -
pop()
===>Appends new elements to an array, and returns the new length of the array.向数组追加新元素,并返回数组的新长度。 -
shift()
===>Returns a section of an array.返回数组的一个部分。 -
unshift()
===>returns the index of the first occurrence of a value in an array.返回数组中一个值的第一个匹配项的索引。 -
splice()
===>Inserts new elements at the start of an array.在数组的开头插入新元素。 -
sort()
===>Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.从数组中移除元素,如果需要,在其位置插入新元素,并返回已删除的元素。 -
reverse()
===>Removes the first element from an array and returns it.从数组中移除第一个元素并返回它。
替换数组
变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()
、concat()
和 slice()
。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) { return item.message.match(/Foo/) })
1.11、事件绑定
-
同模板语法-指令:v-on
1.12、Axios异步通信
1.12.1、什么是Axios
Axios是一个开源的可以用在浏览器端和Node JS
的异步通信框架, 她的主要作用就是实现AJAX异步通信,其功能特点如下:
-
从浏览器中创建
XMLHttpRequests
-
从node.js创建http请求
-
支持Promise API[JS中链式编程]
-
拦截请求和响应
-
转换请求数据和响应数据
-
取消请求
-
自动转换JSON数据
-
客户端支持防御XSRF(跨站请求伪造)
1.12.2、为什么要使用Axios
由于Vue.js
是一个视图层框架并且作者(尤雨溪) 严格准守SoC(关注度分离原则)所以Vue.js
并不包含AJAX的通信功能, 为了解决通信问题, 作者单独开发了一个名为vue-resource
的插件, 在进入2.0版本以后停止了对该插件的维护并推荐了Axios
框架。少用jQuery, 因为它操作Dom太频繁!
1.12.3、第一个Axios应用程序
json
{
"name": "苗犇犇",
"url": "https://www.cnblogs.com/devilben/",
"page": 0,
"isNonProfit": true,
"address": {
"street": "浦江镇",
"city": "上海市闵行区",
"country": "中国"
},
"links": [
{
"name": "博客园",
"url": "https://home.cnblogs.com/"
},
{
"name": "DevilBen",
"url": "https://www.cnblogs.com/devilben/"
},
{
"name": "百度一下,你就知道",
"url": "https://www.baidu.com/"
}
]
}
测试
<!DOCTYPE html>
<html lang="en" xmlns:v-binf="http://www.w3.org/1999/xhtml" xmlns:v-for="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--引入js文件-->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
<!--将axios的js文件引入-->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="vue">
<div>名称:{{info.name}}</div>
<div>url:{{info.url}}</div>
<div>地址:{{info.address.country}}==={{info.address.city}}==={{info.address.street}}</div>
<ul>
<li v-for="link in info.links">
{{link.name}}===<a href="link.url" target="_blank" >{{link.url}}</a>
</li>
</ul>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#vue",
//data:属性:vm
data() {
return {
info: {
name: '',
url: '',
address: {
street: '',
city: '',
country:''
},
links:[]
}
}
},
mounted() { //通过钩子函数在装载的时候就将json中的数据渲染进入到前端界面中
axios.get('data.json').then(response => this.info = response.data)
}
});
</script>
</body>
</html>
说明:
-
在这里使用了v-bind将a:href的属性值与Vue实例中的数据进行绑定
-
使用axios框架的get方法请求AJAX并自动将数据封装进了Vue实例的数据对象中
-
我们在data中的数据结构必须和
Ajax
响应回来的数据格式匹配!
1.13、表单输入绑定
1.13.1、基础用法
v-model
指令在表单 <input>
、<textarea>
及 <select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值。
解释:在使用v-model的时候,原有控件中定义的初始值,全部失效
v-model
在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
-
text 和 textarea 元素使用
value
property 和input
事件; -
checkbox 和 radio 使用
checked
property 和change
事件; -
select 字段将
value
作为 prop 并将change
作为事件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<h3>
双向绑定
</h3>
<input type="text" v-model="message" placeholder="请输入值">
<p>你好: {{ message }}</p>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data:{
message:"hello vue"
}
})
</script>
</body>
</html>
1.13.2、多行文本的双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<h3>
双向绑定
</h3>
<span>多行文本中的内容:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data:{
message:"hello vue"
}
})
</script>
</body>
</html>
1.13.3、复选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
checkedNames: ['Mike']
}
})
</script>
</body>
</html>
v-model:在vue的实例中,data中定义v-model的数组,数组中的值是复选框选中的值
1.13.4、单选按钮
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="app"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <br> <span>Picked: {{ picked }}</span> </div> <script type="text/javascript"> var vm = new Vue({ el: 'app', data: { picked: '' } }) </script> </body> </html>
1.13.5、下拉菜单
-
静态渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
selected: ''
}
})
</script>
</body>
</html>
-
v-for动态渲染
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="app"> <select v-model="selected"> <option v-for="option in options" :value="option.value"> {{ option.text }} </option> </select> <span>Selected: {{ selected }}</span> </div> <script type="text/javascript"> new Vue({ el: '#app', data: { selected: 'A', options: [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ] } }) </script> </body> </html>
1.14、组件基础
1.14.1基本示例
Vue 组件的示例:
// 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
-
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是
<button-counter>
。我们可以在一个通过new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:<!DOCTYPE html> <html lang="en" xmlns:v-for="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="app"> <ul> <tempdemo v-for="item in info" :title="item"></tempdemo> </ul> </div> <script type="text/javascript"> Vue.component("tempdemo", { props: ['title'], template: "<li>{{title}}</li>" }) var vm = new Vue({ el: "#app", data: { info: [ "java从入门到放弃", "mysql从删库到跑路", "python从入门到入狱" ] } }) </script> </body> </html>
1.14.2、插槽
在Vue.js
中我们使用<slot>
元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中;
测试
创建一个待办事项组件(todo) , 该组件由待办标题(todo-title) 和待办内容(todo-items)组成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script>
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title">
</todo-title>
<todo-context slot="todo-context" v-for="item in info" :context=item></todo-context>
</todo>
</div>
<!--<div>-->
<!-- <slot name="todo-title"></slot>-->
<!-- <ul>-->
<!-- <slot name="todo-context"></slot>-->
<!-- </ul>-->
<!--</div>-->
<script type="text/javascript">
// 定义待办事项-组件
Vue.component("todo",{
template:"<div><slot name=\'todo-title\'></slot> <ul><slot name=\'todo-context\'></slot></ul></div>"
});
// 定义待办事项-标题 组件
Vue.component("todo-title",{
props:['title'],
template: "<div>{{title}}</div>"
});
// 定义待办事项-内容 组件
Vue.component("todo-context",{
props:['context'],
template:"<li>{{context}}</li>"
});
var vm = new Vue({
el:"#app",
data: {
title:"标题1",
info: [
"java从入门到放弃",
"mysql从删库到跑路",
"python从入门到入狱"
]
}
})
</script>
</body>
</html>
1.14.3、自定义事件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js"></script> </head> <body> <div id="app"> <todo> <todo-title slot="todo-title" :title="title"></todo-title> <todo-context slot="todo-context" v-for="(item,index) in info" :index="index" v-bind:context=item v-on:remove="removeItem"></todo-context> </todo> </div> <!--<div>--> <!-- <slot name="todo-title"></slot>--> <!-- <ul>--> <!-- <slot name="todo-context"></slot>--> <!-- </ul>--> <!--</div>--> <script type="text/javascript"> // 定义待办事项-组件 Vue.component("todo",{ template:"<div><slot name=\'todo-title\'></slot> <ul><slot name=\'todo-context\'></slot></ul></div>" }); // 定义待办事项-标题 组件 Vue.component("todo-title",{ props:['title'], template: "<div>{{title}}</div>" }); // 定义待办事项-内容 组件 Vue.component("todo-context",{ props:['index','context'], template:"<li>{{index}}--{{context}}<button @click='remove'>删除</button></li>", methods:{ remove:function (){ this.$emit("remove") } } }); var vm = new Vue({ el:"#app", data: { title:"标题1", info: [ "java从入门到放弃", "mysql从删库到跑路", "python从入门到入狱" ], methods:{ removeItem:function (index) { this.splice(index,1) //根据下表删除 } } } }) </script> </body> </html>
1.15、Vue-cli
介绍
Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供:
-
通过
@vue/cli
实现的交互式的项目脚手架。 -
通过
@vue/cli
+@vue/cli-service-global
实现的零配置原型开发。 -
一个运行时依赖 (
@vue/cli-service
),该依赖:
-
可升级;
-
基于 webpack 构建,并带有合理的默认配置;
-
可以通过项目内的配置文件进行配置;
-
可以通过插件进行扩展。
-
-
一个丰富的官方插件集合,集成了前端生态中最好的工具。
-
一套完全图形化的创建和管理 Vue.js 项目的用户界面。
Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject。
主要功能:
-
统一目录结构
-
本地调试
-
热部署
-
单元测试
-
集成打包测试
环境准备:
-
node.js
-
git
该系统的组件
Vue CLI 有几个独立的部分——如果你看到了我们的源代码,你会发现这个仓库里同时管理了多个单独发布的包。
CLI
CLI (@vue/cli
) 是一个全局安装的 npm 包,提供了终端里的 vue
命令。它可以通过 vue create
快速搭建一个新项目,或者直接通过 vue serve
构建新想法的原型。你也可以通过 vue ui
通过一套图形化界面管理你的所有项目。我们会在接下来的指南中逐章节深入介绍。
CLI 服务
CLI 服务 (@vue/cli-service
) 是一个开发环境依赖。它是一个 npm 包,局部安装在每个 @vue/cli
创建的项目中。
CLI 服务是构建于 webpack 和 webpack-dev-server 之上的。它包含了:
-
加载其它 CLI 插件的核心服务;
-
一个针对绝大部分应用优化过的内部的 webpack 配置;
-
项目内部的
vue-cli-service
命令,提供serve
、build
和inspect
命令。
如果你熟悉 create-react-app 的话,@vue/cli-service
实际上大致等价于 react-scripts
,尽管功能集合不一样。
CLI 服务章节涵盖了它的具体用法。
CLI 插件
CLI 插件是向你的 Vue 项目提供可选功能的 npm 包,例如 Babel/TypeScript 转译、ESLint 集成、单元测试和 end-to-end 测试等。Vue CLI 插件的名字以 @vue/cli-plugin-
(内建插件) 或 vue-cli-plugin-
(社区插件) 开头,非常容易使用。
当你在项目内部运行 vue-cli-service
命令时,它会自动解析并加载 package.json
中列出的所有 CLI 插件。
插件可以作为项目创建过程的一部分,或在后期加入到项目中。它们也可以被归成一组可复用的 preset。我们会在插件和 preset 章节进行深入讨论。
安装:
Vue3安装:
#安装vue3 npm uninstall -g @vue/cli
vue create
运行以下命令来创建一个新项目:
#创建一个名称位hello-world的项目
vue create hello-world
#进入项目目录下 cd hello-world #运行项目 npm run serve
执行结果页面
Vue2
-
安装Node.js淘宝镜像加速器
# -g 就是全局安装 npm install cnpm -g # 或使用如下语句解决npm速度慢的问题 npm install --registry=https://registry.npm.taobao.org
安装的过程可能有点慢~,耐心等待!虽然安装了cnpm,但是尽量少用!
安装的位置:C:\Users\administrator\AppData\Roaming\npm
-
安装vue-cli
cnpm instal1 vue-cli -g #测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack vue list
1.创建一个Vue项目,我们随便建立一个空的文件夹在电脑上,我这里在D盘下新建一个目录
D:\Project\vue-study;
2.创建一个基于webpack模板的vue应用程序
#1、首先需要进入到对应的目录 cd D:\Project\vue-study #2、这里的myvue是顶日名称,可以根据自己的需求起名 vue init webpack myvue
一路都选择no即可; 说明:
-
Project name:项目名称,默认回车即可
-
Project description:项目描述,默认回车即可
-
Author:项目作者,默认回车即可
-
Install vue-router:是否安装vue-router,选择n不安装(后期需要再手动添加)
-
Use ESLint to lint your code:是否使用ESLint做代码检查,选择n不安装(后期需要再手动添加)
-
Set up unit tests:单元测试相关,选择n不安装(后期需要再手动添加)
-
Setupe2etests with Nightwatch:单元测试相关,选择n不安装(后期需要再手动添加)
-
Should we run npm install for you after the,project has been created:创建完成后直接初始化,选择n,我们手动执行;运行结果!
(1)初始化并运行
#进入程序目录 cd myvue #安装依赖 npm install #运行程序 npm run dev
执行完成后,目录多了很多依赖
当出现问题时,可以查看提示进行处理
package.json里面有一些配置,主要的配置
node—modules依赖
1.16、Webpack
什么是Webpack
webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler) 。当webpack处理应用程序时, 它会递归地构建一个依赖关系图(dependency graph) , 其中包含应用程序需要的每个模块, 然后将所有这些模块打包成一个或多个bundle. Webpack是当下最热门的前端资源模块化管理和打包工具, 它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。
安装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
-
创建项目
-
创建一个名为modules的目录,用于放置JS模块等资源文件
-
在modules下创建模块文件,如hello.js,用于编写JS模块相关代码
//暴露一个方法:sayHi
exports.sayHi = function () {
document.write("<h1><div>hello world </div></h1>")
}
-
在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
//require 导入一个模块,就可以调用这个模块中的方法了 var hello = require("./hello"); hello.sayHi();
-
在项目目录下创建webpack.config.js配置文件,使用webpack命令打包
module.exports = { entry:"./modules/main.js", output:{ filename:"./js/bundle.js" } }
-
在项目目录下创建HTML页面,如index.html,导入webpack打包后的JS文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script src="dist/js/bundle.js"></script> </body> </html>
-
在IDEA控制台中webpack打包,需要管理员权限;
-
运行HTML看效果
# 参数--watch 用于监听变化,通过webpack --watch实现热部署
1.17、Vue-route
介绍
Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括:
-
嵌套路由映射
-
动态路由选择
-
模块化、基于组件的路由配置
-
路由参数、查询、通配符
-
展示由 Vue.js 的过渡系统提供的过渡效果
-
细致的导航控制
-
自动激活 CSS 类的链接
-
HTML5 history 模式或 hash 模式
-
可定制的滚动行为
-
URL 的正确编码
安装
基于第一个vue-cli
查看node modules中是否存在vue-router vue-router是一个插件包, 需要用n pm/cn pm来进行安装的。打开命令行工具,进入项目目录,输入下面命令。
npm install vue-router --save-dev
如果在一个模块化工程中使用它,要通过 Vue.use()
明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
如果使用全局的 script 标签,则无须如此 (手动安装)
测试
1、先删除没有用的东西 2、components
目录下存放我们自己编写的组件 3、定义一个Login.vue 的组件
<template>
<div>内容</div>
</template>
<script>
export default {
name: "Login"
}
</script>
<style scoped>
</style>
Main.vue组件
<template> <div>首页</div> </template> <script> export default { name: "Main" } </script> <style scoped> </style>
4、安装路由,在src目录下,新建一个文件夹:router,专门存放路由,配置路由index.js,如下
import Vue from'vue'
//导入路由插件
import Router from 'vue-router'
//导入上面定义的组件
import Login from '../views/Login'
import Main from '../views/Main'
//安装路由
Vue.use(Router) ;
//配置路由
export default new Router({
routes:[
{
//路由路径
path:'/login',
//路由名称
name:'login',
//跳转到组件
component:Login
},{
//路由路径
path:'/main',
//路由名称
name:'main',
//跳转到组件
component:Main
}
]
});
5、在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/>'
});
6、在App.vue中使用路由
<template>
<div id="app">
<!--
router-link:默认渲染成一个<a>标签,to属性为指定链接
router-view:用于渲染路由匹配到的组件
-->
<router-link to="/main">首页</router-link>
<router-link to="/login">内容页</router-link>
<router-view/>
</div>
</template>
<script>
export default{
name:'App'
}
</script>
<style></style>
二、elementUI
官网:https://element.eleme.cn/#/zh-CN
安装:
npm 安装
推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。
npm i element-ui -S
CDN
目前可以通过 unpkg.com/element-ui 获取到最新版本的资源,在页面上引入 js 和 css 文件即可开始使用。
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
我们建议使用 CDN 引入 Element 的用户在链接地址上锁定版本,以免将来 Element 升级时受到非兼容性更新的影响。锁定版本的方法请查看 unpkg.com。
2.1、vue+elementUI整合
我们采用实战教学模式并结合ElementUI组件库,将所需知识点应用到实际中,以最快速度带领大家掌握Vue的使用;
2.1.1、创建工程
注意:命令行都要使用管理员模式运行 1、创建一个名为hello-vue的工程vue init webpack vue-element
2、安装依赖, 需要安装vue-router、element-ui、sass-loader和node-sass四个插件
#下载Vue2
npm install vue-cli -g
#创建项目文件
vue init webpack vue-element
#进入工程目录
cd vue-element
#安装vue-routern
npm install vue-router@3 --save-dev #将版本操作,会更好一写
#安装element-ui
npm i element-ui -S
#安装依赖
npm install
# 安装SASS加载器
#cnpm install sass-loader node-sass --save-dev #最新版本,有问题
cnpm install [email protected] node-sass --save-dev #通过@指定版本
#启功测试
npm run dev
在源码目录中创建如下结构:
-
assets:用于存放资源文件
-
components:用于存放Vue功能组件
-
views:用于存放Vue视图组件
-
router:用于存放vue-router配置
2.2、路由详解+常用的组件
-
Form
<template>
<el-form ref="form" :model="form" class="login-box" :rules="rules">
<h2 class="login-title">欢迎登陆</h2>
<el-form-item label="账号" prop="name">
<el-input type="text" placeholder="请输入用户名" v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" placeholder="请输入密码" v-model="form.password"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="submitForm('form')" type="primary">登录</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
name: "Login",
data(){
return{
form:{
name:"",
password:""
},
rules: {
name: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
]
}
}
},
methods:{
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$router.push("/main");
} else {
this.$message({
message: '账号或密码错误',
type: 'warning'
});
return false;
}
});
},
}
}
</script>
<style scoped>
.login-box{
width: 350px;
margin: 120px auto;
border: 2px solid #909399;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 30px #909399;
}
.login-title{
text-align: center;
}
</style>
路由嵌套
-
main.vue组件
<template>
<div>
<el-container>
<el-aside width="200px">
<el-menu :default-openeds="['1']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>会员管理</template>
<el-menu-item-group>
<el-menu-item index="1-1">
<router-link to="/member/level">会员等级</router-link>
</el-menu-item>
<el-menu-item index="1-2">
<router-link to="/member/list">会员列表</router-link>
</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-message"></i>商品管理</template>
<el-menu-item-group>
<el-menu-item index="1-1">商品分类</el-menu-item>
<el-menu-item index="1-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>
<span>admin</span>
</el-header>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
-
在views/member目录下创建MemberList.vue会员列表的组件
<template>
<h1>会员列表</h1>
</template>
<script>
export default {
name: "MemberList"
}
</script>
<style scoped>
</style>
-
在views/member目录下创建MemberLevel会员等级的组件
<template>
<h1>会员等级</h1>
</template>
<script>
export default {
name: "MemberLevel"
}
</script>
<style scoped>
</style>
-
路由嵌套的index.js 文件
//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
import MemberList from "../views/Member/MemberList";
import MemberLevel from "../views/Member/MemberLevel";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({
routes: [
{
//登录页
path: '/main',
component: Main,
//嵌套子路由
children:[
{
path:"/member/list",
name:"MemberList",
component:MemberList
},
{
path:"/member/level",
name:"MemberLevel",
component:MemberLevel
}
]
},
//首页
{
path: '/login',
component: Login
},
]
})
参数传递
路径匹配:
修改路由的配置
这里演示如果请求带有参数该怎么传递 demo 用的还是上述例子的代码 修改一些代码 这里不放重复的代码了 第一种取值方式 1、 修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符
{
path:"/member/level/:id",
name:"MemberLevel",
component:MemberLevel,
}
2、传递参数 此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径;
<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定-->
<router-link :to="{name:'MemberLevel',params:{id:1}}">个人信息</router-link>
12
3、在的组件 Member.vue中接收参数 使用 {{$route.params.id}}来接收
<template>
<div>
会员等级+id={{$route.params.id}}
</div>
</template>
props传值:
main.vue
<template> <div> <el-container> <el-aside width="200px"> <el-menu :default-openeds="['1']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>会员管理</template> <el-menu-item-group> <el-menu-item index="1-1"> <router-link :to="{name:'MemberLevel',params:{id:3}}">会员等级</router-link> </el-menu-item> <el-menu-item index="1-2"> <router-link to="/member/list">会员列表</router-link> </el-menu-item> </el-menu-item-group> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-message"></i>商品管理</template> <el-menu-item-group> <el-menu-item index="1-1">商品分类</el-menu-item> <el-menu-item index="1-2">商品列表</el-menu-item> </el-menu-item-group> </el-submenu> </el-menu> </el-aside> <el-container> <el-header > <el-dropdown> <i class="el-icon-setting" ></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>用户中心</el-dropdown-item> <el-dropdown-item>退出登录</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>{{$route.params.name}}</span> </el-header> <el-main> <router-view/> </el-main> </el-container> </el-container> </div> </template> <script> export default { name: "Main" } </script> <style scoped> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style>
login.vue
<template> <el-form ref="form" :model="form" class="login-box" :rules="rules"> <h2 class="login-title">欢迎登陆</h2> <el-form-item label="账号" prop="name"> <el-input type="text" placeholder="请输入用户名" v-model="form.name"></el-input> </el-form-item> <el-form-item label="密码" prop="password"> <el-input type="password" placeholder="请输入密码" v-model="form.password"></el-input> </el-form-item> <el-form-item> <el-button @click="submitForm('form')" type="primary">登录</el-button> </el-form-item> </el-form> </template> <script> export default { name: "Login", data(){ return{ form:{ name:"", password:"" }, rules: { name: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' } ] } } }, methods:{ submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { this.$router.push({name:'Main',params:{name:this.form.name}}); } else { this.$message({ message: '账号或密码错误', type: 'warning' }); return false; } }); }, } } </script> <style scoped> .login-box{ width: 350px; margin: 120px auto; border: 2px solid #909399; padding: 10px; border-radius: 10px; box-shadow: 0 0 30px #909399; } .login-title{ text-align: center; } </style>
通过props进行值传递的时候,要设置props:true ,如下,index.js:
//导入vue import Vue from 'vue'; import VueRouter from 'vue-router'; //导入组件 import Main from "../views/Main"; import Login from "../views/Login"; import MemberList from "../views/Member/MemberList"; import MemberLevel from "../views/Member/MemberLevel"; //使用 Vue.use(VueRouter); //导出 export default new VueRouter({ routes: [ { //登录页 path: '/main', name:"Main", component: Main, children:[ //会员列表 { path:"/member/list", name:"MemberList", component:MemberList }, //会员等级 { path:"/member/level/:id", name:"MemberLevel", component:MemberLevel, props:true } ] }, //首页 { path: '/login', name:"Login", component: Login }, ] })
MemberLevel.vue
<template> <h1>会员等级+id={{id}}</h1> </template> <script> export default { props:['id'], name: "MemberLevel" } </script> <style scoped> </style>
组件重定向
重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下,比如: 在router下面index.js的配置
//导入vue import Vue from 'vue'; import VueRouter from 'vue-router'; //导入组件 import Main from "../views/Main"; import Login from "../views/Login"; import MemberList from "../views/Member/MemberList"; import MemberLevel from "../views/Member/MemberLevel"; //使用 Vue.use(VueRouter); //导出 export default new VueRouter({ routes: [ { //首页 path: '/main/:name', name: "Main", component: Main, children: [ //会员列表 { path: "/member/list", name: "MemberList", component: MemberList }, //会员等级 { path: "/member/level/:id", name: "MemberLevel", component: MemberLevel, props: true }, //返回首页 { path: "/goHome/:name", redirect:"/main/:name" } ] }, //登录页 { path: '/login', name: "Login", component: Login }, ] })
说明:这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件;
使用的话,只需要在Main.vue设置对应路径即可;
<template> <div> <el-container> <el-aside width="200px"> <el-menu :default-openeds="['1']"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>会员管理</template> <el-menu-item-group> <el-menu-item index="1-1"> <router-link :to="{name:'MemberLevel',params:{id:3}}">会员等级</router-link> </el-menu-item> <el-menu-item index="1-2"> <router-link to="/member/list">会员列表</router-link> </el-menu-item> <el-menu-item index="1-2"> <router-link to="/goHome/admin123">返回主页</router-link> </el-menu-item> </el-menu-item-group> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-message"></i>商品管理</template> <el-menu-item-group> <el-menu-item index="1-1">商品分类</el-menu-item> <el-menu-item index="1-2">商品列表</el-menu-item> </el-menu-item-group> </el-submenu> </el-menu> </el-aside> <el-container> <el-header > <el-dropdown> <i class="el-icon-setting" ></i> <el-dropdown-menu slot="dropdown"> <el-dropdown-item>用户中心</el-dropdown-item> <el-dropdown-item>退出登录</el-dropdown-item> </el-dropdown-menu> </el-dropdown> <span>{{$route.params.name}}</span> </el-header> <el-main> <router-view/> </el-main> </el-container> </el-container> </div> </template> <script> export default { name: "Main" } </script> <style scoped> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } </style>
路由模式与 404
路由模式有两种
-
hash:路径带 # 符号,如 http://localhost/#/login
-
history:路径不带 # 符号,如 http://localhost/login
默认是hash模式的
修改路由模式:
export default new Router({ mode: 'history', routes: [ ] });
404 demo 1.新建一个NotFound.vue视图组件 NotFound.vue
<template> <div> <h1>404,你的页面走丢了</h1> </div> </template> <script> export default { name: "NotFound" } </script> <style scoped> </style>
2.修改路由配置index.js
//在路由index.js中将组件引入,路由中添加 import NotFound from '../views/NotFound' { path: '*', component: NotFound }
路由钩子与异步请求
beforeRouteEnter:在进入路由前执行 beforeRouteLeave:在离开路由前执行
在Profile.vue中写
export default { name: "UserProfile", beforeRouteEnter: (to, from, next) => { console.log("准备进入个人信息页"); next(); }, beforeRouteLeave: (to, from, next) => { console.log("准备离开个人信息页"); next(); } }
参数说明: to:路由将要跳转的路径信息 from:路径跳转前的路径信息 next:路由的控制参数 next() 跳入下一个页面 next(’/path’) 改变路由的跳转方向,使其跳到另一个路由 next(false) 返回原来的页面 next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例
在钩子函数中使用异步请求
cnpm install --save vue-axios import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
1、安装 Axios
npm install axios -s
2、main.js引用 Axios
import Vue from 'vue' import App from './App' import Router from "vue-router" import router from "./router" //引入axios import axios from "axios"; import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(Router) Vue.use(ElementUI) //使用axios Vue.prototype.axios = axios /* eslint-disable no-new */ new Vue({ el: '#app', router, render:h=>h(App) })
3、准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。 数据和之前用的json数据一样 需要的去上述axios例子里
// 静态数据存放的位置 static/mock/data.json { "name": "苗犇犇", "url": "https://www.cnblogs.com/devilben/", "page": 0, "isNonProfit": true, "address": { "street": "浦江镇", "city": "上海市闵行区", "country": "中国" }, "links": [ { "name": "博客园", "url": "https://home.cnblogs.com/" }, { "name": "DevilBen", "url": "https://www.cnblogs.com/devilben/" }, { "name": "百度一下,你就知道", "url": "https://www.baidu.com/" } ] }
4.在 beforeRouteEnter 中进行异步请求 MemberLevel.vue
<template> <h1>会员等级+id={{id}}</h1> </template> <script> export default { props: ['id'], name: "MemberLevel", //使用路由钩子函数 beforeRouteEnter: (to, from, next) => { //加载数据 //进入路由之前执行getData方法 next(vm => { vm.getData(); }); }, beforeRouteLeave: (to, from, next) => { alert("离开路由"); next(); }, methods: { getData: function () { this.axios({ method: 'get', // url: 'http://localhost:8080/static/mock/data.json' url: 'Access-Control-Allow-Origin:http://localhost:8080/static/mock/data.json' }).then(function (response) { console.log(response) }) } } } </script> <style scoped> </style>
参数说明: to:路由将要跳转的路径信息 from:路径跳转前的路径信息 next:路由的控制参数 next() 跳入下一个页面 next(’/path’) 改变路由的跳转方向,使其跳到另一个路由 next(false) 返回原来的页面 next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例
5.实现图
问题官网:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin
url: 'http://localhost:8080/static/mock/data.json' //存在跨域问题 url: 'Access-Control-Allow-Origin:http://localhost:8080/static/mock/data.json' //解决跨域问题
-
-
Basic
-
Data
-
Notice
-
Nav
-
Others
2.3、栅格系统
<el-container>
:外层容器。当子元素中包含 <el-header>
或 <el-footer>
时,全部子元素会垂直上下排列,否则会水平左右排列。
<el-header>
:顶栏容器。
<el-aside>
:侧边栏容器。
<el-main>
:主要区域容器。
<el-footer>
:底栏容器。
以上组件采用了 flex 布局,使用前请确定目标浏览器是否兼容。此外,<el-container>
的子元素只能是后四者,后四者的父元素也只能是 <el-container>
。
通过组件的方式,结合elementUI的样式,进行前端的开发
2.4、VueX
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
安装
npm install vuex@3 --save //指定版本号
引入到main.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
判断用户登录
使用钩子函数进行判断
// 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 App from './App' import Router from "vue-router" import router from "./router" import axios from "axios"; import Vue from 'vue' import Vuex from 'vuex' import store from './store' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(Vuex) Vue.use(store) Vue.use(Router) Vue.use(ElementUI) Vue.prototype.axios = axios router.beforeEach((to, from, next) => { var isLogin = sessionStorage.getItem("isLogin"); //注销 if (to.path == "/logout"){ sessionStorage.clear(); next({path:'/login'}); }else if (to.path=="/login"){ if (isLogin!=null){ next({path:'/main'}); } }else if (isLogin==null){ next({path:'/login'}); } next(); }) /* eslint-disable no-new */ new Vue({ el: '#app', router, render:h=>h(App) })标签:Vue,入门,vue,组件,new,data,name From: https://www.cnblogs.com/devilben/p/17902404.html