第一章 Vue认识和基础
安装Vue插件到浏览器。
Vue 简介
渐进式 JavaScript 框架
作者:尤雨溪 大学 科尔盖特大学
易学易用,性能出色,适用场景丰富的 Web 前端框架。
Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。
渐进式框架
Vue 是一个框架,也是一个生态。其功能覆盖了大部分前端开发常见的需求。但 Web 世界是十分多样化的,不同的开发者在 Web 上构建的东西可能在形式和规模上会有很大的不同。考虑到这一点,Vue 的设计非常注重灵活性和“可以被逐步集成”这个特点。根据你的需求场景,你可以用不同的方式使用 Vue:
-
无需构建步骤,渐进式增强静态的 HTML
-
在任何页面中作为 Web Components 嵌入
-
单页应用 (SPA)
-
全栈 / 服务端渲染 (SSR)
-
Jamstack / 静态站点生成 (SSG)
-
开发桌面端、移动端、WebGL,甚至是命令行终端中的界面
如果你是初学者,可能会觉得这些概念有些复杂。别担心!理解教程和指南的内容只需要具备基础的 HTML 和 JavaScript 知识。即使你不是这些方面的专家,也能够跟得上。
如果你是有经验的开发者,希望了解如何以最合适的方式在项目中引入 Vue,或者是对上述的这些概念感到好奇,我们在使用 Vue 的多种方式中讨论了有关它们的更多细节。
无论再怎么灵活,Vue 的核心知识在所有这些用例中都是通用的。即使你现在只是一个初学者,随着你的不断成长,到未来有能力实现更复杂的项目时,这一路上获得的知识依然会适用。如果你已经是一个老手,你可以根据实际场景来选择使用 Vue 的最佳方式,在各种场景下都可以保持同样的开发效率。这就是为什么我们将 Vue 称为“渐进式框架”:它是一个可以与你共同成长、适应你不同需求的框架。
Vue初次体验
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root">{{username}}</div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', data: { username: '张三', }, }) </script> </body> </html>
Vue指令语法
①插值表达式:
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root">{{num1+num2}}</div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { num1: 6, num2: 8, }, }) </script> </body> </html>
案例二:
对象插值表达式使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <!-- {{num1+num2}} --> 姓名:{{user.name}} <br /> 年龄:{{user.age}}<br /> 性别:{{user.sex}} </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { // num1: 6, // num2: 8, user: { name: '高启强', age: 48, sex: '男', }, }, }) </script> </body> </html>
②v-text用法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <p v-text="content"></p> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { content: '我是中国人', }, }) </script> </body> </html>
③v-html用法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <!-- 这样写就直接解析html标签属性 --> <div v-html="docontent"></div> <!-- 插值是原样输出 --> <div>{{docontent}}</div> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { docontent: '<h4 style="color: red; font-weight: bold;">欢迎大家来学习前端 vue技术</h4>', }, }) </script> </body> </html>
-
{{ }}
插值表达式:在实际开发中用的最多,只是内容的占位符,不会覆盖原有的内容! -
v-text
指令的缺点:会覆盖元素内部原有的内容! -
v-html
指令的作用:可以把带有标签的字符串,渲染成真正的 HTML 内容!
MVVM架构模型
属性绑定指令
属性绑定指令分单项属性绑定指令和双向数据绑定指令。
①单项数据绑定指令:v-bind
单项数据绑定指令一般开发用在非表单的标签。
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <!-- v-bind可以简写成英文的: --> <p :title="title">{{title}}</p> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { title: '学习Vue开发', }, }) </script> </body> </html>
案例二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <input type="text" :placeholder="tips" /><br /> <hr /> <img :src="photo" alt="" style="width: 680" /> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { photo: 'https://syw.ctgu.edu.cn/__local/8/6E/DD/2F507A146723E194C2A7404B0EA_DEE66658_1D0B0.jpg', tips: '请您输入', }, }) </script> </body> </html>
②事件绑定
v-on:
简写是 @
案例一
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> 你看到的数字是{{num}} <hr /> <button @click="add">点击一下加1</button> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { num: 0, }, methods: { add() { this.num += 1 console.log(this) }, }, }) </script> </body> </html>
案例二:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <h2>欢迎来到学习{{name}}技术</h2> <!-- <button v-on:click="showInfo">点我提示信息</button> --> <button @click="showInfo1">点我提示信息1(不传参)</button> <button @click="showInfo2($event,88)">点我提示信息2(传参)</button> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { name: 'vue', }, methods: { showInfo1(event) { // console.log(event.target.innerText) // console.log(this) //此处的this是vm alert('同学你好!') }, showInfo2(event, number) { console.log(event, number) // console.log(event.target.innerText) // console.log(this) //此处的this是vm alert('同学你好!!') }, }, }) </script> </body> </html>
按键修饰符
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> 按键esc清空输入内容 <input type="text" @keyup.esc="doesc" /> <hr /> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { username: '', }, methods: { doesc(e) { //e.targen.value = '' e.target.value = '' console.log('执行了esc按键操作') }, }, }) </script> </body> </html>
③双向绑定V-model
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> 双向绑定 <input type="text" v-model="username" /> <input type="text" v-model="password" /> <hr /> 单项绑定 <input type="text" :value="username" /> <input type="text" :value="password" /> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { username: '张三', password: '123456', }, }) </script> </body> </html>
双向绑定在实际开发中用于表单元素。
V-if指令:
V-if是用来判断条件的,和java中的if语句是一样的。
案例:
<div id="root"> <template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template> </div> </body> <script src="./js/vue.js"></script> <script> const vm = new Vue({ el:'#root', data(){ return{ ok:true } } })
V-if 及V-else指令
相当于java中的if else 作用。
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue使用</title> </head> <body> <div id="root"> <div> <template v-if="isValues"> <h3>你今天生病了吗? 没有</h3> <hr> </template> <template v-else="isValues === false"> <h3>你今天生病了吗?伤病了</h3> <hr> </template> <button @click="updateValue">点击事件</button> </div> </div> </body> <script src="./js/vue.js"></script> <script> const vm = new Vue({ el:'#root', data(){ return{ isValues:true, } }, methods: { updateValue(){ this.isValues = !this.isValues } }, }) </script> </html>
V-show指令:
另一个用于根据条件展示元素的选项是 v-show
指令。用法大致一样:
<h1 v-show="ok">Hello!</h1> <hr> const vm = new Vue({ el:'#root', data(){ return{ ok:false, // isValues:true, } },
注意,v-show
不支持 <template>
元素,也不支持 v-else
。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
V-for指令:
过滤器(了解学习Vue3中已经删除了。)
filter
过滤器(Filters)是 vue 为开发者提供的功能,常用于文本的格式化。过滤器可以用在两个地方:插值表达式 和 v-bind 属性绑定。 过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用。
案例一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> 先输出 <p>{{massage}}</p> <hr /> 通过过滤器输出 <p>{{massage | cap}}</p> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { massage: 'hello vue.js', }, methods: { }, //过滤器声明 filters: { //过滤器是函数 cap(vul) { //过滤器必须要求返回值。 //console.log(vul) //return '啊啊啊啊啊啊' return vul.charAt(0).toUpperCase() + vul.slice(1) }, }, }) </script> </body> </html>
案例练习
实现效果:
案例代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="./css/brandlist.css" /> <link rel="stylesheet" href="./tjs/bootstrap.css" /> <title>案例练习</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <div class="card"> <div class="card-header">添加名称</div> <div class="card-body"> <!-- 添加品牌的表单区域 --> <!-- form 表单元素有 submit 事件 --> <form @submit.prevent="add"> <div class="form-row align-items-center"> <div class="col-auto"> <div class="input-group mb-2"> <div class="input-group-prepend"> <div class="input-group-text">用户名称</div> </div> <input type="text" class="form-control" placeholder="请输入用户名称" v-model.trim="brand" /> </div> </div> <div class="col-auto"> <button type="submit" class="btn btn-primary mb-2">添加</button> </div> </div> </form> </div> </div> <table class="table table-bordered table-hover table-striped"> <thead> <tr> <th scope="col">#</th> <th scope="col">用户名称</th> <th scope="col">用户状态</th> <th scope="col">创建时间</th> <th scope="col">操作</th> </tr> </thead> <tbody> <tr v-for="item in list" :key="item.id"> <td>{{ item.id }}</td> <td>{{ item.name }}</td> <td> <div class="custom-control custom-switch"> <!-- 使用 v-model 实现双向数据绑定 --> <input type="checkbox" class="custom-control-input" :id="'cb' + item.id" v-model="item.status" /> <!-- 使用 v-if 结合 v-else 实现按需渲染 --> <label class="custom-control-label" :for="'cb' + item.id" v-if="item.status" >健康</label > <label class="custom-control-label" :for="'cb' + item.id" v-else >生病</label > </div> </td> <td>{{ item.time | dateFormat }}</td> <td> <a href="javascript:;" @click="remove(item.id)">删除</a> </td> </tr> </tbody> </table> </div> <!-- 导入Vue的js --> <script src="./tjs/dayjs.min.js"></script> <script src="../js/vue.js"></script> <script> Vue.filter('dateFormat', function (time) { // 1. 对 time 进行格式化处理,得到 YYYY-MM-DD HH:mm:ss // 2. 把 格式化的结果,return 出去 // 直接调用 dayjs() 得到的是当前时间 // dayjs(给定的日期时间) 得到指定的日期 const dtStr = dayjs(time).format('YYYY-MM-DD HH:mm:ss') return dtStr }) // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { brand: '', // nextId 是下一个,可用的 id nextId: 4, // 品牌的列表数据 list: [ { id: 1, name: '张三', status: true, time: new Date() }, { id: 2, name: '李四', status: false, time: new Date() }, { id: 3, name: '王五', status: true, time: new Date() }, ], }, methods: { // 点击链接,删除对应的品牌信息 remove(id) { this.list = this.list.filter((item) => item.id !== id) }, // 阻止表单的默认提交行为之后,触发 add 方法 add() { // 如果判断到 brand 的值为空字符串,则 return 出去 if (this.brand === '') return alert('必须用户名称') // 如果没有被 return 出去,应该执行添加的逻辑 // 1. 先把要添加的品牌对象,整理出来 const obj = { id: this.nextId, name: this.brand, status: true, time: new Date(), } // 2. 往 this.list 数组中 push 步骤 1 中得到的对象 this.list.push(obj) // 3. 清空 this.brand;让 this.nextId 自增 +1 this.brand = '' this.nextId++ }, }, }) </script> </body> </html>
第二章Vue
axios 发送请求后端接口
axios 的基本使用
发送get请求:
axios({ // 请求方式 method: 'GET', // 请求的地址 url: 'http://127.0.0.1:10086/api/get',//请求路径 // URL 中的查询参数 params: { id: 1 } }).then(function (result) { console.log(result) })
发送POST请求:
document.querySelector('#btnPost').addEventListener('click', async function () { // 如果调用某个方法的返回值是 Promise 实例,则前面可以添加 await! // await 只能用在被 async “修饰”的方法中 const { data: res } = await axios({ method: 'POST', url: 'http://127.0.0.1:10086/api/post', data: { name: 'zs', age: 20 } }) console.log(res) })
案例一:(请求我们之前开发的年级数据)记得在年级的controller加上跨域注解 @CrossOrigin
不加注解错误:
代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <!-- 导入Vue的js --> <!-- <script src="js/vue.js"></script> --> <script src="js/axios.js"></script> <script> //调用axios返回结果是Promise 对象 const result = axios({ method: 'GET', url: 'http://127.0.0.1:10086/sms/gradeController/getGrades', }) // console.log(res) result.then(function (list) { console.log(list) }) </script> </body> </html>
上述返回结果是:Promise 对象,如果需要后台数据,只需要在返回结果中加上list.data就可以实现。
Post 请求:
案例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/axios.js"></script> </head> <body> <script> //调用axios返回结果是Promise 对象 const result = axios({ method: 'post', url: 'http://127.0.0.1:10086/sms/gradeController/saveOrUpdateGrade', data:{ name:'大学三年级', manager:'赵六', email:'111@163.com', telephone:'17812345678', introducation:'这个班级学生学习JavaEE开发' } }) // console.log(res) result.then(function (list) { console.log(list.data) }) </script> </body> </html>
Vue CLI(Vue 脚手架及工程化开发)
按照官网安装:
命令:在doc 命令下输入:
npm install -g @vue/cli # OR yarn global add @vue/cli
npm淘宝的代理:
npm config set registry https://registry.npm.taobao.org
建议用npm
安装好可以查看版本。
用dos 命令:
vue --version
如果想升级Vue CLI可以用下面命令:
npm update -g @vue/cli # 或者 yarn global upgrade --latest @vue/cli
创建项目用下面命令:
vue create 项目名称
这里选择自定义选择。
先选择vue2.0版。后续我们用vue3.0
下面就可以启动项目了,我就在IDEA中启动了。
启动命令:
npm run serve
ctrl+c
第二种创建Vue工程项目方式:
Vue ui
安装yarn 命令:
①
npm install -g yarn
②查看版本:
yarn --version
③安装yarn的依赖:
yarn install
上述是需要的同学安装。
yarn 没有npm稳定建议使用npm命令。
assets 文件夹:存放项目中用到的静态资源文件,例如:css 样式表、图片资源components 文件夹:程序员封装的、可复用的组件,都要放到 components 目录下main.js 是项目的入口文件。整个项目的运行,要先执行 main.jsApp.vue 是项目的根组件。
①自己创建Vue需要在components 目录下。
②导入Vue import Ins from 具体目录
③注册到Vue根元素下面的components
components: { HelloWorld, Ins }
④标签方式使用组件。
下面咱们就体验一下Vue组件。
新建一个mains.Vue如下:
<template> <div id="app"> <h3>内容输出</h3> <p> {{username}} </p> </div> </template> <script> export default { name: "Mains", /*data:{ username:'张大大' }*/ data(){ return { username:'张大大' } } } </script> <style lang="less"> </style>
①将main.js中的换成mains里内容,上述Mains.Vue就可以在页面渲染。
②说明Vue初始化先执行main.js 油main.js 确定加载哪个Vue来做初始加载。
③Vue初始就是Vue组件
组件中的data用data函数。
Vue事件(下篇)
-
绑定事件:<div v-on:事件名='函数名'></div>
-
实现方法:methods:{
函数名(){
}
}
-
事件对象 event
-
无参数传递 :第一个参数就是event
-
有参数传递 :需要手动传递事件对象
<div v-on:click='demo(1,2,$event)'></div>
-
-
事件修饰符.stop *.prevent *.capture.self.once.passive
案例一(阻止事件冒泡)
<template> <div> <h2>vue事件处理</h2> <!-- 1. 事件修饰符 --> <div @click="parent"> 我是小头爸爸 <!-- 阻止单击事件继续传播 --> <button @click.stop="child">大头儿子</button> </div> </div> </template> <script> export default { name: "vue-event", methods: { child(e) { e.stopPropagation()//使用vue提供的修饰符 console.log("子元素事件"); }, parent(){ console.log("父元素事件"); } }, } </script> <style scoped> </style>
两种方式:
一、通过@click.stop 阻止单击事件继续传播
二、通过 e.stopPropagation()阻止单击事件继续传播
-
按键修饰符.enter * .tab.delete (捕获“删除”和“退格”键).esc.space.up.down.left.right
案例二(按键事件)
<template> <input type="text" v-on:keyup.enter='getInput'> </template> <script> export default { name: "input-vue", methods:{ getInput(e){ //console.log(e); console.log('按下了回车--搜索'); } } } </script> <style scoped> </style>
-
系统修饰键.ctrl.alt.shift.meta
案例三:
<template> <div> <!-- 3. 系统修饰键 --> <textarea @keyup.ctrl.enter="" cols="30" rows="10"></textarea> <button @click="send">发送</button> </div> </template> <script> export default { name: "vue-send", methods:{ //系统修饰符 send(){ console.log('发送了聊天信息'); } } } </script> <style scoped> </style>
-
鼠标按钮修饰符.left.right.middle
数组更新检测
-
说明:在列表渲染中,如果遍历是数组,当数组数据发生改变时,页面什么时候能自动更新(页面重新渲染)
-
实现数组视图同步更新
-
变更方法 (修改了原数组)push()pop()shift()unshift()splice()sort()reverse()
-
替换数组(修改后返回新的数组 原数据不修改 视图想同步更新 覆盖原数组)filter()、concat() 和 slice()
-
**案例演示数组追加、反转、切割**
```vue <template> <div> <h2>数组更新同步</h2> <p>arr:{{ arr }}</p> <button @click="addArr">追加数组</button> <button @click="sliceArr">切割数组</button> <button @click="reverseArr">数组反转</button> </div> </template> <script> export default { name: "vue-array", data() { return { arr: [1, 2, 3], }; }, methods: { reverseArr(){ this.arr.reverse() }, addArr() { this.arr.push(100) }, sliceArr() { //slice() 返回新的数组 let newArr = this.arr.slice(0); console.log(newArr); //替换 this.arr = newArr; }, }, } </script> <style scoped> </style> ```
对象更新检测
-
说明:对象修改后 视图同步更新视图 -- 内存:栈内存 堆内存
-
实现对象视图同步更新
-
Vue.set( target, propertyName/index, value )参数:
{Object | Array} target {string | number} propertyName/index {any} value 返回值:设置的值。
用法:
向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')
-
案例(对象同步更新)
<template> <div> <h2>对象同步更新</h2> <p>对象obj:{{ obj }}</p> <button @click="changeUname">修改对象已存在的属性</button> <button @click=" obj = {user:'admin'}">修改整个obj</button> <button @click="addAttribute">给obj添加不存在的属性</button> </div> </template> <script> export default { name: "vue-object", data(){ return { obj:{ uname:'张三三', age:20 } } }, methods:{ changeUname(){ this.obj.uname ='李思思' }, addAttribute(){ this.obj.sex='女' console.log('obj',this.obj); //问题:vue认为 obj没有修改 //1. ... // this.obj ={...this.obj}; //2. es6: 合并对象 Object.assign({},{},{}) // this.obj=Object.assign({},this.obj) //3. vue官网解决方法: //向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。 // this.$set(this.obj,'love','女') //Vue.set(this.obj,'learn','学习') //删除 同步视图 删除对象的 property。如果对象是响应式的,确保删除能触发更新视图。 //Vue.delete(this.obj,'age') } } } </script> <style scoped> </style>
Class 与 Style 绑定
-
介绍:动态的添加class或者是style样式
-
绑定 HTML Class
-
直接绑定变量
<div v-bind:class='变量'></div>
-
对象语法 ***
<div v-bind:class="{类名: 表达式-true显示类名、false隐藏 ,类名:boolean}"></div>
-
数组语法
<div v-bind:class="[变量1,变量2, {类名:boolean}]"></div>
-
-
绑定内联样式v-bind:style 的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名
-
对象语法
<div v-bind:style="{css样式:变量,... }"></div>
-
数组语法
<div v-bind:style="[baseStyles, overridingStyles]"></div>
-
直接变量
<div v-bind:style="styleObject"></div>
data: {
styleObject: { color: 'red', fontSize: '13px' }
}
-
表单输入绑定
-
介绍你可以用 v-model 指令在表单 <input>、<textarea> 及 <select> 元素上创建双向数据绑定通过指令 v-model='' 获取表单输入的信息数据 实现双向数据绑定
-
语法: <input type='text' v-model='变量' />data(){
return{ msg:'' }
}
-
修饰符 .lazy 只有当input失去焦点时才更新数据 .number 把input标签中输入的内容转成数字,调用是parseFloat (Nunber()) .trim 去除左右空格
-
v-model实现原理v-model只不过是一个语法糖而已,真正的实现靠的还是
v-bind:绑定响应式数据触发oninput 事件并传递数据
v-model 是什么。语法糖 :value + @input。还要分为两种情况
<input v-model="val"><!-- 基本等价于,因为内部还有一些其他的处理 -->是事件对象,event.target.value表示input框中的输入值<input :value="val" @input="val = $event.target.value">
*案例练习
<template> <div> <h2>表单输入绑定</h2> <!-- <input type="text" :value="msg" name="" id=""> --> <!-- 1. 文本/密码 v-model=''--> <input type="text" placeholder="请输入" v-model="formData.msg" @keyup.enter="send" name="" id="" /> <p>msg:{{ formData.msg }}</p> <!-- 2. 多行文本 --> <!-- 3. 单选按钮 --> 性别: <input type="radio" v-model="formData.sex" name="aa" value="1" />男 <input type="radio" v-model="formData.sex" name="aa" value="2" />女 <p>选择的性别:{{ formData.sex }}</p> 爱好: <input type="checkbox" v-model="formData.arr" value="a" />吃 <input type="checkbox" v-model="formData.arr" value="b" />喝 <input type="checkbox" v-model="formData.arr" value="c" />玩 <p>选择的爱好:{{ formData.arr }}</p> 城市: <select name="" id="" v-model="formData.select"> <option value="">请选择</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="gaungzhou">广州</option> </select> <p>城市选择:{{ formData.select }}</p> <button @click="submit">注册信息</button> <hr> <h3>表单修饰符 -修饰符 </h3> <!-- .lazy 失去焦点或者回车 获取数据 --> <input type="text" v-model.lazy="search"> <p>search:{{ search }}</p> <!-- .trim 去掉前后空格 --> <input type="text" v-model.trim="msg" name="" id=""> <p>去空格:{{msg}}</p> <!-- .number 转数字 --> <input type="number" v-model.number="num" name="" id=""> <p>num:{{ num }}</p> <!-- v-model实现的原理 --> <input type="text" v-model="inp" name="" id=""> <p>inp:{{inp}}</p> <!-- v-model == v-bind:value='' @input='函数' --> 表单值:<input type="text" :value="val" @input="changeVal" name="" id=""> <p>val:{{val}}</p> </div> </template> <script> export default { data() { return { val:'请输入', inp:'', msg: "", //输入框 sex: 1, //性别 arr: [], select: "", search:'', num:'', //对象的语法--------------- formData: { msg: "", //输入框 sex: 1, //性别 arr: [], select: "", }, }; }, methods: { send() { console.log("输入的数据为:", this.msg); }, submit() { //点击按钮--发送输入的数据给后台-- data -- msg sex arr ... console.log("提交注册信息表单",this.formData); }, changeVal(e){ console.log(e); console.log(e.target.value);//獲得輸入信息 this.val = e.target.value; } }, }; </script> <style> </style>
例题:将上述的张大大点击按钮后修改成岳云鹏
实现方式如下:
<template> <div id="app"> <h3>内容输出</h3> <p> {{username}} </p> <button @click="updateUserName">修改上述张大大</button> </div> </template> <script> export default { name: "Mains", /*data:{ username:'张大大' }*/ data(){ return { username:'张大大' } }, //这里需要和data函数平级 methods:{ updateUserName(){ this.username = "岳云鹏" //this 表示Vue对象 } } } </script> <style lang="less"> </style>
计算属性讲解
计算属性是定义在computed 这个当中。
计算属性中必须有get()
计算属性是计算出来的没有在Vue对象中,通过Vue插件可以证明。
案例显示如下:
定义一个三峡大学,定义一个科技学院 然后通过计算属性将他们连接起来。
实现如下:
<template> <div id="app"> <span> {{frName}} </span> <hr> <span> {{LzName}} </span> <hr> <span> {{allName}} </span> </div> </template> <script> export default { name: "Mains", data(){ return { frName:"三峡大学", LzName:"科技学院" } }, //用来定义计算属性。 computed:{ allName:{ get(){ return this.frName +'-'+ this.LzName } } }, methods:{ } } </script> <style lang="less"> </style>
计算属性中也有set()函数。 是用来修改数据的【开发当中不常用】。
上述可以简化为下面代码。
allName(){ return this.frName + '-'+this.LzName }
实现代码如下:
<template> <div id="app"> <h3>你今天生病了吗?{{isValues?'没有':'生病了'}}</h3> <hr> <button @click="updateValue">点击变化</button> </div> </template> <script> export default { name: "Mains", data(){ return { isValues:true, } }, computed:{ }, methods:{ updateValue(){ this.isValues = !this.isValues } } } </script> <style lang="less"> </style>
上述功能实现了,需要用计算属性来实现。
<template> <div id="app"> <h3>你今天生病了吗?{{info}}</h3> <hr> <button @click="updateValue">点击变化</button> </div> </template> <script> export default { name: "Mains", data(){ return { isValues:true, } }, computed:{ info(){ return this.isValues?'没有':'生病了' } }, methods:{ updateValue(){ this.isValues = !this.isValues } } } </script> <style lang="less"> </style>
案例三
<template> <div> <h2>计算属性computed</h2> <!-- 如果是字符串 取反操作实现 --> <p>字符串:{{ msg }}</p> <!-- 不推荐: 模板语法里面写很多方法 多次使用不方便 --> <p>字符串-取反:{{ msg.split("").reverse().join("") }}</p> <p>字符串-取反-封装函数:{{ qufan() }}</p> <p>字符串-取反-封装函数:{{ qufan() }}</p> <p>字符串-取反-封装函数:{{ qufan() }}</p> <!-- 计算属性: --> <p>计算属性:-取反:{{ msg2 }}</p> <p>计算属性:-取反:{{ msg2 }}</p> <p>计算属性:-取反:{{ msg2 }}</p> <button @click="msg = 'how are you'">修改msg</button> <!-- 例子: v-for='' v-if不能在同一个元素使用 -- computed处理数据 --> <h4>早市水果更新:</h4> <ul> <li v-for="item in zaoshi2" :key='item.id'> {{item.fruit}} </li> </ul> </div> </template> <script> export default { data() { return { msg: "hello vue", zaoshi: [ { id: 100, fruit: "苹果", flag: false, }, { id: 101, fruit: "阳光玫瑰", flag: true, }, { id: 102, fruit: "车厘子", flag: false, }, { id: 103, fruit: "榴莲", flag: true, }, ], }; }, methods: { qufan() { console.log("执行了方法"); return this.msg.split("").reverse().join(""); }, }, //计算属性: 对数据进行加工处理 缓存数据 computed: { msg2() { console.log("计算属性: 对数据进行加工处理 缓存数据"); return this.msg.split("").reverse().join(""); }, //处理数据 zaoshi2(){ //过滤方法 返回的满足条件的数组 比如:[1,2,3,4] =>[3,4] return this.zaoshi.filter((item)=>{ return item.flag }) } }, }; </script> <style> </style>
侦听器学习:(watch)
定义格式为 watch:{
对那和属性侦听
}
将上面的例子修改一下:
<template> <div id="app"> <h3>你今天生病了吗?{{info}}</h3> <hr> <button @click="updateValue">点击变化</button> </div> </template> <script> export default { name: "Mains", data(){ return { isValues:true, } }, computed:{ info(){ return this.isValues?'没有':'生病了' } }, watch:{ isValues:{ handler(newValue,oldValue){ //console.log(newValue,oldValue) console.log('isValues被修改了',newValue,oldValue) }, } }, methods:{ updateValue(){ this.isValues = !this.isValues } } } </script> <style lang="less"> </style>
侦听 中有handler()函数,通过handler()中newValue,oldValue获得侦听 前的值和侦听后的值。
第二种侦听通过Vue对象中定义的$watch()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 绑定Vue数据的插值语法 --> <div id="root"> <h3>你今天生病了吗?{{info}}</h3> <hr /> <button @click="updateValue">点击变化</button> </div> <!-- 导入Vue的js --> <script src="js/vue.js"></script> <script> // 初始化Vue const vm = new Vue({ el: '#root', //绑定事件 data: { isValues: true, }, computed: { info() { return this.isValues ? '没有' : '生病了' }, }, methods: { updateValue() { this.isValues = !this.isValues }, }, }) vm.$watch('isValues', { handler(newValue, oldValue) { //console.log(newValue,oldValue) console.log('isValues被修改了', newValue, oldValue) }, }) </script> </body> </html>
computed和watch区别 (考点面试题)
-
相同:computed和watch都是观察页面的数据变化的。
-
不同:computed:是计算属性,依赖其它属性值:
1. 支持缓存,只有依赖数据发生改变,才会重新进行计算 2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化 watch:没有缓存性,更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作; 1. 不支持缓存,数据变,直接会触发相应的操作; 2. watch支持异步;
# 第三章 vue