Vue基础-Day02

模板语法

事件绑定指令

目标:熟悉v-on指令用法

  • v-on:具体事件名称=”处理逻辑” 处理逻辑:简单js表达式 或者 methods中的函数
  1. 表示式用法
  1. <div class="active" v-show='isShow'>测试事件</div>
  2. <button v-on:click='isShow=!isShow'>点击</button>
  1. 函数用法
  1. <button v-on:click="showInfo">隐藏DIV</button>
  1. new Vue({
  2. el: '#app',
  3. data: {
  4. isShow: false
  5. },
  6. // methods属性专门用于定义函数,
  7. // 1、主要给模板提供事件处理函数
  8. // 2、函数之间也可以相互调用
  9. methods: {
  10. showMsg() {
  11. console.log('nihao')
  12. },
  13. showInfo() {
  14. // 这里的函数中可以操作data中的数据
  15. this.isShow = !this.isShow
  16. // 函数直接也可以相互调用
  17. this.showMsg()
  18. }
  19. }
  20. })

总结:

  1. methods属性专门用于定义函数,
    1、主要给模板提供事件处理函数
    2、函数之间也可以相互调用
  • 函数传递参数
  1. <div id="app">
  2. <ul>
  3. <li v-on:click='getInfo(item.id, item.uname)' :key='item.id' v-for='item in list'>
  4. {{item.uname}}
  5. </li>
  6. </ul>
  7. </div>
  1. methods: {
  2. getInfo(id, name) {
  3. console.log(id, name)
  4. }
  5. }

总结:绑定函数时,可以直接调用函数并且传递实参,那么事件函数中可以直接获取参数值。

  • 访问事件对象
    • $event名称是固定的(Vue的API)
  1. <button data-id='123' v-on:click='showInfo'>点击1</button>
  2. <button data-id='456' v-on:click='showInfo'>点击2</button>
  3. <!-- ----------------------------- -->
  4. <!-- 如果需要手动传递事件对象参数,需要使用$event这个名字 -->
  5. <button data-id='789' v-on:click='showInfo("hi", $event)'>点击3</button>
  1. methods: {
  2. showInfo(msg, e) {
  3. console.log(msg)
  4. console.log(e.target.dataset.id)
  5. }
  6. }

总结:

  1. 如果直接绑定函数名称,那么事件函数的参数中默认得到事件对象
  2. 如果绑定函数调用showInfo(),那么要想得到事件对象,需要手动传递$event,该参数位置自己决定
  • 事件修饰符
  1. 阻止默认行为
  1. <!-- .prevent事件修饰符的作用:阻止标签的默认行为 -->
  2. <a href="http://itcast.cn" v-on:click.prevent='handleJump'>黑马</a>
  1. 阻止冒泡
  1. <div v-on:click='showInfo'>
  2. <!-- 事件名称之后.stop为事件修饰符,用于阻止冒泡 -->
  3. <button v-on:click.stop='handleClick'>点击</button>
  4. </div
  1. 修饰符串联写法:既阻止冒泡又阻止默认行为
  1. <!-- 事件修饰符可以连续使用 -->
  2. <a href="http://itcast.cn" v-on:click.stop.prevent='handleJump'></a>
  • 事件绑定简写方式 v-on:可以简写为@
  1. <a @click.stop="doThis"></a>

总结:

  1. 绑定事件时,最后可以添加事件修饰符
    1. .stop修饰符用于阻止冒泡
    2. .prevent修饰符用于阻止默认行为
  2. 修饰符可以连续使用
  3. 事件绑定的v-on:可以简化为@

双向数据绑定指令

目标:熟悉v-model指令用法;熟悉双向绑定效果

作用:实现表单元素(视图View)和data当中的数据(数据模型Model)的双向的绑定。

  • 双向数据绑定
    • data当中的数据需要在表单元素中显示(M—->V)
    • 当表单元素的值发生改变,绑定的data当中对应的数据也需要改变(V—->M)
  1. <input type="text" v-model="msg">

总结:

  1. 双向绑定是哪两个方向?
    1. V -> M
    2. M -> V
  2. 具体使用指令v-model实现双向绑定
  3. methods中定义的函数中的this指的是vue的实例对象

指令v-model本质分析

目标:熟悉v-model指令的本质(属性绑定和事件绑定)

  • 前提 data 当中有数据:data:{msg:'表单数据'}
    • <input type="text" :value="msg"> 赋值 (M—->V)
    • <input type="text" @input="msg=$event.target.value"> 改值 (V—->M)

总结:v-model指令是一个语法糖(简写代码),它简写了 :value 与 @input 两段代码

