网站开发常去的论坛,中国公司网站建设方案,wordpress目录迁移,如何办宽带文章目录 1. Vue简介2. Vue官网使用指南3. 初识Vue3.1 搭建Vue开发环境3.2 HelloWorld案例3.3 el与data的两种写法3.4 MVVM模型3.5 模板语法 4. 数据绑定4.1 v-bind单向数据绑定4.2 v-model双向数据绑定 5. 事件处理5.1 v-on绑定事件5.2 事件修饰符5.3 键盘事件 6. 计算属性6.1… 文章目录 1. Vue简介2. Vue官网使用指南3. 初识Vue3.1 搭建Vue开发环境3.2 HelloWorld案例3.3 el与data的两种写法3.4 MVVM模型3.5 模板语法 4. 数据绑定4.1 v-bind单向数据绑定4.2 v-model双向数据绑定 5. 事件处理5.1 v-on绑定事件5.2 事件修饰符5.3 键盘事件 6. 计算属性6.1 姓名案例6.2 computed计算属性 7. 监视属性7.1 天气案例7.2 watch监视属性 8. 绑定样式8.1 绑定class样式8.2 绑定style样式 9. 条件渲染9.1 v-show9.2 v-if、v-else与v-else-if 10. 列表渲染10.1 v-for渲染列表数据10.2 key的作用与原理10.3 列表过滤10.4 列表排序 11. 收集表单数据12. 内置指令12.1 v-text 解析普通文本12.2 v-html 解析html标签12.3 v-cloak 隐藏模板12.4 v-once 仅渲染一次12.5 v-pre 跳过元素编译 13. 自定义指令13.1 函数式和对象式13.2 局部指令和全局指令 14. Vue的生命周期14.1 生命周期概念14.2 生命周期演示 15. Vue的组件化编程15.1 模块与组件15.2 非单文件组件15.2.1 组件的基本使用15.2.2 组件的注意事项15.2.3 组件的嵌套15.2.4 VueComponent15.2.5 一个重要的内置关系 15.3 单文件组件15.3.1 单文件组件的组成15.3.2 单文件组件的示例 1. Vue简介
Vue的概念Vue是一套用于构建用户界面的渐进式JavaScript框架。 渐进式表示Vue可以自底向上逐层的应用从简单应用逐渐递进到复杂应用。 Vue的特点
采用组件化模式提高代码复用率且让代码更好维护。声明式编码让编码人员无需直接操作DOM提高开发效率。使用虚拟DOM和Diff算法尽量复用DOM节点。
学习Vue之前要掌握的js基础知识
ES6语法规范ES6模块化包管理器原型和原型链数组常用方法axiospromise
2. Vue官网使用指南
Vue官网
Vue3文档https://cn.vuejs.org/Vue2文档https://v2.cn.vuejs.org/
以Vue2文档为例对该文档顶部的导航栏做详细的介绍。 1.学习其中最重要的是教程和API贯穿vue学习的始终。
教程入门vue的教程APIvue的属性、方法和指令等风格指南官方推荐的vue代码风格指南示例官方展示的一些vue案例Cookbook展示一些vue案例教你如何优化vue代码
2.生态系统其中工具和插件很重要用于搭建Vue工程。 3.资源列表其中Awesome Vue、浏览和Vue相关的包这两个包含了官方整理的一些优秀的vue周边库。
3. 初识Vue
3.1 搭建Vue开发环境
1.首先需要下载Vue
进入Vue官网的导航列表学习 - 教程 - 安装也可点击如下地址直接跳转https://v2.cn.vuejs.org/v2/guide/installation.html
有开发和生产两种版本这里我们使用开发版本其中包含了完整的警告和调试模式适用于学习阶段。
开发环境版本安装包名称为 vue.js包含了有帮助的命令行警告体积较大。生产环境版本安装包名称为 vue.min.js优化了尺寸和速度体积较小。
2.新建一个js文件夹将下载好的vue.js放入js文件夹中然后使用 script标签引入 vue.js就可以使用Vue了
目录结构如下 index.html内容如下
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/title!-- 引入Vue --script src../js/vue.js/script/headbody/body
/html
打开页面后再打开控制台发现有两个提示 3.消除开发环境的提示
添加vue开发者工具消除第一个提示步骤如下打开Chrome扩展程序 - 打开开发者模式 -拖入vue_dev_tools.crx 文件到浏览器并松开点击添加程序即可 script标签中写入以下vue配置消除第二个提示
Vue.config.productionTip false; // 阻止vue在启动时生成生产提示3.2 HelloWorld案例
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/title!-- 引入Vue --script src../js/vue.js/script/headbody!-- 准备好一个容器 --div idapph1{{message}}/h1/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示// 创建Vue实例new Vue({// 配置el: #app, // el用于指定当前Vue实例为哪个容器服务data: { // data中用于存储数据数据供el所指定的容器去使用message: Hello World!}});/script/body
/html 代码解释 1.el表示元素element值通常为css选择器此处#app为id选择器对应div idapp此时当前vue实例挂载到了div容器上为该容器服务。 2.data表示数据数据供挂载的容器去使用而容器中使用了模板语法 {{message}}引用了vue实例中的data数据。 3.vue实例中的message属性值Hello World!替换了{{message}}因此h1{{message}}/h1最终解析成了h1Hello World!/h1 运行结果如下 注 1.想让Vue工作就必须创建一个Vue实例且要传入一个配置对象 2.容器里的代码依然符合html规范只不过混入了一些特殊的Vue语法 3.容器里的代码被称为Vue模板 4.Vue实例和容器是一一对应的 5.真实开发中只有一个Vue实例并且会配合着组件一起使用 6.{{xxx}}中的xxx要写js表达式且xxx可以自动读取到data中的所有属性 7.一旦data中的数据发生改变那么页面中用到该数据的地方也会自动更新 3.3 el与data的两种写法
1.el与data的第一种写法是对象式写法就是上述HelloWorld案例中的写法即通过配置对象属性和属性值。
// 创建Vue实例
new Vue({// 配置el: #app, // 将Vue实例挂载到 idapp的容器上data: { // data中用于存储数据数据供挂载的容器去使用message: Hello World!}
});2.el与data的第二种写法是函数式写法
// 创建Vue实例
const vm new Vue({// data的函数式写法组件中必须使用该写法data() {return {message: Hello World!};}
});vm.$mount(#app); // 等价于 el: #app注意vue实例中的函数不能使用箭头函数的写法原本函数中的this指向的是vue实例对象使用箭头函数后函数中的this指向的就是window对象。 3.4 MVVM模型
Vue采用了MVVM架构模型其对应关系如下
M模型(Model) 对应 data 中的数据V视图(View) 对应模板VM视图模型(ViewModel) 对应 Vue 实例对象 3.5 模板语法
模板语法Vue实例挂载的容器里中的代码被称为模板模板语法也就是这个容器中代码的语法规范模板语法分为两大类插值语法和指令语法。
插值语法
功能用于解析标签体内容写法{{xxx}}xxx是js表达式且可以直接读取到data中的所有属性
指令语法
功能用于解析标签包括标签属性、标签体内容、绑定事件等写法v-xxx如v-bind、v-model、v-on等
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/title!-- 引入Vue --script src../js/vue.js/script/headbodydiv idapp!-- 插值语法{{js表达式}} --h3{{message.toUpperCase()}}/h3!-- 指令语法v-xxx --a v-bind:hrefurl百度链接/a/divscriptnew Vue({el: #app,data: {message: hello world,url: https://www.baidu.com/}});/script/body
/html
运行结果
4. 数据绑定
Vue中有两种数据绑定的方式
单向绑定(v-bind)数据只能从data流向页面双向绑定(v-model)数据不仅能从data流向页面还可以从页面流向data
4.1 v-bind单向数据绑定
v-bind用于单向数据绑定该指令也可以简写为 :。
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 普通写法 --单向数据绑定input typetext v-bind:valuename / br /!-- 简写 --单向数据绑定input typetext :valuename //divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {name: hello}});/script/body
/html
验证数据能从data流向页面打开控制台输入 vm.namehello123并回车可以发现页面中的数据也显示成了hello123 验证页面的数据无法流向data在文本框中输入hello1234随后在控制台输入vm.name得到的结果依然是hello123说明vue实例中的data数据未发生改变 4.2 v-model双向数据绑定
v-model用于双向数据绑定双向绑定只能应用在表单类元素输入类元素上如input、select等 注v-model:value 可以简写为 v-model因为v-model默认收集的就是value值。 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 普通写法 --双向数据绑定input typetext v-model:valuename / br /!-- 简写 --双向数据绑定input typetext v-modelname //divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {name: hello}});/script/body
/html
验证数据能从data流向页面打开控制台输入 vm.namehello123并回车可以发现页面中的数据也显示成了hello123 验证页面的数据也能流向data在文本框中输入hello1234随后在控制台输入vm.name得到的结果是hello1234说明vue实例中的data数据随页面数据的改变而改变 5. 事件处理
5.1 v-on绑定事件
事件的基本使用
使用v-on:xxxyyy 指令用于绑定事件其中v-on:可以简写为xxx是事件名yyy是回调函数名也可以是简单的语句如isShow!isShowmethods对象用于配置vm的方法事件的回调函数需要配置在methods对象中methods中配置的函数this指向的是vm或组件实例对象且配置的函数不能使用箭头函数否则this指向的是window对象clickdemo 和 clickdemo($event) 效果一致但后者可以传参
1.绑定事件且回调函数不传参
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 普通写法 --button v-on:clickshowInfo按钮1/button!-- 简写 --button clickshowInfo按钮2/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,// 配置方法methods: {// 事件回调函数showInfo() {alert(Hello World!);}}});/script/body
/html
2.绑定事件且给回调函数传参
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idappbutton clickshowInfo按钮1/button!-- $event为占位符表示此时第一个参数为事件对象 --button clickshowInfo1($event,Jack)按钮2/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,// 配置方法methods: {// 不传参时函数的第一个参数代表事件对象showInfo(e) {console.log(e.target); // 触发事件的对象console.log(e.type); // 事件的类型console.log(this); // this指向vm},// 传参时根据$event占位符的位置确定哪个参数代表事件对象showInfo1(e, name) {console.log(e.target);console.log(e.type);console.log(Hello ${name});}}});/script/body
/html
运行结果 5.2 事件修饰符
Vue中的事件修饰符
prevent阻止默认事件常用stop阻止事件冒泡常用once事件只触发一次常用capture使用事件的捕获模式self只有event.target是当前操作的元素时才触发事件passive事件的默认行为立即执行无需等待事件回调执行完毕 注修饰符可以连续写如click.prevent.stopshowInfo 1.prevent阻止事件的默认行为常用 同js事件对象中的e.preventDefault()方法用于阻止事件的默认行为 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 阻止链接跳转 --a hrefhttps://www.baidu.com/ click.preventshowInfo百度链接/a!-- 阻止表单提交 --form actionhttps://www.baidu.com/input typesubmit value提交 click.preventshowInfo //form/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo() {console.log(已阻止事件的默认行为);}}});/script/body
/html
运行结果点击百度链接和表单提交按钮都不发生页面跳转因为跳转的默认行为被阻止了
2.stop阻止事件冒泡常用 同js事件对象中的e.stopPropagation()方法用于阻止事件冒泡 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.father {position: relative;width: 200px;height: 200px;background-color: #666;margin: 30px;}.son {position: absolute;width: 100px;height: 100px;background-color: orange;margin: auto;top: 0;left: 0;right: 0;bottom: 0;}/style/headbodydiv idapp classfather clickshowInfo1!-- 阻止事件冒泡 --div classson click.stopshowInfo2/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo1() {alert(father);},showInfo2() {alert(son);}}});/script/body
/html
运行结果点击子元素 只弹出警示框“son”没有后续弹出“father” (释义点击子元素son以后阻止冒泡因此没有冒泡到父元素父元素的事件行为不执行) 3.once事件只触发一次常用
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 此按钮只在第一次点击时触发事件 --button click.onceshowInfo点击按钮/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo() {alert(Hello World!);}}});/script/body
/html
运行结果第一次点击按钮时弹出警示框后续再点击无法弹出
4.capture使用事件的捕获模式 注js中addEventListener(type, listener, useCapture)useCapture 为false或者忽略时事件处于冒泡阶段为true时事件处于捕获阶段 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.father {position: relative;width: 200px;height: 200px;background-color: #666;margin: 30px;}.son {position: absolute;width: 100px;height: 100px;background-color: orange;margin: auto;top: 0;left: 0;right: 0;bottom: 0;}/style/headbody!-- 绑定事件到父元素father为捕获阶段 --div idapp classfather click.captureshowInfo1div classson clickshowInfo2/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo1() {alert(father);},showInfo2() {alert(son);}}});/script/body
/html
运行结果点击橘色的子元素div先弹出警示框 “father”后弹出警示框 “son” (释义捕获从上往下传递点击子元素son以后会先找到父元素并执行它的事件再往下找到子元素后执行子元素的事件) 5.self只有event.target是当前操作的元素时才触发事件 注通过这种方式也能阻止事件冒泡 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.father {position: relative;width: 200px;height: 200px;background-color: #666;margin: 30px;}.son {position: absolute;width: 100px;height: 100px;background-color: orange;margin: auto;top: 0;left: 0;right: 0;bottom: 0;}/style/headbody!-- 只有当e.target是当前操作的元素时才触发事件即只有点击该父元素才触发父元素的事件 --div idapp classfather click.selfshowInfo1!-- div idapp classfather clickshowInfo1 --div classson clickshowInfo2/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo1() {alert(father);},showInfo2() {alert(son);}}});/script/body
/html
运行结果只有点击灰色的父元素div时才弹出警示框 “father” 5.3 键盘事件
Vue中常用的按键别名
回车 enter删除 delete (捕获“删除”和“退格”键)退出 esc空格 space换行 tab (特殊必须配合keydown去使用)上 up下 down左 left右 right 注 1.Vue未提供别名的按键可以使用按键原始的key值去绑定但注意要转为kebab-case短横线命名如caps-lock 2.可以使用keyCode去指定具体的按键不推荐如e.keyCode13代表回车键 3.Vue.config.keyCodes.自定义键名 键码可以去定制按键别名如Vue.config.keyCodes.huiche13此时别名huiche代表回车键 4.系统修饰键用法特殊ctrl、alt、shift、meta 配合keyup使用按下修饰键的同时再按下其他键随后释放其他键事件才被触发。配合keydown使用正常触发事件。 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 按下回车键松开时触发事件 --input typetext placeholder输入完成后请按回车 keyup.entershowInfo //divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,methods: {showInfo(e) {alert(e.target.value);}}});/script/body
/html
运行结果输入“123456”再按下回车后松开 6. 计算属性
6.1 姓名案例
要求一个input框输入“姓”另一个input框输入“名”生成“姓-名”
解题方法有三种
使用插值语法{{}}实现使用methods方法实现使用computed计算属性实现推荐
1.使用插值语法{{}}实现姓名案例通过直接在模板里进行字符串拼接
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp姓input typetext v-modelfirstName / br /名input typetext v-modellastName / br /全名span{{firstName}}-{{lastName}}/span/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {firstName: 张,lastName: 三}});/script/body
/html
运行结果如下在两个输入框中分别输入“姓”和“名”得到全名为“姓-名” 2.使用methods方法实现姓名案例通过调用方法将方法的返回值渲染到模板中
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp姓input typetext v-modelfirstName / br /名input typetext v-modellastName / br /全名span{{fullName()}}/span/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {firstName: 张,lastName: 三},methods: {fullName() {return this.firstName - this.lastName;}}});/script/body
/html
3.使用computed计算属性实现通过计算原有的属性得到新的属性并将其渲染到模板中
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp姓input typetext v-modelfirstName / br /名input typetext v-modellastName / br /全名span{{fullName}}/span/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {firstName: 张,lastName: 三},computed: {fullName: {get() {return this.firstName - this.lastName;}}}});/script/body
/html
6.2 computed计算属性
计算属性
定义要用的属性不存在要通过已有属性计算得来计算属性最终会出现在vm上直接读取使用即可原理底层借助了Objcet.defineproperty方法提供的getter和setter优势与methods实现相比内部有缓存机制复用效率更高调试方便计算属性中的get和set函数 使用计算属性时初次读取会执行一次get函数当依赖的数据发生改变时也会再次调用get函数修改计算属性时会调用set函数 当计算属性中只有get函数时可以简写计算属性
1.计算属性中的get和set函数的使用
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp姓input typetext v-modelfirstName / br /名input typetext v-modellastName / br /全名span{{fullName}}/span/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {firstName: 张,lastName: 三},computed: {fullName: {// 使用fullName时返回全名get() {console.log(get被调用了);return this.firstName - this.lastName;},// 修改fullName时修改firstName和lastName属性set(value) {console.log(set被调用了);arr value.split(-);this.firstName arr[0];this.lastName arr[1];}}}});/script/body
/html
运行结果 由于模板中使用了fullName属性先调用了一次get然后在输入修改名后fullName依赖的lastName属性发生了改变再次调用了get 控制台中输入vm.fullName张-三丰fullName属性被修改调用了set又因为set函数修改了fullName所依赖的firstName 和lastName所以再次触发调用了get 2.简写计算属性
当计算属性中只有get函数时代码可以进行如下简写
// 普通写法
computed: {fullName: {get() {return this.firstName - this.lastName;}}
}// 简写
computed: {fullName() {return this.firstName - this.lastName;}
}7. 监视属性
7.1 天气案例
要求点击按钮时天气在炎热和凉爽之间切换初始值默认为炎热。
实现如下
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph1今天天气很{{info}}/h1button clickchangeWeather点击切换天气/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {isHot: true // 默认天气为炎热},computed: {info() {return this.isHot ? 炎热 : 凉爽;}},methods: {changeWeather() {this.isHot !this.isHot; // 每次调用方法时isHot取反}}});/script/body
/html 注由于methods中的changeWeather方法逻辑简单因此也可以将methods去掉并把clickchangeWeather改为clickisHot !isHot这样就简化了代码。 运行结果点击按钮天气在炎热和凉爽之间切换 7.2 watch监视属性
监视属性watch
监视的属性必须存在才能进行监视当被监视的属性变化时, handler回调函数自动调用监视属性有两种写法一是通过watch属性配置二是通过vm.$watch()方法深度监视属性 当被监视的属性有多层结构时默认不监测对象内部值的改变一层通过配置deep:true可以监测对象内部值改变多层 当监视属性中只有handler函数时可以监视计算属性
1.监视属性的基本用法通过watch属性配置
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph1今天天气很{{info}}/h1button clickisHot !isHot点击切换天气/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {isHot: true // 默认天气为炎热},computed: {info() {return this.isHot ? 炎热 : 凉爽;}},methods: {changeWeather() {this.isHot !this.isHot; // 每次调用方法时isHot取反}},watch: {// 当isHot属性发生变化时会调用handler函数isHot: {immediate: true, //初始化时会调用一下handler函数handler(newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});}}}});/script/body
/html
点击按钮运行结果如下 2.可以通过vm.$watch()方法进行属性监视
// watch属性配置的写法
watch: {isHot: {immediate: true, handler(newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});}}
}// vm.$watch()的写法
vm.$watch(isHot, {immediate: true, handler(newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});}
});3.deep:true 用于深度监视属性
深度监视单个属性监视的属性写为numbers.a表示监视numbers属性中的a属性深度监视所有属性 监视的属性写为numbers再配置deep:true表示监视numbers属性中的所有属性
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph3a的值是:{{numbers.a}}/h3button clicknumbers.a点我让a1/buttonh3b的值是:{{numbers.b}}/h3button clicknumbers.b点我让b1/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {// numbers属性有多层结构numbers: {a: 1,b: 1,c: {d: {e: 100}}}},watch: {//监视多级结构中某个属性的变化numbers.a: {handler() {console.log(a发生了改变);}},//监视多级结构中所有属性的变化numbers: {deep: true,handler() {console.log(numbers发生了改变);}}}});/script/body
/html
分别点击上下两个按钮使a、b值增加运行结果如下 4.简写监视属性
当监视属性中只有handler函数时代码可以进行如下简写
// 普通写法
watch: {isHot: {handler(newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});}}
}// watch属性配置简写
watch: {isHot(newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});}
}// vm.$watch()方法简写
vm.$watch(isHot, function (newValue, oldValue) {console.log(isHot被修改原来的值是${oldValue}现在是${newValue});
});5.计算属性与监视属性的区别
computed和watch之间的区别
computed能完成的功能watch都可以完成watch能完成的功能computed不一定能完成例如watch可以进行异步操作computed的写法更加的简洁因此能用 computed完成的功能不要用watch完成 注Vue中有关函数的两个重要的小原则 1.所有被Vue管理的函数最好写成普通函数这样this的指向才是vm 或 组件实例对象 2.所有不被Vue所管理的函数定时器的回调函数、ajax的回调函数等、Promise的回调函数最好写成箭头函数这样this的指向才是vm 或 组件实例对象。 8. 绑定样式
8.1 绑定class样式
绑定class样式有三种方式分别适用于不同的场景写法为:classxxx
字符串写法适用于样式的类名不确定需要动态指定对象写法适用于要绑定的样式个数确定、名字也确定但要动态决定用不用数组写法适用于要绑定的样式个数不确定、名字也不确定
1.绑定class样式字符串写法适用于样式的类名不确定需要动态指定
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle/* basic为固定样式happy和sad为需要动态绑定的样式 */.basic {width: 200px;height: 100px;border: 1px solid black;}/* 快乐情绪 */.happy {border: 4px solid red;background-color: orangered;background: linear-gradient(30deg, yellow, pink, orange, yellow);}/* 悲伤情绪 */.sad {border: 4px dashed rgb(2, 197, 2);background-color: gray;}/style/headbodydiv idapp!-- 字符串写法适用于样式的类名不确定需要动态指定 --div classbasic :classmood/divbr /button clickchangeMood点击切换情绪/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {mood: happy // 属性值为字符串},methods: {// 改变情绪changeMood() {if (this.mood happy) {this.mood sad;} else {this.mood happy;}}}});/script/body
/html
运行结果点击按钮盒子样式发生改变盒子的样式是动态的 2.绑定class样式对象写法适用于要绑定的样式个数确定、名字也确定但要动态决定用不用
动态切换单个 class样式
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.basic {width: 200px;height: 100px;border: 1px solid black;}.a1 {background-color: yellowgreen;}/style/headbodydiv idapp!-- 对象写法适用于要绑定的样式个数确定、名字也确定但要动态决定用不用 --div classbasic :class{a1:isActive}归海一刀/divbutton clickisActive!isActive添加/删除样式/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {isActive: true}});/script/body
/html
运行结果点击按钮选择添加或者删除样式. 动态切换多个 class样式
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.basic {width: 200px;height: 100px;border: 1px solid black;}.a1 {background-color: yellowgreen;}.a2 {font-size: 30px;text-shadow: 2px 2px 10px red;}.a3 {border-radius: 20px;}/style/headbodydiv idapp!-- 对象写法适用于要绑定的样式个数确定、名字也确定但要动态决定用不用 --div classbasic :classclassObj归海一刀/divbutton clickclassObj.a1!classObj.a1添加/删除样式a1/buttonbutton clickclassObj.a2!classObj.a2添加/删除样式a2/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {classObj: {a1: false,a2: false}}});/script/body
/html
运行结果点击按钮选择添加或者删除样式 3.绑定class样式数组写法适用于要绑定的样式个数不确定、名字也不确定
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.basic {width: 200px;height: 100px;border: 1px solid black;}.a1 {background-color: yellowgreen;}.a2 {font-size: 30px;text-shadow: 2px 2px 10px red;}.a3 {border-radius: 20px;}/style/headbodydiv idapp!-- 数组写法适用于要绑定的样式个数不确定、名字也不确定 --div classbasic :classclassArr归海一刀/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {classArr: [a1, a2] // 属性值为数组}});/script/body
/html
运行结果可以通过对数组进行操作从而对样式进行添加和删除 8.2 绑定style样式
绑定style样式有两种方式
对象写法:style{fontSize: xxx}其中xxx是动态值数组写法:style[a,b]其中a、b是样式对象
1.绑定style样式对象写法 注在style样式绑定中CSS中的样式名要改为小驼峰写法如font-size 要改为 fontSize !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.basic {width: 200px;height: 100px;border: 1px solid black;margin-bottom: 20px;}/style/headbodydiv idapp!-- 绑定style样式对象写法 --div classbasic :style{fontSize: ${fsize}px}归海一刀/divdiv classbasic :stylestyleObj归海一刀/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {fsize: 30,styleObj: {// 小驼峰写法fontSize: 30px,color: red,backgroundColor: orange}}});/script/body
/html
运行结果 2.绑定style样式数组写法
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle.basic {width: 200px;height: 100px;border: 1px solid black;margin-bottom: 20px;}/style/headbodydiv idapp!-- 绑定style样式数组写法 --div classbasic :stylestyleArr归海一刀/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {styleArr: [{fontSize: 30px,color: red},{backgroundColor: orange}]}});/script/body
/html
运行结果 9. 条件渲染
9.1 v-show
v-show
写法v-show表达式适用于切换频率较高的场景特点不展示的DOM元素未被移除仅仅是使用样式隐藏掉设置为display:none
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph1 v-showisActiveHello World/h1button clickisActive!isActive显示/隐藏元素/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {isActive: true}});/script/body
/html
运行结果点击按钮之后元素被隐藏再查看DOM结构发现元素样式上多了个styledisplay: none; 9.2 v-if、v-else与v-else-if
v-if
写法v-if表达式、v-else表达式、v-else-if表达式适用于切换频率较低的场景特点不展示的DOM元素直接被移除
1.使用v-if会把DOM元素直接被移除
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph1 v-ifisActiveHello World/h1button clickisActive!isActive显示/隐藏元素/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {isActive: true}});/script/body
/html
运行结果点击按钮之后元素被隐藏再查看DOM结构发现元素直接被移除了 2.v-if、v-else与v-else-if配合使用
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph2当前n的值是{{n}}/h2button clickn点击n1/buttonh3 v-ifn1Angular/h3h3 v-else-ifn2React/h3h3 v-else-ifn3Vue/h3h3 v-else不是前端三大框架/h3/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {n: 0}});/script/body
/html
运行结果点击按钮增加n的值当n达到对应值时分别展示对应的元素 注v-if可以和v-else-if、v-else一起使用但要求结构不能被“打断” 打断的结构示例如下
h3 v-ifn1Angular/h3
h3 v-else-ifn2React/h3
h3打断结构/h3
h3 v-else-ifn3Vue/h3
h3 v-else不是前端三大框架/h33.v-if与template的配合使用当几个v-if的条件一样时可以配合template将多个条件简写为一个 注使用template标签不会影响结构而且只能和v-if配合使用不能和v-show配合 !-- 简写前 --
h3 v-ifn1Angular/h3
h3 v-ifn1React/h3
h3 v-ifn1Vue/h3!-- 简写后 --
template v-ifn1h3Angular/h3h3React/h3h3Vue/h3
/template10. 列表渲染
10.1 v-for渲染列表数据
v-for指令用于展示列表数据
语法v-for(item, index) in xxx :keyyyy
xxx为可遍历对象包括数组、对象、字符串等item为可遍历对象的每一项数据index为每一项数据的索引值key属性为每项数据的唯一标识
1.使用v-for遍历数组常用
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 遍历数组 --ul!-- p为数组成员index为数组下标 --li v-for(p,index) in persons :keyindex{{index}}{{p.name}}-{{p.age}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {// id为每项数据的唯一标识persons: [{ id: 001, name: 张三, age: 18 },{ id: 002, name: 李四, age: 19 },{ id: 003, name: 王五, age: 20 }]}});/script/body
/html 注由于数组下标index和id都是唯一标识而key只要作为唯一标识就可以因此以上代码中的:keyindex也可以改为:keyp.id 运行结果 2.使用v-for遍历对象常用
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 遍历对象 --ul!-- v为对象的属性值valuek为对象的属性名key --li v-for(v,k) in car :keyk{{k}}-{{v}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {// 对象是一个键值对属性名就是键key可以作为唯一标识car: {name: 奥迪A6L,price: 70万,color: 黑色}}});/script/body
/html
运行结果 3.使用v-for遍历字符串用的少
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 遍历字符串 --ul!-- item为每个字符index为字符串下标 --li v-for(item,index) in str :keyindex{{index}}-{{item}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {str: Hello}});/script/body
/html
运行结果 4.使用v-for遍历指定的次数用的少
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 遍历指定的次数 --ul!-- 遍历5次 --li v-for(number,index) in 5 :keyindex{{number}}-{{str}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {str: Hello World}});/script/body
/html
运行结果 10.2 key的作用与原理
1.key作为数据的唯一标志选择原则遵循如下
最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。如果不存在对数据的逆序添加、逆序删除等破坏顺序操作仅用于渲染列表用于展示使用index作为key是没有问题的。
2.用index作为key可能会引发的问题
若对数据进行逆序添加、逆序删除等破坏顺序操作会产生没有必要的真实DOM更新 界面效果没问题, 但效率低。如果结构中还包含输入类的DOM会产生错误DOM更新 界面有问题。
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 遍历数组 --button click.onceadd添加一个老刘/buttonul!-- p为数组成员index为数组下标 --li v-for(p,index) in persons :keyindex{{p.name}}-{{p.age}} input typetext //li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {// id为每项数据的唯一标识persons: [{ id: 001, name: 张三, age: 18 },{ id: 002, name: 李四, age: 19 },{ id: 003, name: 王五, age: 20 }]},methods: {// 对数据进行逆序添加破坏原有顺序add() {const p { id: 004, name: 老刘, age: 40 };this.persons.unshift(p);}}});/script/body
/html
运行结果如下在输入框中输入内容然后再点击按钮发现输入框中的数据显示有问题 当把以上代码的:keyindex改为:keyp.id数据则显示正常了 原理如下
虚拟DOM中key的作用key是虚拟DOM对象的标识当数据发生变化时Vue会根据【新数据】生成【新的虚拟DOM】随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较比较规则如下 旧虚拟DOM中找到了与新虚拟DOM相同的key若虚拟DOM中内容没变, 直接使用之前的真实DOM若虚拟DOM中内容变了, 则生成新的真实DOM随后替换掉页面中之前的真实DOM。旧虚拟DOM中未找到与新虚拟DOM相同的key创建新的真实DOM随后渲染到到页面 10.3 列表过滤
列表过滤对列表的数据进行筛选筛选后的数据再渲染到页面中。
1.使用监视属性实现列表过滤
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp人员列表input typetext placeholder请输入名字 v-modelkeyWord /ul!-- 展示过滤后的数组 --li v-for(p,index) of filPerons :keyindex{{p.name}}-{{p.age}}-{{p.sex}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {keyWord: , // 关键词用于模糊搜索persons: [{ id: 001, name: 马冬梅, age: 19, sex: 女 },{ id: 002, name: 周冬雨, age: 20, sex: 女 },{ id: 003, name: 周杰伦, age: 21, sex: 男 },{ id: 004, name: 温兆伦, age: 22, sex: 男 }],filPerons: [] // 用于存放过滤后的数组避免改动原数组},watch: {// 监视keyWord属性当keyWord属性值发生变化时调用handler函数进行模糊搜索keyWord: {immediate: true, // 初始化时调用handler空字符串会匹配所有数据首次展示为完整数据handler(val) {this.filPerons this.persons.filter(p {return p.name.includes(val); // 判断输入框中的值是否出现在姓名中});}}}});/script/body
/html
运行结果 2.使用计算属性实现列表过滤
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp人员列表input typetext placeholder请输入名字 v-modelkeyWord /ul!-- 展示过滤后的数组 --li v-for(p,index) of filPerons :keyindex{{p.name}}-{{p.age}}-{{p.sex}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {keyWord: , // 关键词用于模糊搜索persons: [{ id: 001, name: 马冬梅, age: 19, sex: 女 },{ id: 002, name: 周冬雨, age: 20, sex: 女 },{ id: 003, name: 周杰伦, age: 21, sex: 男 },{ id: 004, name: 温兆伦, age: 22, sex: 男 }]},computed: {// 计算属性filPerons依赖于keyWord属性当keyWord发生改变时会重新计算属性filPerons() {return this.persons.filter(p {return p.name.includes(this.keyWord);});}}});/script/body
/html 注使用computed还是watch的原则 1.computed 的写法更加的简洁推荐使用能用 computed 完成的功能不要用 watch 完成 2.computed 无法完成的功能才用 watch 实现例如watch 可以进行异步操作 10.4 列表排序
列表排序对列表数据进行排序排序后的数据再渲染到页面中
可以对完整的列表数据进行排序也可以配合列表过滤对筛选后的列表数据进行排序。
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp人员列表input typetext placeholder请输入名字 v-modelkeyWord /button clicksortType 2年龄升序/buttonbutton clicksortType 1年龄降序/buttonbutton clicksortType 0原顺序/buttonul!-- 展示过滤后的数组 --li v-for(p,index) of filPerons :keyindex{{p.name}}-{{p.age}}-{{p.sex}}/li/ul/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {keyWord: ,sortType: 0, // 0原顺序、1降序、2升序persons: [{ id: 001, name: 马冬梅, age: 30, sex: 女 },{ id: 002, name: 周冬雨, age: 31, sex: 女 },{ id: 003, name: 周杰伦, age: 18, sex: 男 },{ id: 004, name: 温兆伦, age: 19, sex: 男 }]},computed: {// 计算属性filPerons依赖于keyWord和sortType属性依赖的这两个属性任何一个发生变化都会引起重新计算属性filPerons() {// 对列表数据进行筛选const arr this.persons.filter(p {return p.name.includes(this.keyWord);});// 判断一下是否需要排序if (this.sortType) {arr.sort((p1, p2) {return this.sortType 1 ? p2.age - p1.age : p1.age - p2.age;});}return arr;}}});/script/body
/html
运行结果在输入框中输入关键词可以对数据进行筛选再点击按钮可以对筛选后的数据再进行排序 11. 收集表单数据
v-model用于收集表单数据且在收集表单数据时根据表单控件类型的不同默认收集的值也不同。
v-model需要注意的点如下
若表单控件为文本框或密码框即 input typetext/或 input typepassword/则v-model收集的是value值用户输入的就是value值。若表单控件为单选框即input typeradio/则v-model收集的是value值需要给标签配置value值。若表单控件为复选框即input typecheckbox/则有以下两种情况 没有配置input的value属性那么收集的就是checked勾选 or 未勾选是布尔值配置了input的value属性当v-model的初始值是非数组时那么收集的就是checked是数组时那么收集的的就是value组成的数组 注v-model的三个修饰符 1.lazy失去焦点时再收集数据 2.number输入字符串转为有效的数字 3.trim清除文本框首尾空格 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 阻止表单默认跳转行为 --form submit.preventdemo账号input typetext v-model.trimuserInfo.account / br /br /密码input typepassword v-modeluserInfo.password / br /br /年龄input typenumber v-model.numberuserInfo.age / br /br /性别 男input typeradio namesex v-modeluserInfo.sex valuemale / 女input typeradio namesex v-modeluserInfo.sex valuefemale / br /br /爱好 学习input typecheckbox v-modeluserInfo.hobby valuestudy / 打游戏input typecheckbox v-modeluserInfo.hobby valuegame / 吃饭inputtypecheckboxv-modeluserInfo.hobbyvalueeat/br /br /所属校区select v-modeluserInfo.cityoption value请选择校区/optionoption valuebeijing北京/optionoption valueshanghai上海/optionoption valueshenzhen深圳/optionoption valuewuhan武汉/option/selectbr /br /其他信息textarea v-model.lazyuserInfo.other/textarea br /br /input typecheckbox v-modeluserInfo.agree /阅读并接受a hrefhttp://www.baidu.com《用户协议》/abutton提交/button/form/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {userInfo: {account: ,password: ,age: 18,sex: female,hobby: [],city: beijing,other: ,agree: }},methods: {demo() {console.log(JSON.stringify(this.userInfo));}}});/script/body
/html
运行结果如下输入内容勾选单选和复选框等控件再点击提交按钮可以看到控制台打印了表单提交的信息。 12. 内置指令
目前已经学过的内置指令有v-bind、v-model、v-on、v-show、v-if、v-else、v-for。
12.1 v-text 解析普通文本
v-text指令用于解析普通文本向其所在的节点中渲染文本内容。
v-text与插值语法的区别v-text会替换掉节点中的内容而{{xxx}}则不会因此{{xxx}}更加灵活用的更多。
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 插值语法相对v-text更加灵活 --divHello, {{name}}/div!-- v-text会替换掉节点中的内容 --div v-textnameHello/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {name: Jack}});/script/body
/html
运行结果 12.2 v-html 解析html标签
v-html指令用于解析html标签向其所在的节点中渲染包含html结构的内容。
v-html与插值语法的区别v-html会替换掉节点中的内容而{{xxx}}则不会。 注v-html有安全性问题 1.在网站上动态渲染任意HTML是非常危险的容易导致XSS攻击 2.一定要在可信的内容上使用v-html永不要用在用户提交的内容上如表单的输入框等 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- v-text只能解析普通文本无法解析html标签 --div v-textstr/div!-- v-html可以解析html标签 --div v-htmlstr/div/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {str: h3Hello World/h3}});/script/body
/html
运行结果 12.3 v-cloak 隐藏模板
v-cloak指令
本质是一个特殊属性Vue实例创建完毕并接管容器后会删掉v-cloak属性该指令可以配合css属性选择器解决网速慢时页面展示出{{xxx}}的问题
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/scriptstyle/* 使用该属性的元素被隐藏 */[v-cloak] {display: none;}/style/headbodydiv idapp!-- 初始时v-cloak属性存在但由于属性选择器的作用会将h2标签隐藏等到vue接管容器后会移除掉h2上的v-cloak属性此时会显示h2标签--h2 v-cloak{{name}}/h2/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {name: Jack}});/script/body
/html
12.4 v-once 仅渲染一次
v-once指令
v-once所在节点在初次动态渲染后就视为静态内容以后数据的改变不会引起v-once所在结构的更新可以用于优化性能
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph2 v-once初始化的n值是:{{n}}/h2h2当前的n值是:{{n}}/h2button clickn点我n1/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {n: 1}});/script/body
/html
运行结果点击按钮只有下面的n值发生变化而上面的n值不变化 12.5 v-pre 跳过元素编译
v-pre指令
跳过其所在节点的编译过程可利用它跳过没有使用指令语法、没有使用插值语法的节点会加快编译
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapp!-- 该标签未用到指令语法和插值语法可以使用v-pre加快编译 --h2 v-preVue其实很简单/h2h2当前的n值是:{{n}}/h2button clickn点我n1/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示const vm new Vue({el: #app,data: {n: 1}});/script/body
/html
13. 自定义指令
13.1 函数式和对象式
自定义指令有两种定义方式
函数式定义对象式定义
1.函数式定义
例定义一个 v-big 指令和 v-text 功能类似但会把绑定的数值放大10倍
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph2当前的n值是span v-textn/span/h2h2放大10倍后的n值是span v-bign/span/h2button clickn点我n1/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示new Vue({el: #app,data: {n: 1,},// 自定义指令directives: {// element表示真实的dom元素, binding表示绑定的对象big(element, binding) {element.innerText binding.value * 10;},},});/script/body
/html big函数被调用的条件 1.指令与元素成功绑定时一上来 2.指令所在的模板被重新解析时 运行结果点击按钮上面的n值1下面的n值1后乘以10倍 2.对象式定义
配置对象中常用的三个回调
bind指令与元素成功绑定时调用inserted指令所在元素被插入页面时调用update指令所在模板结构被重新解析时调用 对象式定义与函数式定义的区别函数式定义写法等于对象式定义中的 bind update 回调函数而对象式定义还有inserted回调函数可以实现函数式定义无法实现的细节操控。 例定义一个 v-fbind 指令和 v-bind 功能类似但可以让其所绑定的input元素默认获取焦点
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idapph2当前的n值是span v-textn/span/h2button clickn点我n1/buttonbr /input typetext v-fbind:valuen //divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示new Vue({el: #app,data: {n: 1,},// 自定义指令directives: {fbind: {//指令与元素成功绑定时一上来bind(element, binding) {element.value binding.value;},//指令所在元素被插入页面时inserted(element, binding) {element.focus();},//指令所在的模板被重新解析时update(element, binding) {element.value binding.value;},},},});/script/body
/html
运行结果刷新页面后文本框默认获取焦点点击按钮后失去焦点 13.2 局部指令和全局指令
自定义指令分为两类
局部指令全局指令
1.局部指令写法
// 函数式定义new Vue({ directives:{指令名:回调函数} }) // 对象式定义 new Vue({ directives:{指令名:配置对象} }) new Vue({// 局部自定义指令directives: {// 函数式定义big(element, binding) {element.innerText binding.value * 10;},// 对象式定义fbind: {bind(element, binding) {element.value binding.value;},inserted(element, binding) {element.focus();},update(element, binding) {element.value binding.value;},},},
});2.全局指令写法
// 函数式定义
Vue.directive(指令名, 回调函数)
// 对象式定义
Vue.directive(指令名, 配置对象)// 函数式定义Vue.directive(big, function (element, binding) {element.value binding.value;});// 对象式定义Vue.directive(fbind, {bind(element, binding) {element.value binding.value;},inserted(element, binding) {element.focus();},update(element, binding) {element.value binding.value;},});自定义指令注意事项 1.指令定义时不加v-但使用时要加v- 2.指令名如果是多个单词要使用kebab-case命名方式不要用camelCase命名。 new Vue({directives: {big-number(element, binding) {element.innerText binding.value * 10;},},
});14. Vue的生命周期
14.1 生命周期概念
Vue的生命周期又称生命周期回调函数、生命周期函数、生命周期钩子是Vue在关键时刻帮我们调用的一些特殊名称的函数。 生命周期函数中的this指向是vm 或 组件实例对象 vue的生命周期分为以下四个流程每个流程对应两个函数其中最重要的是mounted和 beforeDestroy。
创建流程 beforeCreate此时无法通过vm访问到data中的数据和methods中的方法。created此时可以通过vm访问到data中的数据和methods中配置的方法。 挂载流程 beforeMount此时页面呈现的是未经Vue编译的DOM结构所有对DOM的操作最终都不奏效。mounted此时页面呈现的是经过Vue编译的DOM对DOM的操作均有效尽可能避免。至此初始化过程结束一般在此阶段开启定时器、发送网络请求、订阅消息以及绑定自定义事件等初始化操作。 更新流程 beforeUpdate此时数据是新的但页面是旧的即页面尚未和数据保持同步。updated此时数据是新的页面也是新的即页面尚未和数据保持同步。 销毁流程 beforeDestroy此时vm中所有的data、methods和指令等等都处于可用状态马上要执行销毁过程。一般在此阶段关闭定时器、取消订阅消息以及解绑自定义事件等收尾操作。destroyed此时vm已完成销毁。
Vue的生命周期流程图
14.2 生命周期演示
1.生命周期钩子函数的调用顺序
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbody!-- 准备好一个容器--div idapph2当前的n值是{{n}}/h2button clickadd点我n1/buttonbutton clickbye点我销毁vm/button/divscriptVue.config.productionTip false; // 阻止vue在启动时生成生产提示new Vue({el: #app,data: {n: 1,},methods: {add() {this.n;},bye() {this.$destroy();},},beforeCreate() {console.log(beforeCreate);},created() {console.log(created);},beforeMount() {console.log(beforeMount);},mounted() {console.log(mounted);},beforeUpdate() {console.log(beforeUpdate);},updated() {console.log(updated);},beforeDestroy() {console.log(beforeDestroy);},destroyed() {console.log(destroyed);},});/script/body
/html 2.生命周期的常用应用场景
常用的生命周期钩子
mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等收尾操作
关于销毁Vue实例
销毁后借助Vue开发者工具看不到任何信息销毁后自定义事件会失效但原生DOM事件依然有效一般不会在beforeDestroy操作数据因为即便操作数据也不会再触发更新流程了
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbody!-- 准备好一个容器--div idapph2 :style{opacity}欢迎学习Vue/h2button clickopacity 1透明度设置为1/buttonbutton clickstop点我停止变换/button/divscriptVue.config.productionTip false; //阻止 vue 在启动时生成生产提示。new Vue({el: #app,data: {opacity: 1,},methods: {stop() {this.$destroy(); // 销毁vm},},//Vue完成模板的解析并把初始的真实DOM元素放入页面后挂载完毕调用mountedmounted() {// 初始化操作启动定时器console.log(mounted, this);this.timer setInterval(() {console.log(setInterval);this.opacity - 0.01;if (this.opacity 0) this.opacity 1;}, 16);},beforeDestroy() {// 收尾操作清除定时器clearInterval(this.timer);},});/script/body
/html
运行结果 未点击按钮停止变换前点击设置透明度有效点击按钮停止变换后再点击设置透明度则无效因为vm被销毁了。
15. Vue的组件化编程
15.1 模块与组件
1.模块与模块化
模块一个模块就是一个js文件向外提供特定功能的 js 程序作用是可以复用 js、简化 js 的编写、提高 js 运行效率。模块化当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。
2.组件与组件化
组件用来实现局部(特定)功能效果的代码集合(html/css/js/image……)作用是复用编码、简化项目编码、提高运行效率。组件化当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用。
传统方式编写应用 组件化方式编写应用 15.2 非单文件组件
组件的分类
非单文件组件模板编写没有提示 没有构建过程无法将 ES6 转换不支持组件的 CSS真正开发中几乎不用。单文件组件单文件组件为 .vue 文件由template 模板页面、script JS模块对象和 style 样式组成。 虽然非单文件组件在开发中几乎不用但是要想学会单文件组件 .vue 必须先从非单文件组件开始入手。 15.2.1 组件的基本使用
Vue中使用组件的三大步骤
创建组件注册组件使用组件
1.创建组件
使用 Vue.extend(options) 创建组件Vue.extend(options) 和 new Vue(options) 时传入的 options 几乎一样但有区别如下 el 不能写因为最终所有的组件都要经过一个vm的管理由vm中的el决定服务哪个容器data 必须写成函数为了避免组件被复用时数据存在引用关系 注使用template可以配置组件结构 2.注册组件
局部注册靠 new Vue 的时候传入 components 配置项全局注册靠 Vue.component(组件名,组件)
3.使用组件编写组件标签使用组件
组件示例如下
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbody!-- 准备好一个容器--div idapp!-- 第三步使用student组件 --student/student/divscriptVue.config.productionTip false; //阻止 vue 在启动时生成生产提示。// 第一步创建student组件const student Vue.extend({template: divh2学生姓名{{name}}/h2h2学生年龄{{age}}/h2button clickshowName点我提示姓名/button /div,// 组件定义时一定不要写el配置项因为最终所有的组件都要被一个vm管理由vm决定服务于哪个容器data() {return {name: 张三,age: 18,};},methods: {showName() {alert(this.name);},},});// 第二步注册student组件局部注册new Vue({el: #app,components: {student,},});/script/body
/html
以上局部注册也可改为全局注册
// 第二步注册student组件
Vue.component(student, student);new Vue({el: #app,
});15.2.2 组件的注意事项
1.组件名的取名
组件名由一个单词组成 第一种写法(首字母小写)school第二种写法(首字母大写)School推荐 组件名由多个单词组成 第一种写法(kebab-case命名)my-school第二种写法(CamelCase命名)MySchool (推荐且该写法需要Vue脚手架支持)
2.组件标签的两种写法
双标签school/school单标签school/ 备注不用使用脚手架时school/ 会导致后续组件不能渲染 3.Vue.extend()可以简写const school Vue.extend(options) 可简写为 const school options
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbody!-- 准备好一个容器--div idapp!-- 第三步使用student组件 --Student //divscriptVue.config.productionTip false; //阻止 vue 在启动时生成生产提示。// 第一步创建student组件简写省略了Vue.extend()const Student {template: divh2学生姓名{{name}}/h2h2学生年龄{{age}}/h2button clickshowName点我提示姓名/button /div,// 组件定义时一定不要写el配置项因为最终所有的组件都要被一个vm管理由vm决定服务于哪个容器data() {return {name: 张三,age: 18,};},methods: {showName() {alert(this.name);},},};// 第二步注册student组件new Vue({el: #app,components: {Student,},});/script/body
/html
15.2.3 组件的嵌套
组件的嵌套
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbody!-- 准备好一个容器--div idroot/divscriptVue.config.productionTip false; //阻止 vue 在启动时生成生产提示。//定义student组件const student Vue.extend({name: student,template: divh2学生姓名{{name}}/h2 h2学生年龄{{age}}/h2 /div,data() {return {name: 张三,age: 18,};},});//定义school组件const school Vue.extend({name: school,template: divh2学校名称{{name}}/h2 h2学校地址{{address}}/h2 student/student/div,data() {return {name: 北京大学,address: 北京,};},//注册组件局部school中嵌套studentcomponents: {student,},});//定义hello组件const hello Vue.extend({template: h1{{msg}}/h1,data() {return {msg: 欢迎来到北京,};},});//创建vmnew Vue({template: divhello/hello school/school /div,el: #root,//注册组件局部components: {hello,school,},});/script/body
/html
组件之间结构如下 15.2.4 VueComponent
关于VueComponent
1.school 组件本质是一个名为 VueComponent 的构造函数且不是程序员定义的是 Vue.extend 生成的
2.我们只需要编写 school/ 或 school/schoolVue解析时会帮我们创建school组件的实例对象即Vue帮我们执行了 new VueComponent(options)
3.特别注意每次调用 Vue.extend返回的都是一个全新的 VueComponent
4.关于this指向
组件配置中的this指向data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是 VueComponent 实例对象new Vue(options)配置中的this指向data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是 Vue 实例对象
15.2.5 一个重要的内置关系
一个重要的内置关系VueComponent.prototype.__proto__ Vue.prototype这个关系可以让VueComponent组件实例对象访问到 Vue原型上的属性、方法。 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlescript src../js/vue.js/script/headbodydiv idroot/divscriptVue.config.productionTip false; //阻止 vue 在启动时生成生产提示。Vue.prototype.x 99;//定义school组件const school Vue.extend({name: school,template: divh2学校名称{{name}}/h2 h2学校地址{{address}}/h2 button clickshowX点我输出x/button/div,data() {return {name: 北京大学,address: 北京,};},methods: {showX() {alert(this.x);},},});new Vue({template: school/school,el: #root,components: { school },});/script/body
/html
15.3 单文件组件
15.3.1 单文件组件的组成
单文件组件即一个 .vue 文件由以下三部分组成
template 模板页面script JS模块对象style 样式
1.模板页面
template
页面模板
/template2.JS模块对象
scriptexport default {data() {return {};},methods: {},computed: {},components: {},};
/script3.样式
style
样式定义
/style15.3.2 单文件组件的示例
本节仅展示代码和文件之间的关联逻辑此处的代码无法直接运行需要搭建脚手架环境以后才能运行。
示例有以下文件结构作为单文件组件的实际开发使用 文件之间关系如下
index.html 主页面main.js 程序入口App.vue 汇总所有组件此处包括School和Student组件School.vue 学校组件Student.vue 学生组件
index.html
!DOCTYPE html
htmlheadmeta charsetUTF-8 /titleDocument/title/headbody!-- 准备一个容器 --div idroot/divscript typetext/javascript src../js/vue.js/scriptscript typetext/javascript src./main.js/script/body
/html
main.js
import App from ./App.vuenew Vue({el:#root,template:App/App,components:{App},
})
App.vue
templatedivSchool/SchoolStudent/Student/div
/templatescript
//引入组件
import School from ./School.vue;
import Student from ./Student.vue;export default {name: App,components: {School,Student,},
};
/script
School.vue
templatediv classdemoh2学校名称{{name}}/h2h2学校地址{{address}}/h2button clickshowName点我提示学校名/button /div
/templatescriptexport default {name:School,data(){return {name:北京大学,address:北京}},methods: {showName(){alert(this.name)}},}
/scriptstyle.demo{background-color: orange;}
/style
Student.vue
templatedivh2学生姓名{{name}}/h2h2学生年龄{{age}}/h2/div
/templatescriptexport default {name:Student,data(){return {name:张三,age:18}}}
/script