Vue入门笔记之初体验

(一) Vue.js 概述

Vue: 是一套用于构建用户界面的渐进式框架, 与其它大型框架不同的是, Vue 被设计为可以自底向上逐层应用. 渐进式意味着你可以将Vue作为你应用的一部分嵌入其中, 带来更丰富的交互体验. Vue拥有区别其他前端框架的专属特点:

  • 解耦视图和数据
  • 可复用的组件
  • 前端路由技术 (Vue Router)
  • 状态管理 (Vuex)
  • 虚拟DOM


(二) Vue.js 安装

  • 方式一: 直接CDN引入
    • 开发环境版本, 包含了有帮助的命令行警告
      <script src=“https://cdn.jsdelivr.net/npm/vue/dist/vue.js”>
    • 生产环境版本, 优化尺寸和速度
      <script src=“https://cdn.jsdelivr.net/npm/vue@2.6.11”>

  • 方式二: 下载和引入
    • 开发环境: https://cn.vuejs.org/js/vue.js
    • 生产环境: https://cn.vuejs.org/js/vue.min.js

  • 方式三: NPM安装
    $ npm install vue
    
<!DOCTYPE html>
<html lang="en">

<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
</head>

<body>
   <div id="app">
      <div>{{message}}</div>
   </div>
   
   <script src="../js/vue.js"></script>
   <script>
      // 命令式编程(传统js做法, 显示messige) 向 声明式编程 的转变
      const app = new Vue({
         el: '#app', // 用于挂载要管理的元素(选择器)
         data() { // 定义变量, 存储数据
            return {
               message: 'Hellow, Vue !!'
            }
         }
      })
   </script>

</body>
</html>

在这里插入图片描述


(三) Vue 中的 MVVM

MVVM(Model-View-ViewModel): 它对MVC(Model-View-Controller)的改进版, MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑(数据模型)的开发分离开来,这是通过置标语言或GUI代码实现的。MVVM的视图模型是一个值转换器, 这意味着视图模型负责从模型中暴露(转换)数据对象,以便轻松管理和呈现对象。在这方面,视图模型比视图做得更多,并且处理大部分视图的显示逻辑。 视图模型可以实现中介者模式,组织对视图所支持的用例集的后端逻辑的访问。------摘自维基百科

Vue中的MVVM 图解
在这里插入图片描述

  • View层: 在前端开发中, 通常指的是DOM层. 主要作用是给用户展示各种信息
  • Model层: 数据层中的数据可以是固定数据, 也可以是从服务器请求的数据
  • ViewMdoel层: 视图模型层是 View 与 Model 沟通的桥梁, 一方面它实现了Data Binding 数据绑定, 将Model的改变实时响应到View中; 另一方面它实现了DOM Listener DOM监听, 可以监听到View(DOM)中发生的事件, 并在需要的情况先改变对应Model.



(四) Vue 中的Options选项

  • el:
    类型:string | Element
    提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。
  • template:
    类型: string
    一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素, template使用优先级比较高
  • data:
    类型:Object | Function
    Vue 实例对应的数据对象, 组件的定义只接受 function函数 (data 如果还是是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!)
  • methods:
    类型: { string : Function }
    methods 将被混入到 Vue 实例中。可以直接通过实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例
  • 生命周期钩子函数(8个)
  • 计算属性

Vue 中的Options选项还有非常多, 在这就不一一列举了, 可以参考 Vue 中文官方文档



(五) Vue 中的生命周期函数

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如: 每个组件都有一个属于它的生命周期,从一个组件创建、数据初始化、挂载、更新、销毁,这就是一个组件所谓的生命周期. 在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

图解vue生命周期
在这里插入图片描述
这个8个生命周期钩子的函数, 最终会被Vue实例内部的callHook()函数调用



(六) 插值操作-mustache语法

Mustache: 是一个logic-less(轻逻辑)模板解析引擎,它是为了使用户界面与业务数据(内容)分离而产生的.
{{ keyName }} Mustache 的标示符,双括号里的 keyName 表示键名,这句的作用是直接输出与键名匹配的键值, 也可以写简单的表达式语法