image.png

MVVM:将视图(V)和模型(M)解耦——弱化代码之间的关联;然后制定一套通用的规则再建立两者之间的关联关系:

  1. 视图———事件监听———->模型
  2. 模型———数据绑定———->视图
  • 关于v-model执行修饰符lazy的用法
  1. <!-- 如果v-model后面添加lazy修饰符,那么底层的事件监听才用change事件(默认使用input事件) -->
  2. <input type="text" v-model.lazy='msg'>

注意:change和input事件的区别:

  • change事件在失去焦点时触发
  • input事件在有内容变化时触发(按钮按下就触发)

v-once指令用法

目标:知道如何让视图只渲染一次,不受数据变化影响。

作用:优化性能

  1. <div id="app">
  2. <!-- v-once指令会把绑定的数据一次性显示之后,后续就不再更新了 -->
  3. <!-- v-once会把数据绑定变成非响应式的模式 -->
  4. <!-- v-once会提高性能 -->
  5. <!-- 应用场景:一次性展示的内容,后续不需要变更 -->
  6. <div v-once>{{msg}}</div>
  7. </div>
  8. <script src="./vue.js"></script>
  9. <script>
  10. const vm = new Vue({
  11. el: '#app',
  12. data: {
  13. msg: '我是一段信息'
  14. }
  15. })
  16. </script>

注意:【数据】的响应式:数据的变化会导致视图的变化

  1. 一次性展示的内容,后续不需要变更
  2. v-once会提高性能

v-pre指令用法

目标:熟悉v-pre指令的用法

作用:跳过这个元素和它的子元素的编译过程,如果跳过某些标签的编译过程,会提高性能,可以显示原始的信息

  1. <!-- v-pre的作用:防止内部的内容被编译 -->
  2. <span v-pre>{{ msg }}</span>

总结:注意的应用场景:显示标签里面的原始信息

案例功能拓展

添加图书

目标:掌握表单的基本操作流程

  • 基本布局(表单效果)
  • 添加图书按钮的事件绑定
  • 实现添加的功能
  • 清空表单
  1. <!-- 添加图书表单 -->图书名称:<input type="text" v-model='bookname'>图书作者:<input type="text" v-model='author'><button @click='handleSubmit'>提交</button>
  1. methods: {
  2. handleSubmit() {
  3. // 表单验证
  4. if (!this.bookname) {
  5. alert('请输入图书名称')
  6. return
  7. }
  8. // 获取表单数据,添加到列表中
  9. const book = {
  10. bookname: this.bookname,
  11. author: this.author,
  12. date: new Date()
  13. }
  14. // 动态生成图书的编号id(取当前所有图书的id最大值再加1)
  15. // 把图书的所有的图书id放到数组中
  16. const ids = this.books.map(function (item) {
  17. return item.id
  18. })
  19. book.id = Math.max(...ids) + 1
  20. // 把生成的数据对象book添加到列表books中
  21. this.books.push(book)
  22. // 清空表单
  23. this.bookname = ''
  24. this.author = ''
  25. }
  26. },

总结:表单基本布局;绑定表单提交事件;获取表单数据并完善;添加图书数据到列表中即可。

  1. 数组相关的操作方法
    1. forEach 遍历
    2. sort 排序
    3. map 处理数组每一项数据
    4. Math.max方法用法

删除图书

