目录;
1.vue介绍 1.1 什么是vue1.2 vue的优点2. 库和框架的区别 2.1 库2.2 框架vue是一个构建用户界面UI的渐进式javascript框架;渐进式的框架是指可以一步一步的由浅入深的去使用这个框架;该框架可以逐步引入项目。作者;尤雨溪
vue官网 https://cn.vuejs.org/
1.体积小
压缩后33k左右;体积小意味着下载速度很快。
2.更高的运行效率
基于虚拟dom;一种预先通过javascript进行各种计算;把最终的DOM操作计算出来并进行优化的技术。所谓虚拟dom指的是对真实dom的一种模拟。相对于直接操作真实dom;我们构建一棵虚拟的dom树;将各式数据和操作直接应用到这颗虚拟的dom树上;然后再虚拟的树修改应用到真实的dom树中;有助于减少dom的操作次数;带来性能上的提升;可以频繁的操作虚拟节点;然后一定时刻一次性的同步修改到真实dom节点
3.双向数据绑定
让开发者不用再去操作dom对象;把更多精力投入到业务逻辑上来
4.生态丰富;学习比较简单
市场上有很多稳定成熟的基于vue的ui框架可以拿来使用;实现快速开发。中国人开发的;中文资料丰富。
本质上是一些函数的集合。每次调用函数;实现一个特定的功能;接着把控制权交给使用者;js中最典型的是jQuery;jquery本质上是封装dom操作;简化dom操作的工具库
框架是一套完整的解决方案;使用框架是需要遵循框架的规则;将代码放入框架的合适位置;框架在合适的时候调用代码。代表Vue。一种框架会规定自己的编程方式;侵入性较高。
MVVM;一种更好的UI模式解决方案;MVVM通过数据双向绑定让数据自动地双向同步
虽然没有完全遵循MVVM模型;Vue的设计无疑受到了它的启发。另外一个js框架“knockout”完全遵循MVVM模型
学习Vue要转化思想;“不要在想着怎么操作DOM;而是想着如何操作数据;;;”
cdn下载;需要网络;
<!-- 开发环境版本;包含了有帮助的命令行警告 -->
<script src=;https://cdn.jsdelivr.net/npm/vue/dist/vue.js;></script>
<!-- 生产环境版本;优化了尺寸和速度 -->
<script src=;https://cdn.jsdelivr.net/npm/vue;></script>
手动下载
<!-- 开发环境版本;包含了有帮助的命令行警告 -->
<script src=;dist/vue.js;></script>
<!-- 生产环境版本;优化了尺寸和速度 -->
<script src=;dist/vue.min.js;></script>
CDN加速
CDN的全称是Content Delivery Network;即内容分发网络;CDN是构建在网络之上的内容分发网络;依靠部署在各地的边缘服务器;通过中心平台的负载均衡、内容分发、调度等功能模块;使用户就近获取所需内容;降低网络拥塞;提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。CDN加速主要是加速静态资源;如网站上面上传的图片、媒体;以及引入的一些Js、css等文件。CDN加速需要依靠各个网络节点;例如100台CDN服务器分布在全国范围;从上海访问;会从最近的节点返回资源;这是核心。CDN服务器通过缓存或者主动抓取主服务器的内容来实现资源储备。CDN基本原理;将源站内容分发至最接近用户的节点;使用户可就近取得所需内容;提高用户访问的响应速度和成功率。
CDN部署在网络提供商的机房;是用户在请求网络服务的时候;可以从距离最近的网络提供商机房获取数据。
最大的优势就是可以让用户就近访问资源.
BootCDN
BootCDN是Bootstrap中文网支持并维护的前端开源项目免费CDN服务;致力于为Bootstrap、jQuery、Angular、Vuejs一样优秀的前端开源项目提供稳定、快速的免费 CDN 加速服务官网 https://www.bootcdn.cn/
vue有两种开发方式;一种是直接页面开发;一种是工程级开发;本示例使用的是直接页面开发方式。
//创建vue实例
var vm = new Vue({
//指定管理区域
el: ;#app;,
data: {
msg: ;hello vue;
}
});
<div id=;app;>
<h1>{{msg}}, {{ts}}</h1>
</div>
可以将div中的id属性改一个名称;查看一下信息是否还能正常输出;体会一下vue内容管理区的概念和特点。
data属性既可以是一个json对象也可以是一个函数;如;
var vm = new Vue({
el: ;#app;,
data: function(){
return {
msg: ;hello vue;,
ts: new Date().getTime()
}
}
});
注意;data在组件开发中的写法必须是函数。
示例;
var vm = new Vue({
el: ;#app;,
data: function(){
return {
msg: ;hello vue;,
ts: new Date().getTime()
}
},
//定义交互事件
methods: {
clickme: function(){
console.log(;点到我了;);
}
}
});
<div id=;app;>
<h1>{{msg}}, {{ts}}</h1>
<!-- v-on: vue绑定事件的处理函数的方式 -->
<button v-on:click=;clickme();>点我试试</button>
</div>
打开开发者工具;点击按钮;在console中查看点击事件的效果。
双向数据绑定;指的是数据的改变会引起dom的改变;dom的改变也会引起数据的改变。
示例;
<div id=;app;>
<input type=;text; v-model=;msg; ;keyup=;change();>
<button v-on:click=;setVal;>改变值</button>
</div>
var vm = new Vue({
//指定vue实例的管理区域,也叫边界
el: ;#app;,
data: function() {
return {
msg: ;hello vue;
}
},
methods: {
change: function() {
console.log(this.msg);
},
setVal: function() {
this.msg = ;hello hello;;
}
}
});
打开开发者工具;在文本框中输出数据;观察console中的输出;可以看到数据双向绑定的效果。
注意点
只有当实例被创建时已经在data中存在的属性才是响应式的用v-model指令在表单控件元素上创建双向数据绑定this在methods属性的方法里指向当前Vue实例;如果需要外部访问可以使用vm.name/vm.$data.name的方式用v-once指令进行单向绑定;一般不用console对象可以使用printf风格的占位符。只支持字符%s;、整数%d或%i;、浮点数%f;和对象%o;四种Vue实例还暴露了一些有用的实例属性与方法。它们都有前缀$;以便与用户定义的属性区分开来
生命周期钩子示例已经在资料中提供;将demo4.html拷入项目即可。通过该示例了解vue常用的生命周期钩子;及其作用。
每个Vue实例在被创建时都要经过一系列的初始化过程——例如;需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数;这给了用户在不同阶段添加自己的代码的机会。
生命周期函数;
目录;
1. 模板语法 1.1 插值 1.1.1 文本1.1.2 html1.1.3 属性1.1.4 表达式1.2 指令 1.2.1 核心指令 1.2.1.1 v-if |v-else-if|v-else1.2.1.2 v-show1.2.1.3 v-for1.2.1.4 v-on|v-model|v-for1.2.1.5 参数 v-bind:href,v-on:click1.2.1.6 简写2. 过滤器 2.1 局部过滤器2.2 全局过滤器3. 计算属性4.监听属性Vue.js 使用了基于 HTML 的模板语法;允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ;所以能被遵循规范的浏览器和 HTML 解析器解析。vue将模板编译成虚拟dom;
结合响应系统;Vue 能够智能地计算出最少需要重新渲染多少组件;并把 DOM 操作次数减到最少。
html模板语法;
这是一种基于字符串的模板技术,以字符串和数据为输入,通过用正则表达式将占位符替换为所需数据的方式,构建出完整的 HTML 字符串。
使用{{msg}}的形式;标签将会被替换成为数据对象;data;上msg属性值;当绑定的数据对象上的msg属性值发生变化时;插值处的值也会发生变化;双向绑定;
示例;上节课的hello vue示例使用的就是插值。
{{}}的方式将数据处理为普通文本;如果要输出html;需要使用v-html指令
示例;
在data中定义一个html属性;其值为html
data: {
html: ;<input type=;text; value=;hello;/>;
}
在html中取值
<span v-html=;html;></span>
HTML属性中的值应使用v-bind指令。类型与jQuery中的$(;#xxx;).attr(propName, propVal)
示例;以修改元素的class属性为例;
定义一个样式
<style>
.redClass {
font-size: 30px;
color: red;
}
</style>
在data中定义一个属性;其值为上面定义的样式名
data: {
red: ;redClass;
}
在html使用v-bind指令设置样式
<p>设置之前: aaaa</p>
<p>设置之后: <span v-bind:class=;red;>aaa</span></p>
在浏览器中可以看到相应的效果
几种常见的表达式;
{{str.substr(0,6).toUpperCase()}}{{ number ; 1 }}{{ ok ? ;YES; : ;NO; }} 三元运算符<li v-bind:>我的Id是js动态生成的</li>示例1;
在html中加入元素;定义表达式
<span>{{str.substr(0,6).toUpperCase()}}</span>
在data中加入一个属性;名为str与html中对应
data: {
str: ;hello vue;
}
查看效果;字符串被截取;并转换为大写
示例2;
<span>{{ number ; 1 }}</span>
在data中加入一个属性;名为str与html中对应
data: {
number: 10
}
在data中定义的number值将会被加1
示例3;
这是一个三元运算;如果ok为true;表达式值为YES ;如果ok为false则表达式值为NO
<span>{{ ok ? ;YES; : ;NO; }}</span>
在data中加入一个属性;名为str与html中对应
data: {
ok: true
}
示例4;
演示id属性绑定和动态赋值
<p>
<input type=;text; v-bind:id=;bookId;/></br>
<!--动态生成Id-->
<input type=;text; v-bind:id=;;bookList_; ; id;/>
</p>
data: {
bookId: ;book001;,
id: ;book002;
}
该示例可以通过开发者工具查看生成的id属性值。
指令指的是带有“v-;前缀的特殊属性
1.2.1.1 v-if |v-else-if|v-else
根据其后表达式的bool值进行判断是否渲染该元素; 指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况;稍后我们再讨论)
示例;
HTML
<div v-if=;type === ;A;;>
type == A
</div>
<div v-else-if=;type === ;B;;>
type == B
</div>
<div v-else>
other value
</div>
JS
var vm = new Vue({
el: ;#app;,
data: {
type: ;C;
}
});
可以修改data中的type值观察页面的输出。
注; js = == === 之间的区别
一个等号是赋值操作;==先转换类型再比较;===先判断类型;如果不是同一类型直接为false
alert(1 == “1”); // true
alert(1 === “1”); // false
1.2.1.2 v-show
与v-if类似;只是不会渲染其身后表达式为false的元素;而且会给这样的元素添加css代码;style=;display:none;。
当v-show 表达式true则显示;否则不显示。
注意;使用v-show;虽然不显示;但在页面的dom中是存在的;只是display属性为none
示例; 在HTML中加入如下内容
<div v-show=;show === ;yes;;>
show == yes
</div>
在data中定义show属性
var vm = new Vue({
el: ;#app;,
data: {
show: ;yes;
}
});
修改show值;观察页面显示
1.2.1.3 v-for
循环遍历
遍历数组: v-for=;item in items;, items是数组;item为数组中的数组元素遍历对象: v-for=;(value,key,index) in stu;, value属性值, key属性名;index下标<!--数组-->
<div v-for=;item in items;>
{{item.name}} -- {{item.id}}
</div>
<!--循环生成下拉列表-->
<div>
<select >
<option v-for=;item in items;
v-bind:value=;item.id;>{{item.name}}</option>
</select>
</div>
<!--对象-->
<div v-for=;(o,key) in obj;>
{{key}}-{{o}}
</div>
var vm = new Vue({
el: ;#app;,
data: {
itmes:[
{name: ;zs;,age:18},
{name: ;ww;,age:19},
{name: ;ls;,age:20},
{name: ;zl;,age:21}
],
obj: {
name:;张三;,
age: 21,
addr: ;湖南长沙;
}
}
});
1.2.1.4 v-on|v-model|v-for
创建一组多选框;可以获取到用户选择项
<!--
循环生成一组多选按钮;v-model通过vue的双向绑定将用户选择的项保存到
定义的selected组数中
-->
<div v-for=;(item,index) in items;>
{{index}}:<input type=;checkbox; v-bind:value=;item.id;
v-model=;selected;>{{item.name}}
</div>
<button v-on:click=;getSelected();>获取选择</button>
var vm = new Vue({
el: ;#app;,
data: {
type: ;C;,
show: ;no;,
items:[
{name: ;长沙;,id:18},
{name: ;昆明;,id:19},
{name: ;武汉;,id:20},
{name: ;南京;,id:21}
],
obj: {
name:;张三;,
age: 21,
addr: ;湖南长沙;
},
selected:[]
},
methods: {
getSelected: function() {
console.log(this.selected);
}
}
});
1.2.1.5 参数 v-bind:href,v-on:click
示例;
<!--参数;href-->
<div>
<a v-bind:href=;url;>baidu</a>
</div>
<!--
参数;动态参数.
attname需要在data中定义,
注意;attname要全部小写!!
-->
<div>
<a v-bind:[attrname]=;url;>baidu</a>
<button v-on:[evname]=;clickme;>点我看看</button>
</div>
注意;在动态参数中;作为参数的变量名;如;attrname;要全部小写;否则无效 ;;
var vm = new Vue({
el: ;#app;,
data: {
url: ;https://www.baidu.com;,
attrname:;href;,
evname: ;click;
},
methods: {
clickme: function() {
console.log(;点到我了;);
}
}
});
1.2.1.6 简写
Vue为v-bind和v-on这两个最常用的指令;提供了特定简写
vue允许自定义过滤器;一般用于常见的文本格式化;过滤器可用的两个地方;双花括号插值与v-bind表达式;过滤器应该被添加在js表达式的尾部;使用管道运算符;|;
局部过滤器的定义;
var vm = new Vue({
filters: {
;filterName;: function(value) {
//过滤器实现
}
}
});
过滤器的使用
<!--双花括号中的使用-->
{{ name | capitalize }}
<!--在 v-bind 指令中的使用-->
<div v-bind:id=;rawId | formatId;></div>
注1;过滤器函数接受表达式的值作为第一个参数注2;过滤器可以串联示例;
<div>
<p>{{msg | toUpperCase}}</p>
</div>
var vm = new Vue({
el: ;#app;,
data: {
msg:;hello vue;
},
//局部过滤器
filters:{
toUpperCase: function(value) {
return value.toUpperCase();
}
}
});
拷入date.js;日期格式化;放入项目js目录中;在页面中引入。
定义全局过滤器
//全局过滤器
Vue.filter(;fmtDate;,function(value) {
return fmtDate(value, ;yyyy年MM月dd日;)
});
过滤器的使用
<div>
<p>{{date | fmtDate}}</p>
</div>
计算属性用于快速计算视图;View;中显示的属性;这些计算将被缓存;并且只在需要时更新
使用场景;当一个属性需要复杂的逻辑运算之后才能获取其值;可以使用计算属性;在一个计算属性中可以完成各种复杂的逻辑;包括运算;方法调用等;只要最终返回一个结果就可以了
声明计算属性的格式;
computed:{ xxx:function(){ } }
示例; 使用计算属性;计算书本的总价
定义测试数据;和计算属性;计算属性遍历书本记录;计算总价
var vm = new Vue({ el: ;#app;, data: { //定义测试数据 books: [ {name:;红楼梦;, price:;120;}, {name:;三国演义;, price:;100;}, {name:;水浒传;, price:;90;}, ] }, //计算属性 computed: { compTotal: function() { let sum = 0; for(index in this.books) { sum ;= parseInt(this.books[index].price); } return sum; } } });
计算属性在页面中的使用
<div v-for=;book in books;> {{book.name}} -> {{book.price}} </div> <div> 总价;{{compTotal}} </div>
关于var 与 let
var声明为全局属性let为ES6新增;可以声明块级作用域的变量;局部变量;建议使用let声明变量使用场景;我们可以使用监听属性watch来响应数据的变量; 当需要在数据变化时执行异步或开销较大的操作时;这种方式比较有用。回想一下是否做过下拉列表的级联选择?
watch声明语法:
watch: { xxxx: function(val) { //监听器实现 } }
示例; 米和厘米的单位换算
设置监听器;
var vm = new Vue({ el: ;#app;, data: { m: 1, cm: 100 }, //设置监听属性 watch: { m: function(val) { if(val) this.cm = parseInt(val) * 100; else this.cm = ;;; }, cm: function(val) { if(val) this.m = parseInt(val) / 100; else this.m = ;;; } } });
HTML中使用v-model实现与数据的双向绑定
<div>
<!--注意v-model的双向绑定-->
米: <input type=;text; v-model=;m;>
厘米: <input type=;text; v-model=;cm;>
</div>
目录;
1.样式绑定2. 事件修饰符3. 按键修饰符4. 常用控件 4.1 常用控件示例4.2 修饰符5. 自定义指令 5.1 局部5.2 全局6. vue组件;重点; 6.1 组件介绍6.2 局部组件6.3 全局组件7. 自定义事件 7.1 子 -> 父7.2 父 -> 子示例;
<--定义示例样式--> <style> .fontClass { font-size: 40px; } .colorClass { color: red; } </style> <!--使用--> <p> <span v-bind:class=;fc;>fafa</span> </p> <p> <!--简写--> <span :class=;ac;>fafa</span> </p> <p> <!--直接使用style样式单--> <span style=;font-size: 40px; color:blue;;>aaa</span> <br/> <!-- 使用vue;样式名称为驼峰风格 。花括号;多个属性逗号分隔--> <span :style=;{fontSize:fontSize;;px;,color: color};>bbb</span> <br/> <span :style=;myStyle;>test</span> </p>
var vm = new Vue({ el: ;#app;, data: { fc: ;fontClass;, ac: [;fontClass;, ;colorClass;], fontSize: 40, color: ;green;, //样式对象;注意;样式名使用驼峰命名;如;fontSize myStyle: { fontSize: ;50px;, color:;red;, fontWeight: ;bold; } } });
几个常用的事件修饰符;
<!-- 提交事件不再重载页面 -->示例;
<div>接收消息;{{receverMsg}}</div> <p> <!--响应多次或一次点击事件--> <input type=;text; v-model=;sendMsg;> <button ;click=;sender;>发送(多次)</button> <button ;click.once=;sender;>发送(一次)</button> </p> <p> <!-- 阻止表单提交 --> <form action=;testAction.action; method=;post; ;submit.prevent=;doSubmit();> <label>名称</label> <input type=;text; name=;name;/> <input type=;submit; value=;提交;/> </form> </p>
var vm = new Vue({ el: ;#app;, data: { receverMsg: null, sendMsg: null }, methods: { sender: function() { this.receverMsg = this.sendMsg; }, doSubmit: function() { alert(;ok;); } } });
Vue允许为v-on在监听键盘事件时添加按键修饰符。
示例;
<!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13=;submit;> <!-- 利用下面的写法有同样的效果 --> <input v-on:keyup.enter=;submit;>
示例;响应enter键事件
<input type=;text; ;keyup.13=;doSubmit; v-model=;name;>
var vm = new Vue({ el: ;#app;, data: function() { return { name: ;hello vue; } }, methods: { doSubmit: function() { alert(;响应enter;; ; this.name); } } });
通过实现一个类型注册的页面;熟悉常用的控件。文本框/密码框/文本域/单选/多选/下拉列表
<div id=;app;> <div> <label>账号;</label> <input type=;text; v-model=;uname;> </div> <div> <label>密码;</label> <input type=;password; v-model=;upwd;> </div> <div> <label>年龄;</label> <input type=;text; v-model=;age; > </div> <div> <label>性别;</label> <input type=;radio; v-model=;sex; value=;1;>男 <input type=;radio; v-model=;sex; value=;2;>女 </div> <div> <label>爱好;</label> <div style=;display: inline;; v-for=;h in hobbies;> <input type=;checkbox; :value=;h.id; v-model=;hobby;/>{{h.name}} </div> </div> <div> <label>地区</label> <select v-model=;selectedCity;> <option value=;;>-- 请选择 --</option> <option v-for=;c in city; :value=;c.id;>{{c.name}}</option> </select> </div> <div> <label>备注;</label> <textarea v-model=;remark;></textarea> </div> <div> <input type=;checkbox; v-model=;flag;>是否已阅读并同意协议 </div> <div> <button ;click=;submit; :disabled=;disabled;>提交</button> </div> </div>
var vm = new Vue({ el: ;#app;, data: { uname: ;;, upwd:;;, age:;;, sex: 1, //用于通过v-for指令输出多选框列表 hobbies:[ {id: ;1;, name:;打游戏;}, {id: ;2;, name:;编程;}, {id: ;3;, name:;旅游;} ], /* * 用于通过v-model双向绑定,保存用户的选择。 * 此处为多选;需要通过数组接收;否则无法 * 正常接收复选框的值;且复选框的行为也不正常; * 可能出现要么全部被选择;要么全部被取消的情况 */ hobby:[], remark: null, //用于生成地区选择列表 city:[ {id:;1;, name:;长沙;}, {id:;1;, name:;株洲;}, {id:;1;, name:;湘潭;} ], //用于保存用户选择的地区 selectedCity: ;;, //是否同意协议,默认值为false agreed:false, //提交按钮是否禁用,默认为true disabled: true }, //监控agreed属性,如果同意协议则将提交按钮 //设置为可用,否则提交按钮为禁用状态 watch: { agreed: function(val) { if(val) { this.disabled = false; }else{ this.disabled = true; } } }, methods: { submit: function() { let data = { uname: this.uname, upwd: this.upwd, age:this.age, sex: this.sex, hobby: this.hobby, city: this.selectedCity, remark: this.remark } console.log(data); } } });
不使用监视器的简单方式; 删除监听器;然后将提交按钮的做如下修改
<button ;click=;submit; :disabled=;!agreed;>提交</button>
以.number为例;示例修饰符的使用;将输入的年龄属性转换为数值型
<div> <label>年龄;</label> <input type=;text; v-model.number=;age; > </div>
Vue除支持内置的v-model/v-show等指令;还允许自定义指令。 vue2中;代码的复用和抽象的主要形式是组件;但在有些情况下仍然需要对普通dom元素做底层操作;这种情况下需要自定义指令。根据自定义指令的作用范围;可分为;全局、局部两种
钩子函数;
指令钩子函数会被传入以下参数;
el;指令所绑定的元素;可以用来直接操作 DOM 。binding;一个对象;包含以下属性;通过自定义标签设置文字颜色
<div id=;app;> <!--red绑定到data里面的变量--> <p v-color=;red;>我是自定义指令</p> </div>
var vm = new Vue({ el: ;#app;, data: { red:;red; }, //自定义指令;局部 directives:{ color: { inserted: function(el,binding) { console.log(el,binding); el.style.color = binding.value; } } } });
<div id=;app;> <!--red绑定到data里面的变量--> <p v-color=;red;>我是自定义指令</p> </div>
//自定义标签,全局 Vue.directive(;color;, { inserted: function(el,binding) { console.log(el,binding); el.style.color = binding.value; } }) var vm = new Vue({ el: ;#app;, data: { red:;red; } });
组件命名规则
短横线命名;如: my-component;vue推荐使用这种方式的命名规则首字母大写命名规则;如;MyComponentprops
props是父组件用来传递数据的一个自定义属性。父组件的数据需要通过props把数据传给子组件;子组件需要显示父组件的 用props选项声明 ;prop;定义语法;new Vue({el:;#d1;,components:{组件名;{配置选项}}})
<div id=;app;> <div> <!--title是用来传值的自定义属性;在自定义组件的props中定义 --> <button-counter title=;测试;/> </div> </div>
var vm = new Vue({ el: ;#app;, data: { ts: new Date().getTime() }, //局部自定义组件 components: { //组件名: {配置项} ;button-counter;: { //用来传值的自定义属性 props:[;title;], //模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素 template: ;<button ;click=;doClick;>{{title}};局部组件;点击计数器:{{count}}</button>;, //注意;在自定义的组件中需要使用函数来定义data data: function() { return { count: 0 } }, //定义响应事件函数 methods: { doClick: function() { //注意此处this的作用返回是自定义组件,而不是上面声明 //的vue实例. this.count;;; } } } } });
注;为什么在自定义组件中必须使用函数方式来声明data?
每个自定义组件使用函数方式来声明data;这样每个实例可以维护一份被返回对象的独立的拷贝;在定义自定义组件时;一定要注意这一点。
将上面的局部组件修改为全局组件。
全局组件定义语法;Vue.component(组件名, 配置选项)
<div id=;app;> <div> <button-counter title=;测试;/> </div> </div>
//全局组件 Vue.component(;button-counter;, { //用来传值的自定义属性 props:[;title;], //模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素 template: ;<button ;click=;doClick;>{{title}}: 全局组件;点击计数器:{{count}}</button>;, //注意;在自定义的组件中需要使用函数来定义data data: function() { return { count: 0 } }, //定义响应事件函数 methods: { doClick: function() { //注意此处this的作用返回是自定义组件,而不是上面声明 //的vue实例. this.count;;; } } }); var vm = new Vue({ el: ;#app;, data: { ts: new Date().getTime() } });
Vue自定义事件是为组件间通信设计; vue中父组件通过prop传递数据给子组件;而想要将子组件的数据传递给父组件;则可以通过自定义事件的绑定
父Vue实例->子Vue实例;通过prop传递数据子Vue实例->父Vue实例;通过事件传递数据触发事件;$emit(eventName, 参数...)
注意;事件名必须用短横线命名方式。
<div id=;app;> <!--子组件到父组件--> <div> <button-counter v-on:click-test=;clickTest;/> </div> </div>
var vm = new Vue({ el: ;#app;, data: { ts: new Date().getTime() }, //对于自定义的button-counter组件, Vue实例为父组件 //在父组件中定义一个test方法,子组件调用该方法 methods: { clickTest: function(msg) { console.log(;test: ;; msg); } }, //局部自定义组件 components: { //组件名: {配置项} ;button-counter;: { //用来传值的自定义属性 props:[;title;], //模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素 template: ;<button ;click=;doClick;>{{title}};局部组件;计数:{{count}}</button>;, //注意;在自定义的组件中需要使用函数来定义data data: function() { return { count: 0 } }, //定义响应事件函数 methods: { doClick: function() { //注意此处this的作用返回是自定义组件,而不是上面声明的vue实例. //注意事件名使用短横线命名方式 this.$emit(;click-test;,;hello vue;); } } } } });
注意;props定义属性时采用的是驼峰命名法;而在html中使用时需要对应的变为短横线命名法;;
<div id=;app;> <!--子组件到父组件--> <div> <!-- 注意此处将定义props时的驼峰命名法;变为了短横线命名法 !!! --> <button-counter title-desc=;测试; /> </div> </div>
var vm = new Vue({ el: ;#app;, data: { ts: new Date().getTime() }, //对于自定义的button-counter组件, Vue实例为父组件 //在父组件中定义一个test方法,子组件调用该方法 methods: { clickTest: function(msg) { console.log(;test: ;; msg); } }, //局部自定义组件 components: { //组件名: {配置项} ;button-counter;: { //用来传值的自定义属性 //注意此处使用驼峰命名法 !!! props:[;titleDesc;], //模板,模板中写的html代码,在其中可以使用{{}},及指令等vue元素 template: ;<button ;click=;doClick;>{{titleDesc}};局部组件;计数:{{count}}</button>;, //注意;在自定义的组件中需要使用函数来定义data data: function() { return { count: 0 } }, //定义响应事件函数 methods: { doClick: function() { //注意此处this的作用返回是自定义组件,而不是上面声明的vue实例. //注意事件名使用短横线命名方式 this.count ;;; console.log(this.titleDesc); } } } } });
目录;
1 vue中文件及文件夹命名规范2. SPA 2.1 SPA简介2.2 SPA技术点3. 使用路由建立多视图单页应用 3.1 引入依赖库3.2 创建自定义组件3.3 创建路由 3.3.1 什么是路由3.3.2 定义路由3.4 创建和挂载根实例3.5 使用RouterLink和RouterView组件导航与显示4. router-link相关属性 4.1 to4.2 replace4.3 append4.4 tag4.5 active-class4.6 exact-active-class4.7 event命名法
驼峰式命名法(camelCase)
短横线命名(kebab-case)全小写
帕斯卡命名法(PascalCase)
文件夹命名
kebab-case
尽量使用名词;尽量使用一个单词
*.js文件命名规范
3.1 所有模块的主文件index.js全小写
3.2 属于组件的.js文件;使用PascalBase风格
3.3 其他类型的.js文件;使用kebab-case风格
*.vue文件命名规范
除index.vue之外;其他.vue文件统一用PascalBase风格
*.less文件命名规范
统一使用kebab-case命名风格
前三点比较重要;需要记住
附录一;.less为后缀的文件是什么
1、less是什么;LESS 为 Web 开发者带来了福音;它在 CSS 的语法基础之上;引入了变量;Mixin;混入;;
运算以及函数等功能;大大简化了 CSS 的编写;并且降低了 CSS 的维护成本;就像它的名称所说的那样;LESS 可以让我们用更少的代码做更多的事情。
2、为什么有less;CSS 是一门非程序式语言;CSS 需要书写大量看似没有逻辑的代码;不方便维护及扩展;不利于复用
3、less最最最最最最简单实例;使用;符号来定义变量
单页Web应用;single page application;SPA;;就是只有一个Web页面的应用;是加载单个HTML页面;并在用户与应用程序交互时动态更新该页面的Web应用程序
单页面应用程序;
只有第一次会加载页面, 以后的每次请求, 仅仅是获取必要的数据.然后, 由页面中js解析获取的数据, 展示在页面中
传统多页面应用程序;
对于传统的多页面应用程序来说, 每次请求服务器返回的都是一个完整的页面
优势
减少了请求体积;加快页面响应速度;降低了对服务器的压力
更好的用户体验;让用户在web app感受native app的流畅
建立一个基本html项目;创建一个demo页面并引入一下js库文件
<script src=;js/vue.js;></script><script src=;js/vue-router.min.js;></script>创建vue组件有两种方式;
var MyComonent = Vue.component(;button-counter;, {...});相关知识点;
js中const,var,let区别?分别写一个例子
创建一个Home组件和About组件
//组件名用PPascalCase风格 const Home = Vue.extend({ //必须定义一个根元素作为容器,包裹模板中的内容元素 template: ;<div><h1>Home组件</h1><div>Home组件内容区</div></div>; }); const About = Vue.extend({ //必须定义一个根元素作为容器,包裹模板中的内容元素 template: ;<div><h1>About组件</h1><div>About组件内容区</div></div>; });
vue的单页面应用是基于路由和组件的;路由用于设定访问路径;并将路径和组件映射起来。
传统的页面应用;是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中;则是路径之间的切换;实际上就是组件的切换。
路由就是SPA;单页应用;的路径管理器。再通俗的说;vue-router就是我们WebApp的链接路径管理系统。
route和router的区别
route;路线router;路由器路由器中包含了多个路线//定义路由;;/;代表根路径;路由中可以使用name属性;一遍情况不建议使用 var routes = [ {path: ;/home;,component: Home}, {path: ;/about;,component: About} ]; //创建路由器实例 const router = new VueRouter({ routes: routes });
使用路由后;Vue实例的创建于以前会有一定的区别;原来使用el属性指定边界;使用路由后需要使用Vue实例$mount方法挂载根实例
//创建和挂载根实例 var vm = new Vue({ //el: ;#app;, //将路由放入vue实例 router: router, data: { ts: new Date().getTime() } }).$mount(;#app;);
<div> <router-link to=;/home;>go to Home</router-link> <router-link to=;/about;>go to aboue</router-link> </div> <div> <router-view></router-view> </div>
<router-view></router-view>路由内容显示区域。
表示目标路由的链接
<router-link to=;/home;>Home</router-link><!-- 字符串-->
<router-link v-bind:to=;;home;;>Home</router-link><!-- 使用 v-bind 的 JS 表达式 -->
上面的示例已经使用;to既可以使用字符串;也可以使用js表达式
设置 replace 属性的话;当点击时;会调用 router.replace() 而不是 router.push();导航后不会留下 history 记录。
样例;
<router-link :to=;{ path: ;/home;}; replace></router-link>
如果配置了replace;则在点击该链接;将会导致history记录被清空;不能再执行回退。
vue中导航中的后退-前进-编程式导航
this.$router.go(-1) ;代表着后退this.$router.go(1);代表着前进切换到path为/home的路由this.$router.push({
path:;/home;
});
//或者使用path;推荐path
this.$router.push({
path:;/home;
});
示例一;编程式前进后退按键
1;在页面上加入前进和后退按钮;
<p> <button ;click=;previous;>前进</button> <button ;click=;next;>后退</button> </p>
2;添加事件处理程序
methods: { //前进 previous: function() { this.$router.go(1); }, //后退 next: function() { this.$router.go(-1); } }
vue的 $
除了数据属性;Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $;以便与用户定义的属性区分开
示例二;切换到指定路由;
添加一个“回家”按钮。
<button ;click=;gotohome;>回家</button>
gotohome: function() { console.log(;go to home;); this.$router.push({ path: ;/home; }); }
示例三;设置默认显示的组件
这个很简单;只要将需要默认显示的组件对应的路由的path设置为;/;即可
//定义路由表 var routes = [ //默认显示home {path:;/;, component:Home}, {path:;/home;, component:Home}, {path:;/about;, component:About} ];
示例四;
如果配置了replace;则在点击该链接;将会导致history记录被清空;不能再执行回退。
例如; 将
<router-link to=;/home;>Home</router-link>
加入replace属性;修改为;
<router-link to=;/home; replace>Home</router-link>
通过测试可以看到;点击home后;history记录被清空。所以一般不用。
设置 append 属性后;则在当前 (相对) 路径前添加基路径。例如;我们从 /a 导航到一个相对路径 b;如果没有配置 append;则路径为 /b;如果配了;则为 /a/b ;路径追加;
<router-link :to=;{ path: ;relative/path;}; append></router-link>
<router-link>默认渲染为<a>标签;有时候想要 <router-link> 渲染成某种标签;例如 <li>。 于是我们使用 tag prop 类指定何种标签;同样它还是会监听点击;触发导航。;如果不指定tag;默认渲染为a标签;
<router-link to=;/foo; tag=;li;>foo</router-link>
<!-- 渲染结果 -->
<li>foo</li>
设置链接激活时使用的 CSS 类名
配置当链接被精确匹配的时候应该激活的class
声明可以用来触发导航的事件。可以是一个字符串或是一个包含字符串的数组。
<router-link v-bind:to = ;{ path: ;/route1;}; event = ;Mouse+over;>Router Link 1</router-link>