<h3>{{message}}</h3>
<h3>{{flag}} {{!flag}}</h3>
<h3>{{num1 + num2}}</h3>

...

data() { 
   return {
      message: 'Hellow, Vue!!',
      num1: 10,
      num2: 20,
      flag: true
   }
}

在这里插入图片描述

(七) Vue 指令

1. v-once

v-once: 指令表示元素和组件只会渲染一次, 不会随着数据的改变而改变. 且 该指令不需要跟任何表达式

<h3>{{message}}</h3>
<h3 v-once>{{message}}</h3>

2. v-html

v-html: 指令会将String类型的html解析并进行渲染. v-html=“String类型的HTML”

<h3>{{url}}</h3>
<h3 v-html="url"></h3>
data() { 
   return {
      url: '<a href="https://www.baidu.com">百度一下</a>'
   }
}

在这里插入图片描述

3. v-pre

v-pre: 指令用于跳过这个元素和它子元素的编译过程, 显示原本的Mustache语法

<h3>{{message}}</h3>
<h3 v-pre>{{message}}</h3>
data() { 
   return {
      message: 'Hellow, Vue !!',
   }
}

在这里插入图片描述

3. v-cloak

v-cloak: 隐藏还未编译的Mustache标签, 可能因为网络延迟等其他问题导致Vue实例延迟创建或内部出错, 此时, 不应该展示还未编译的Mustache标签.
原理: v-cloak 是个自定义属性绑定到挂彩目标上, 在Vue实例创建成功后移除 v-cloak属性. 从而达到隐藏效果

<h3 v-cloak>{{message}}</h3>
<style>
   [v-cloak] {
      display: none;
   }
</style>

setTimeout(() => {
   const app = new Vue({
      el: '#app',
      data() {
         return {
            message: 'Hellow, Vue !!',
         }
      }
   })
}, 1000);

4. v-bind

v-bind: 主要用于属性动态绑定, v-bind:属性名 = “变量”, 可以缩写为 :属性名 = “变量”

<a :href="aHref">百度一下</a>
data() {
   return {
      aHref: 'https://www.baidu.com',
   }
}

v-bind动态绑定class(对象语法)

<style>
   .classB {
      color: red;
   }
</style>

<div id="app">
   <!-- class 和 :class 中的对象, 最终会合并在一起: calss = 'classA, classB'-->
   <!-- 对象语法: {类名1: boolean1, 类名2: boolean2, ...} boolean为true的对象才会被引用 -->
   <h3 class="classA" :class="{classB: isClassB, classC: isClassC}">{{message}}</h3>
   <button @click="changeClass">按钮</button>
</div>
const app = new Vue({
   el: '#app',
   data() {
      return {
         message: 'Hellow, Vue !!',
         isClassB: true,
         isClassC: false
      }
   }, 
   methods: {
      changeClass () {
         this.isClassB = !this.isClassB;
      }
   }
})

在这里插入图片描述
v-bind动态绑定style(对象语法)

<!-- :style="{key(属性名): vlaue(属性值变量  ), ...}" -->
<h3 :style="{font-szie: '50px'}">{{message}}</h3>
<h3 :style="{fontSzie: size}">{{message}}</h3>
data() {
	return {
		size: 50px
	}
}

5. v-on

v-on: 指令用于绑定事件监听器(原生 DOM 事件)。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句. 如: v-on:click、v-on:blur、v-on:keydown… 也可以缩写为: @click、@blur、@keydown…

  • 方法参数: 默认传递浏览器event事件
<button @click="handleClick">按钮</button>
methods: {
   handleClick(event) {
      console.log("handleClick click...", event)
   }
}

同时需要event对象 和 其他参数对象

<button @click="handleClick('张三', $evnet)">按钮</button>
methods: {
   handleClick(name, event) {
      console.log("handleClick click...", name, event)
   }
}
  • 修饰符
  1. .stop: 相当于调用 event.stopPropagation(), 阻止事件的冒泡方法,不让事件向document上蔓延,但是默认事件任然会执行
  2. .prevent: 相当于调用 event.preventDefault(), 取消事件的默认动作, 如 取消form表单中 type=‘submit’ 的按钮, 自动提交到action事件
  3. .{keyCode(键编码) | keyAlias(键别名)}:只当事件是从特定键触发时才触发回调, 如:
    <input @keyup.enter=“handleKeyup” /> 只监听Enter键按下事件
  4. .native: 监听组件根元素的原生事件, 注: 组件必须通过.native修饰符才可以监听DOM事件
  5. .once: 只触发一次回调

