01 Vue的基本概念

  • 概念

    • Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。即是说这个框架可以用于简单到复杂的各种场景
    • 开发者:尤雨溪
  • Vue特点

    1.采用组件化模式,提高代码复用率、且让代码更好维护
    一个.vue文件就包括了html,css,js。编辑一个.vue文件,不会影响其他的.vue文件
    2.声明式编码,让编码人员无需直接操作DOM,提高开发效率
    命令式编程就像“您如何做某事,而声明式编程更像您在做什么
    Vue实现:数据 – 虚拟DOM – 页面真实DOM

  • 搭建Vue开发环境

    https://cn.vuejs.org/v2/guide/installation.html

  • 容器和实例是一一对应的

    JS表达式是一种特殊的JS代码,特殊在表达式会生成一个值
    JS表达式: yige表达式会生成一个值,可以放在任何一个需要值的地方

    • a
    • a + b
    • demo(1)
    • x === y ? a : b

{{XXX}}中,XXX是JS表达式,且XXX自动读取到该数据的所有属性
一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新

02 模板语法

  • 插值语法:
    • 功能:用于解析标签体内容
    • 写法:{{XXX}},xxx是js表达式,且可以直接读取到data中的所有属性
  • 指令语法:
    • 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件···)
    • 举例:v-bind:href=“xxx” 或简写为 :href=“xxx”
    • PS:使用v-bind:后,会把值当成表达式进行处理。 v-bind : XXX 可以简写成 : XXX

03 数据绑定

  • v-bind: 单向数据绑定
  • v-model:双向数据绑定,只能用于表单类(输入类元素,具有value值的元素)元素
    • v-model:value 可以简写成v-model

04 el的两种写法

 - 在new Vue()对象中el直接赋值
 - 通过$mount()函数进行绑定
  • data的两种写法

  • 对象式:在new Vue()对象中data直接赋值

  • 函数式:

     例 :data : function() { return { name : 'XXX'} }
          data () { return { name : 'XXX'} }
    
  • PS :由Vue管理的函数,一定不要写成箭头函数,一旦写成了箭头函数,this就不再是Vue的实例了。

05 MVVM模型

M:模型(Model),对应data中的数据
V:视图(View),模板
VM:视图模型,Vue实例对象

数据代理:通过一个对象代理对另一个对象中属性的操作
Object.defineProperty(变量, 变量中的属性, {})
例:

 let person = {
     name : 'xx',
     sex : 'boy'
 }
 Object.defineProperty(person, 'sex', {
     value : 18, 
     // 控制属性是否可以枚举,默认值false
     enumerable : true,
     // 控制属性是否可以被修改,默认值false
     writable : true, 
     // 控制属性是否可以被删除,默认值false
     configurable : true, 
     get(){},
     set(value){}
})

06 Vue中的数据代理

a. 通过Vue实例来代理data对象中的属性操作
b. 更加方便的操作data中的数据
c. 通过Object.defineProperty()把data对象中所有属性添加到vm上。
   为每一个添加到vm上的属性,都指定一个getter/setter。
   在getter/setter内部去操作data中对应的属性。

07 事件处理

07_1. 事件的基本使用

a. 可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。

<div id="example-2">
    <!-- `greet` 是在下面定义的方法名 -->
    <button v-on:click="greet">Greet</button>
</div>
var example2 = new Vue({
    el: '#example-2',
    data: {
        name: 'Vue.js'
    },
    // 在 `methods` 对象中定义方法
    methods: {
        greet: function (event) {
            alert(event.target)
        }
    }
})

b. 也可以用 JavaScript 直接调用方法

example2.greet() // => 'Hello Vue.js!'

c. 内联处理器中的方法
v-on:click 可以写成 @click
@click=“demo” 和 @click=“demo(event)” 效果一致,后者可以传参
html代码:

<div id="example-3">
    <button v-on:click="say('hi')">Say hi</button>
    <button v-on:click="say('what')">Say what</button>
</div>

javascript代码:

new Vue({
    el: '#example-3',
    methods: {
        say: function (message) {
            alert(message)
        }
    }
})

d. 有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法

<button v-on:click="warn('Form cannot be submitted yet.', $event)">
	Submit
</button>

07_2. 事件修饰符

  • 在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。

  • 尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

  • 为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

    .stop
    .prevent
    .capture
    .self
    .once
    .passive

 <!-- 阻止单击事件继续传播 -->
 <a v-on:click.stop="doThis"></a>

 <!-- 提交事件不再重载页面 -->
 <form v-on:submit.prevent="onSubmit"></form>

 <!-- 修饰符可以串联 -->
 <a v-on:click.stop.prevent="doThat"></a>

 <!-- 只有修饰符 -->
 <form v-on:submit.prevent></form>

 <!-- 添加事件监听器时使用事件捕获模式 -->
 <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
 <div v-on:click.capture="doThis">...</div>

 <!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
 <!-- 即事件不是从内部元素触发的 -->
 <div v-on:click.self="doThat">...</div>

        

课间小插曲

  • @wheel:鼠标滚轮事件
  • @scroll:滚动条滚动事件