目标:实现删除图书功能

  • 绑定删除按钮事件
  • 获取要删除的图书的id
  • 根据id删除数组中的数据
  1. <td><a @click='handleDelete(item.id)' href="#">删除</a></td>
  1. handleDelete(id) { // 删除图书 // 1、获取要删除的图书id // 2、根据id插值数组中要删除的数据索引 const index = this.books.findIndex(function (item) { // 查找条件 return item.id === id }) // 3、根据索引删除数组中一项数据 this.books.splice(index, 1)},

总结:获取id、更加id获取索引;根据索引删除。 注意:熟悉findIndex方法的使用规则

总结

  • 事件处理
    • 基本事件绑定 v-on:事件名称=表达式/函数名/函数调用
    • 绑定函数名 v-on:click=’showInfo’
    • 绑定函数调用 v-on:click=’showInfo()’
    • 事件函数如何传递参数v-on:click=’showInfo(123,, 456)’
    • 事件对象作为参数传递
      • v-on:click=’showInfo’,这种方式默认会传递事件对象
      • v-on:click=’showInfo($event)’ $event是vue规定的名称,表示事件对象
    • 事件修饰符用法
      • 阻止冒泡 .stop
      • 阻止默认行为 .prevent
      • 事件修饰符可以连续使用
    • 双向绑定指令 v-model ,主要用于表单数据项
      • 从模型到视图 M -> V (数据绑定)
      • 从视图到模型 V -> M (事件监听)
    • v-model的底层实际上是两个指令的组合
      • v-bind:value=’msg’
      • v-on:input=’msg=$event.target.value’
    • v-model的修饰符.lazy用于修改事件input为change事件
    • v-once 仅仅渲染一次,禁用数据响应式效果,提高性能
    • v-pre 不编译模板,显示原始内容
    • v-on:可以简写为@
  • 图书管理案例
    • 添加图书
    • 删除图书
    • 数组相关的方法
      • sort
      • findIndex
      • map
      • some
      • every
      • filter
      • find
    • 计算最大值 Math.max(…arr)

  • 13个指令(把数据填充到模板中)
    • 把数据填充到模板的标签中间
      • 插值表达式(v-cloak)
      • v-text
      • v-html
      • v-once
      • v-pre
    • 把数据填充到模板标签的属性中
      • v-bind
      • v-bind:class
      • v-bind:style
    • 条件渲染
      • v-if
      • v-else
      • v-else-if
      • v-show
    • 列表渲染
      • v-for
      • key的作用
    • 事件监听
      • v-on
      • v-model
        • v-bind:value
        • v-on:input

概念:

  1. 编译:把vue模板中的代码转换为浏览器可以认识的代码
  2. 数据绑定:把数据填充到模板的过程
  3. 数据的响应式:数据的变化会导致页面的自动更新(A的变化会引起B的变化)
  4. 事件监听:给模板中的标签绑定事件

Vue常用特性

通过案例的相关功能学习这些特性

  • 过滤器(格式化日期)
  • 自定义指令(获取焦点)
  • 计算属性(输入查询)
  • 直接操作DOM

过滤器

目标:知道如何定义过滤器和使用过滤器。

作用:在插值表达式中使用,主要用于转换数据格式。

  • 定义过滤器
  1. 全局过滤器(在任何视图中可以使用)
  1. // 实现一个过滤器,用于把图书名称的首字母变成大写
  2. Vue.filter('upcase', function (value) {
  3. // 参数value就表示原始需要处理的数据
  4. // 1、获取原始字符串的首字母
  5. // charAt作用:获取指定索引的单个字符
  6. // toUpperCase作用:把小写字符串转换为大写
  7. const firstLetter = value.charAt(0).toUpperCase()
  8. // 2、截取首字符之外的剩余字符串
  9. const otherLetter = value.substring(1)
  10. // 返回时直接拼接即可
  11. return firstLetter + otherLetter
  12. })
  1. 局部过滤器(在当前vue实例管理的视图才可以使用)
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hi vuejs'
  5. },
  6. filters: {
  7. // 实现格式化日期的功能
  8. formatDate: function (date) {
  9. const year = date.getFullYear()
  10. const month = date.getMonth() + 1
  11. const day = date.getDate()
  12. const hours = date.getHours()
  13. const minutes = date.getMinutes()
  14. const seconds = date.getSeconds()
  15. return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
  16. }
  17. },
  18. })
  • 使用过滤器
  1. <div id="app"> <!-- 需求:输出的字符串是大写(对现有的数据格式不满意,要进行格式转换,使用过滤器) --> <!-- 使用过滤器, | 术语:管道符 --> {{username|upcase}}</div>
  • 基于局部过滤器格式化图书列表中的日期格式
  1. <td>{{item.date | formatDate}}</td>

总结:

  1. 过滤器的作用:格式化数据
  2. 两种定义方式:全局过滤器;局部过滤器
  3. 先定义,再使用(插值表达式中添加【|过滤器名称】)

自定义指令

目标:知道如何定义自定义指令,使用自定义指令。