5. v-if、v-else-if、v-else

根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提出它的内容作为条件块。
推荐使用computed 来替换较为复杂的v-if、v-else-if、v-else 的指令


6. v-show

v-show: 根据表达式之真假值,切换元素的 display CSS property.

v-show与v-if 非常相似, 是控制一个元素是否显示, 但两者差异在于:

  • v-if: 当条件为false时, 不会渲染, 元素不存在于浏览器中的DOM
  • v-show: 当条件为false时, 只会给元素添加一个行内样式: display: none
<h3 v-if="false" id="if">Hello, Vue!!</h3>
<h3 v-show="false" id="show">Hello, Vue!!</h3>

在这里插入图片描述

7. v-for

v-for: 指令用于将数组或对象遍历循环显示渲染

  • 遍历普通数组
    <!-- item 代表 当先遍历项 -->
    <li v-for="item in arr">{{item}}</li>
    <!-- index 代表 当先遍历项的下标索引 -->
    <li v-for="(item, index) in arr">{{index}} {{item}}</li>
    
  • 遍历对象
    <!-- value 代表 当先遍历对象的value -->
    <li v-for="value in obj">{{value}}</li>
    <!-- key, value 分别代表 当先遍历对象的key, value -->
    <li v-for="(key, value) in obj">{{key}} {{value}}</li>
    ```
    

Vue官方推荐在使用v-for时, 给对应的元素或组件添加一个key属性, 是为了高效的更新虚拟DOM

Vue在重新渲染虚拟DOM时, 会采用就地复用策略: 会对已有的标签进行复用, 不会将整个DOM树删除然后重新创建, 如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素, 如图:
在这里插入图片描述
添加一个key唯一标识属性, vue(diff算法)可以正确的匹配识别此节点, 然后找到正确的位置插入到新的结点
在这里插入图片描述

8. v-model

v-model: 指令实现表单元素和数据的双向绑定

单向绑定: 把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新. 在Vue中可以使用mustache语法{{}} 或 v-bind 实现
双向绑定: 在单向绑定的基础上, 实现用户更新了View, Model中的数据也被自动更新. 在Vue中使用v-model指令实现

<input type="text" v-model="message" />
<h3>{{message}}</h3>

在这里插入图片描述
v-model原理: 是一个语法糖, 它本质包含两个操作

  • v-bind:value 指令绑定value属性
  • v-on:input 指令绑定<input>输入框的 input的事件
<input type="text" :value="message" @input="message = $event.target.value"/>
<h3>{{message}}</h3>

v-model 修饰符:

  • .lazy: v-model 默认是在input事件中同步输入框的数据的, lazy修饰符可以让数据在失去焦点或者回车才会更新
  • .number: 修饰符会将输入框输入的字符串类型转为数字类型
  • .trim: 修饰符会将输入框首尾空格过滤



(八) 计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护

<div id="example">
  {{ message.split('').reverse().join('') }} <!-- Hello-->
</div>

Computed计算属性: 可以对data中的属性进行逻辑计算, 且计算的值将被缓存. 只有当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值

<h3>{{fullName}}</h3> <!-- Lin Ken-->
data () {
	return {
		firstName: 'Lin',
		lastName: 'Ken'
	}
},
computed: {
	fullName: function() {
		return this.firstName + ' ' + this.lastName 
	}
}

Computed计算属性的get、set: 计算属性默认只有 get方法(只读属性), 上面的reversedMessage计算属性是简写方式, 只有提供了get方法. 为此, 可以提供set方法

data () {
	return {
		firstName: 'Lin',
		lastName: 'Ken'
	}
},
computed: {
	fullName: {
		set: function(newValue ) {
			// newValue : fullName set 的值
            console.log('fullName.set 方法被调用: ', newValue)

            // 赋值给data对象中的 firstName 和 lastName
            const nameArr = newValue.split(' ')
            this.firstName = nameArr[0]
            this.lastName = nameArr[1]
		},
		get: function() {
			return this.firstName + ' ' + this.lastName 
		}
	}
}


计算属性缓存 vs 方法:

<div>{{getFullName()}}, {{getFullName()}}, {{getFullName()}}, {{getFullName()}}</div>
<div>{{fullName}}, {{fullName}}, {{fullName}}, {{fullName}} </div>
data() {
   return {
      firstName: 'Lin',
      lastName: 'Ken'
   }
},
computed: {
   fullName: function () {
      console.log('fullName running...')
      return this.firstName + ' ' + this.lastName
   }
},
methods: {
   getFullName: function() {
      console.log('getFullName running...')
      return this.firstName + ' ' + this.lastName
   }
}

在这里插入图片描述
计算属性缓存和方法, 这两种方式的最终结果是完全相同的. 但方法每次调用都会执行, 而计算属性是基于它们的响应式依赖进行缓存的, 只在相关响应式依赖发生改变时它们才会重新求值



(九) 浅谈响应式原理

响应式是 Vue最独特的特性之一, 它可以监听Model数据层的数据变更操作, 并实时响应到对应的View视图中. 极大的将我们从繁琐的DOM操作中解放出来

Vue响应式原理离不开关键的两个点:

  • 如何监听data数据改变操作, 并在监听到这一操作中做了什么了?
  • 如何知道哪些组件需要动态响应更新? 即 如何记录哪些组件使用了data数据? (发布订阅者模式)

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。

Object.defineProperty(obj, ‘prop’, {descriptor}): 方法会直接在一个对象上定义一个新属性key,或者修改一个对象的现有属性,并返回此对象

  • obj: 要定义或修改属性的对象
  • prop: 要定义或修改属性的名称, 字符串类型
  • descriptor: 要定义或修改属性的描述符
    {
    	get() { return value }, // 当访问该属性时,会调用此函数。该函数的返回值会被用作属性的值
    	set(newValue) {} // 当属性值被修改时,会调用此函数. 
    }
    

get() 中实现发布订阅者模式: 当访问该属性时, 会调用此函数. Vue 在此方法中监听哪些组件使用了data数据. Vue对这些使用了data数据的组件分别创建一个 Watcher 观察者对象, 这些Watcher对象 订阅 Dep发布者对象(用来收集Watcher 、删除Watcher 和 向Watcher发送消息)

set() 中通知订阅者更新数据

// data对象
const obj = {
   name: 'zhangsan',
   age: 4,
   addr: 'BeJing'
}

Object.keys(obj).forEach(key => {
	let value = obj[key]
	Dep dep = new Dep() // 发布者对象: 一个key 对应 一个Dep对象
	
   Object.defineProperty(obj, key, {
      get() {
         // 监听获取data数据操作, 为使用data数据的组件创建Watcher对象, 并订阅(Dep收集Watcher)
         dep.push(new Watcher(obj, key, fn))
         return value
      },
      set(newValue) {
         this.value = newValue
         // 监听修改data数据操作, 通知订阅者更新数据
         dep.notify()
      },
   })
})

// 观察者对象
class Watcher {
	constructor(obj, key, fn) {
	}
	// 更新数据
	update() {
		// 获得新值
    	this.value = this.obj[this.key]
  	 	// 我们定义一个 fn 函数,这个函数用来模拟视图更新,调用它即代表更新视图
    	this.cb(this.value)
	}
}

// 发布者对象
class Dep {
	// 构造器方法, 初始化订阅者Watcher对象
	constructor() {
		this.subs = []; // 用来存放已订阅的Watcher对象的数组
	}
	
	// 在subs数组中添加一个订阅Watcher对象
	addSub(sub) {
		this.subs.push(sub)
	}
	
	// 向存储在subs数组中的Watcher发送消息
	notify() {
		this.subs.forEach(sub => {
			sub.update()
		})
	}
}

注: 上面的js代码是伪代码, 无法真正运行, 只是为了说明响应式的原理. 下图为Vue响应式原理图解

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值