07_3. 键盘事件

(1). 在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

    .enter
    .tab (特殊,必须配合keydown使用)
    .delete (捕获“删除”和“退格”键)
    .esc
    .space
    .up
    .down
    .left
    .right

(2). 系统修饰键:

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。
.ctrl
.alt
.shift
.meta

PS:

  • 系统修饰键配合keyup使用:按下修饰键的同事,再按下其他键,随后释放其他键,事件才被触发。系统修饰键配合keydown使用:正常触发事件
  • Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
  • Vue未提供别名的按键,可以使用按键原始的Key值去绑定,但注意要转为kebab-case(短横线命名)
  • keyCode 的事件用法已经被废弃了并可能不会被最新的浏览器支持
  • 在 Mac 系统键盘上,meta 对应 command 键 (⌘)。
    在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。
    在 Sun 操作系统键盘上,meta 对应实心宝石键 (◆)。
    在其他特定键盘上,尤其在 MIT 和 Lisp 机器的键盘、以及其后继产品,比如 Knight 键盘、space-cadet 键盘,meta 被标记为“META”。
    在 Symbolics 键盘上,meta 被标记为“META”或者“Meta”。

(3). .exact 修饰符

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

(4). 鼠标按钮修饰符:这些修饰符会限制处理函数仅响应特定的鼠标按钮

.left
.right
.middle

08. 计算属性: computed

  • 定义:要用的属性不存在,要通过已有属性计算得来
  • 原理:底层借助了Object.defineProperty方法提供的getter和setter。
  • get函数什么时候执行
    • 初次读取时会执行一次
    • 当依赖的数据发生改变时会被再次调用
  • 优势: 与methods实现相比,内部有缓存机制(复用),效率更高,调试方便
  • 备注
    • 计算属性最终会出现在vm上,直接读取使用即可
    • 如果计算属性被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化

例:

<body>
  <div id="root">
      <h1> {{ name }} </h1>
      <h1> {{ name2 }} </h1>
      <h1> {{ fullName }} </h1>
  </div>
  <script type="text/javascript">
      Vue.config.productionTip = false; // 阻止 vue 在启动时生产生产提示
      // 创建Vue实例
      const x = new Vue({
          el: '#root',
          data: {
              name: '张',
              name2 : '三',
          },
          computed : {
              // 完整形式
              fullName : {
                  get() {
                      return this.name + '-' + this.name2
                  },
                  // set什么时候调用?当fullName被修改时
                  // 
                  set(value) {
                      const arr = value.split('-')
                      this.name = arr[0]
                      this.name2 = arr[1]
                  }
              }
              // 只读不写时,可以使用简写形式
              fullName : {
                  // 实际上是使用的get函数
                  return this.name + '-' + this.name2
              }
          }
      })
  </script>
</body>

课间小插曲:Vue 3 Snippets插件:提供代码片段,语法高亮和格式化的 VS Code 插件,能极大提高你的开发效率。

09. 监视属性

(1). 当监视属性发生变化时,回调函数自动调用,进行相关操作
(2). 监视的属性必须存在,才能进行监视
(3). 监视的两种写法
    a. new Vue时传入watch配置
    b. 通过vm.$watch进行监视

例:

<body>
  <div id="root">
      <h1>今天天气很{{info}}</h1>
      <button @click="changeWeather">切换天气</button>
  </div>
  <script type="text/javascript">
      Vue.config.productionTip = false; // 阻止 vue 在启动时生产生产提示
      // 创建Vue实例
      const x = new Vue({
          el: '#root',
          data: {
              name: '张',
              name2 : '三',
          },
          computed : {
              info(){
                  return this.isHot ? '炎热' : '凉爽'
              }
          },
          methods : {
              changeWeather(event) {
                  this.isHot = !this.isHot
              }
          },
          // 方式一
          watch : {
              // 方式一正常写法
              isHot : {
                  immediate : true, // 初始化时让handler调用一下
                  // 什么时候调用?当Hot发生改变的时候
                  handler(newValue, oldValue) {
                      consle.log('xxx')
                  }
              },
              // 方式一简写
              isHot(newValue, oldValue){
                  consle.log('xxx')
              },
          }
      })

      // 方式二正常写法
      x.$watch('isHot', {
          immediate : true,
          handler(newValue, oldValue) {
              consle.log('xxx')
          }
      })
      // 方式二简写
      x.$watch('isHot', (newValue, oldValue) {
          consle.log('xxx')
      })
  </script>
</body>

深度监视

  • Vue中的watch默认不监测对象内部值的改变(一层)
  • 配置deep:true可以监测对象内部的改变(多层)
  • Vue自身可以监测内部值的改变,但Vue提供的watch默认不可以!
  • 使用watch时根据数据的具体结构,决定是否采用深度监视

例:

<body>
   <div id="root">
       <h3>a的值是{{info}}</h3>
       <button @click="numbers.a++">点我让a+1</button>
       <h3>b的值是{{info}}</h3>
       <button @click="numbers.b++">点我让b+1</button>
   </div>
   <script type="text/javascript">
       Vue.config.productionTip = false; // 阻止 vue 在启动时生产生产提示
       // 创建Vue实例
       const x = new Vue({
           el: '#root',
           data: {
               numbers : {
                   a:1,
                   b:1
               }
           },
           watch : {
               // 监视多级结构中的某个属性的变化
               /* 'numbers.a': {
                       handler(){

                       }
                   }, */
               number:{
                   // 可以监测对象内部的改变
                   deep:true,
                   handler(){
                       
                   }
               }
           }
       })
   </script>
</body>

总结

watch和computed的对比

  • computed能完成的功能,watch都能完成
  • watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作

两个重要的小原则

  • 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象
  • 所有不被Vue管理的函数(定时器的回调函数、aja的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象

10. Class与Style绑定

  • 10_1. 绑定class样式

    • 字符串写法:适用于class的类名不固定,需要动态生成
    • 数组写法:适用于要绑定的样式个数不确定,名字也不确定
    • 对象写法:适用于要绑定的样式个数确定、名字也确定,但动态决定要不要使用

    (1).绑定单个class

    html部分:

<div :class="{'active':isActive}"></div>

js部分:判断是否绑定一个active

data() {
   return {
   isActive: true
   };
}

结果渲染为:

<div class="active"></div>

(2).若要绑定多个class,需要逗号隔开就行:(这里的activeTwo加不加引号都可以,也一样都能渲染,如下)

<div class="activeOne" v-bind:class="{ activeTwo: isActive, 'activeThree': hasError }"></div>

js部分:判断是否绑定对应class

data() {
    return {
    isActive: true,
    hasError: true
    };
}

结果渲染为:

<div class="activeOne activeTwo activeThree"></div>

(3).数组语法

<div :class="[activeClass, errorClass]"></div>
data() {
   return {
    activeClass: "active",
    errorClass: "disActive"
    };
},

结果渲染为:

<div class="active disActive"></div>

(4). 绑定的对象

<div :class="classObject"></div>
data: {
    classObject: {
        active: true,
    }
}
  • 10_2. 绑定style样式

    (1). 在 v-bind:style 直接设置样式:
<div id="app">
       <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">XXX</div>
</div>

以上实例 div style 为:

<div style="color: green; font-size: 30px;">XXX</div>

(2). 也可以直接绑定到一个样式对象,让模板更清晰:

<div id="app">
    <div v-bind:style="styleObject">XXX</div>
</div>

(3). v-bind:style 可以使用数组将多个样式对象应用到一个元素上:baseStyles, overridingStyles是样式对象

<div id="app">
    <div v-bind:style="[baseStyles, overridingStyles]">XXX</div>
</div>

11. 条件渲染

(1). v-if

v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。
例:

<h1 v-if="awesome">Vue is awesome!</h1>

(2). v-else

也可以用 v-else 添加一个“else 块”:
例:

<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>

(3). v-else-if

顾名思义,充当 v-if 的“else-if 块”,可以连续使用:
例:

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

PS: 类似于 v-else,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后。

(4). v-show

用于根据条件展示元素的选项是 v-show 指令。用法大致一样:
例:

<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。

ps: v-show 不支持 元素,也不支持 v-else。

(5). v-if vs v-show

  • v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
  • v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
  • 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
  • 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
    较好;如果在运行时条件很少改变,则使用 v-if 较好。

12. 列表渲染

12_1. 基本用法

  • 我们可以用 v-for 指令基于一个数组来渲染一个列表。
  • v-for 指令需要使用 item in items 形式的特殊语法,
    • 其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。 index是当前项的索引
<ul id="example-2">
    <li v-for="(item, index) in items">
        {{ parentMessage }} - {{ index }} - {{ item.message }}
    </li>
</ul>
var example2 = new Vue({
    el: '#example-2',
    data: {
        parentMessage: 'Parent',
        items: [
        { message: 'Foo' },
        { message: 'Bar' }
        ]
    }
})
   1. 用于展示列表数据
   2. 语法:v-for="(item, index) in xxx" :key="yyy"
   3. 可遍历:数组、对象、字符串(用得较少)、指定次数(用得较少)

12_2. key的内部原理(react、vue的key有什么作用)

A. 虚拟DOM中key的作用:

  • key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,

  • 随后Vue进行【新虚拟DOM】和【旧虚拟DOM】的差异比较,比较规则如下:

    B. 对比规则:

  • 旧虚拟DOM中找到了与新虚拟DOM相同的key

    • 若虚拟DOM中内容没变,直接使用之前的真实DOM
    • 若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key

    • 创建新的真实DOM,随后渲染到页面

C. 用index作为key可能会引发的问题

  • 若对数据进行:逆序添加、逆序删除等破坏顺序操作时:
    • 会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低
  • 如果结构中还包含输入类的DOM:
    • 会产生错误DOM更新 ==> 界面有问题

D. 开发中如何选择key?

  • 最好使用每条数据的唯一标识作为key, 比如:id、手机号、身份证号、学号等唯一标识

  • 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的

    12_3. 列表过滤

    12_4. 列表排序

Logo

前往低代码交流专区

更多推荐