作用: 我们学过很多vue提供的指令,能够帮助我们实现很多功能,但是不能实现将来我们遇到的所有业务功能,所以vue给你提供了扩展vue指令的方式。(自己封装指令)

  • 注册自定义指令
  1. 全局自定义指令
  1. // Vue.directive('指令的名称','指令的配置对象') 基本语法// 注意:指令的名字在定义时候不需要加v-,在是用的时候才需要加v- Vue.directive('focus', { // 固定属性:inserted 在使用指令的元素渲染完毕后触发的函数 inserted (el) { // 这个函数执行了,代表元素渲染完毕,才可以操作元素。 // 最后根据你指令的需求,实现业务逻辑。el 是使用指令的dom元素 // dom提供的api用了获取焦点 el.focus() }})
  1. 局部自定义指令
  1. const vm = new Vue({ el: '#app', // key是 指令的名称 要求:定义时候不需要加v-,在是用的时候才需要加v- // value是 指令的配置对象 directives: { // 给使用指令的标签添加背景颜色 color: { inserted: function (el, bindings) { // bindings表示指令使用时相关的信息 // el.style.backgroundColor = '#eee' el.style.backgroundColor = bindings.value } } },})
  • 使用指令
  1. <!-- 指令:directive --><div id="app"> <!--需求: v-focus 的指令,自动获取焦点 --> <input type="text" v-focus></div>
  • 图书管理案例实现光标定位和背景变色
  1. <input v-color v-focus='bgColor' v-model='bookname' type="text" class="form-control" placeholder="请输入图书名称">
  1. data: {
  2. bgColor: 'pink'
  3. }

总结:

  1. 内置指令仅仅可以完成一些通用的功能,那么业务相关功能可以通过自定义指令进行扩展
  2. 定义指令:全局自定义指令和局部自定义指令
  3. 先定义,在使用
  • 处理指令相关信息变更的问题
  1. directives: {
  2. // 给使用指令的标签添加背景颜色
  3. color: {
  4. inserted: function (el, bindings) {
  5. // v-focus='bgColor'
  6. // bindings表示指令使用时相关的信息
  7. // el.style.backgroundColor = '#eee'
  8. el.style.backgroundColor = bindings.value
  9. },
  10. update: function (el, bindings) {
  11. // 更新指令相关信息时触发
  12. el.style.backgroundColor = bindings.value
  13. }
  14. }
  15. },

计算属性

目标:知道如何定义计算属性,以及计算属性和函数的区别。

应用场景:vue不建议在模板中(视图中)使用过于复杂的js表达式,可读性差,不好维护,因此可以使用计算属性进行优化。

  • 定义计算属性
  1. new Vue({ el:'#app', data: { message: 'hi vuejs' }, // 计算属性写法,固定的 computed: { // 写函数处理复杂逻辑 handleMsg () { // 反转逻辑,处理之后的结果,是一定要return出去 return this.message.split('').reverse().join('') } }})
  • 使用计算属性(注意computed 声明计算属性是函数,当做属性来用了。)
  1. <div id="app">
  2. <!-- 在模板中直接使用计算属性配置对象中声明的函数名称即可(这个函数名称叫计算属性) -->
  3. {{handleMsg}}
  4. </div>
  • 基于计算属性的方式计算图书的数量
  1. computed: {
  2. bookTotal() {
  3. // 计算图书的总数
  4. return this.books.length
  5. }
  6. },
  1. <div>图书总数是{{bookTotal}}</div>

总结:基于计算属性的方式实现图书数量的统计

  • 计算属性和函数的区别分析
    • 计算属性会基于原来的计算结果进行缓存(多次使用计算属性的值,第一次会计算,后续的使用缓存)
    • 函数是不会缓存的

总结:

  1. 计算属性主要解决模板中复杂的js计算(可读性较差)
  2. 计算属性在使用时不需要添加()
  3. 计算属性在计算时依赖的数据来源于data,如果data中数据发生改变,那么计算属性是否会重新计算?会的
  4. 计算数量是有缓存机制的,但是函数没有

操作DOM

目标:知道使用ref获取DOM元素的方法

在Vue中极大的解放了DOM操作(数据驱动视图),但是极端情况下依然需要操作DOM。

  • 操作DOM步骤
  1. 在需要操作的DOM元素上添加ref属性
  2. 给ref属性加上属性值(保证唯一):<div ref='userInfo'></div>
  3. 在vue的方法中,通过this.$refs.userInfo 获取到DOM元素
  1. <div id="app">
  2. <div ref="myDom">我是一个div</div>
  3. <span ref="mySpan">我是一个span</span>
  4. <button @click="fn">获取dom</button>
  5. </div>
  6. <script src="./vue.js"></script>
  7. <script>
  8. const vm = new Vue({
  9. el: '#app',
  10. methods: {
  11. fn () {
  12. // this.$refs 是收集了视图中所有加了ref属性的dom元素
  13. // this.$refs = {myDom: 'dom元素',mySpan: 'dom元素'}
  14. const dom = this.$refs.myDom
  15. console.log(this.$refs)
  16. console.log(dom)
  17. }
  18. }
  19. })
  20. </script>

总结:

  1. 通用ref属性给标签起一个名字,保证唯一性
  2. 通过this.$refs.ref起的名字获取DOM元素