6

Vue快速上门(1)-基础知识图文版 - 安木夕

 1 year ago
source link: https://www.cnblogs.com/anding/p/16906379.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
image.png

VUE家族系列:

  • Vue快速上门(1)-基础知识
  • Vue快速上门(2)-模板语法
  • Vue快速上门(3)-组件与复用

01、基本概念

1.1、先了解下MVVM

VUE是基于MVVM思想实现的,❓那什么是MVVM呢?—— MVVM,是Model-View-ViewModel的缩写,是一种软件架构模式。其核心思想就是分离视图、数据、逻辑,VUE框架解决了数据Model到视图View的双向绑定,我们只关注业务逻辑ViewModel即可,极大的提高的编程效率。

  • M:Model,数据模型,通常来自后端服务、数据库。
  • V:View,视图,就是HTML页面,Dom。
  • VM:ViewModel,视图模型,连接模型和视图,实现数据和视图的相互绑定。包含了视图状态、行为,如页面展示的内容(逻辑)、页面响应事件、数据获取更新等,都封装在 ViewModel 中。
image

VUE实现双向绑定的基本原理:

🔸Dom Listeners:通过对DOM元素(表单输入元素)的值变更监听,同步视图变化的数据到模型。

🔸Data Bindings:通过对模型数据拦截监听,监测数据变化进行更新视图。原理是基于基于ES5的特性Object.defineProperty(obj, propertyName, descriptor),通过其get、set访问器来监听数据变更,这也是Vue不支持IE8的原因。

image.png

🌰一个双向绑定的简单示例:

<div id="app"> <h2>{{message}}--{{message}}</h2></div><form action="#"> <input type="text" v-model="message"></form><script> //定义一个数据ViewModel,数据实际存储在$data中。 let app = { $data: {} } //通过defineProperty的get、set拦截,检测数据变化》更新数据 Object.defineProperty(app, "message", { get() { return this.$data.message; }, set(value) { this.$data.message = value; updateView(this); //更新视图 } }) //保存模板、绑定了数据的表单元素 let template = document.querySelector("#app").innerHTML; let vinputs = document.querySelectorAll("input[v-model]"); //更新视图 function updateView(data) { const html = template.replace(/{{(\w+)}}/g, (match, $1) => { return data[$1] || ""; }) document.querySelector("#app").innerHTML = html; //更新表单元素的数据绑定 vinputs.forEach(el => { el.value = data[el.getAttribute('v-model')]; }); } //监听输入表单的值变更 vinputs.forEach(el => { el.addEventListener("input", function (e) { app[e.target.getAttribute('v-model')] = e.target.value; }); }); //赋值 app.message = "hello";</script>

1.gif

» 基本过程如图:

image

1.2、虚拟DOM

直接操作DOM,DOM频繁变动会使得页面不停的布局、渲染,是很消耗性能的,虚拟DOM就是来解决这个问题的。虚拟DOM 就是先在内存中构建一个虚拟DOM结构(JS对象表示),批量操作完成后再一次性的更新到浏览器DOM树上。VUE中的虚拟DOM操作思路也是如此,只是为了更高效,实际要稍微复杂一点点。

  • ❶ 用JS 对象模拟 虚拟DOM树
  • ❷ 比较DOM树差异(修改、删除、新增...)
  • ❸ 将差异更新到真正的DOM树中。

1.3、VUE是什么?

中文官网https://cn.vuejs.org | Vue3版本手册 | Vue2版本手册

Vue(读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架,同他周边的生态共同构成了一个灵活的、渐进式的前端框架。

  • 2013年底作为尤雨溪个人实验项目开始开发。
  • 2014年公开发布。
  • 2016年10月发布2.0版本。
  • 2020年发布3.0版本。

🔸核心特性

  • 响应式数据驱动(双向绑定),数据>视图(数据监听),视图>数据(事件监听)。
  • 组件化:组件化的应用构建。
  • 申明式渲染:采用模板语法申明式的将数据渲染到DOM。
  • 轻量级框架:只关注视图层,是一个构建数据的视图集合,压缩后30+K;
  • 高效率:基于虚拟化Dom技术,DOM操作效率很高。

02、准备开始

2.1、安装使用Vue2

  • 通过<script>标签直接引用vue.js
<!-- 开发环境版本,包含了有帮助的命令行警告 --><script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <!-- 生产环境版本,优化了尺寸和速度 --><script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  • 通过 vue-cli 脚手架搭建vue的开发框架。

2.2、命名规范

前端无非就是HTML、CSS、JS,坑爹的是他们的命名规范并不相同。前端常用的两种命名方式:

  • 小驼峰命名(lowerCamelCase):首字母小写,后面的单词首字母大写:userName
  • kebab-case命名:烤串命名法(kebab /kɪˈbɑːb/ 烤肉串),都小写,单词之间用短线连接:user-name
类型 命名方式 说明
HTML kebab-case 按照W3C规范,HTMl中(包括标签名、attribute)不区分大小写,HTML解析时都会转换为小写,支持字母数字、下划线_、短线-
自定义名称一般都采用烤串命名,加短线主要是避免和HTML原生冲突(包括以后新的名称)
CSS kebab-case 字母开头,字母数字、下划线_、短线-,一般都采用烤串命名
JavaScript lowerCamelCase 字母开头,字母数字、下划线_,不支持短线-(作为对象属性得引起来)。还有些细分:
🔸 类、构造函数采用大驼峰命名
🔸 常量采用全大写+下划线_

Vue中的命名就有一点特殊了(混合),默认是JavaScript的小驼峰命名,但当会用于Dom时,就要采用烤串命名了,比如:

  • 组件的id:作为元素标签名
  • props参数:作为元素attribute
  • 自定义事件名:作为元素attribute
  • 自定义指令(包括指令参数、修饰符):作为元素attribute

📢自动转换:参数props、组件id可以采用小驼峰命名,Vue会自动转换。如果使用字符模板,就不归浏览器管了,就没有命名的限制问题了!

Vue中其他命名规范:

  • 组件名,大驼峰,首字母大写。

2.3、开发插件

  • Vue Devtools:浏览器调试插件 ,在浏览器的调试面板中使用,推荐Edge浏览器安装。
  • Vetur:VSCode插件,Vue开发必备⭐,核心功能:
    • ✅代码高亮:语法、语义代码高亮。
    • ✅代码片段:常用代码片段的提示输入,以及自定义代码片段。
    • ✅代码检查和格式化。
    • ✅自定义代码模板。
  • Volar,Vue3版本的vetur

03、Vue基础结构

3.1、创建一个Vue实例

每一个Vue组件都是通过Vue()函数创建的一个Vue实例,他就是对应页面Dom的 ViewModel

<div id="app2"> <h2>{{title}}</h2> <div> <span v-text="user.name"></span>---<span v-text="age"></span> <button v-on:click="showUpperCase">提交</button> </div></div><script> let vm = new Vue({ el: "#app2", data: { user: { name: "sam", birthday: '2000-12-1'}, title: "hello world!" }, computed: { age() { return (new Date().getFullYear() - new Date(this.user.birthday).getFullYear()); } }, methods: { showUpperCase: function (e) { this.title = this.title.toUpperCase(); }, } })</script>

Vue()的构造函数参数,就是Vue的选项对象,提供了Vue实例的各项配置,常用配置:

  • el:绑定视图Dom元素,通过app.$el访问。
  • data:数据模型,会被Vue递归实现数据响应(数据监听),通过Vue对象的get、set访问器访问数据,数据实际都存放在vm.$data上。这里的数据都是响应式的,支持数据双向绑定,数据变化会自动更新同步。
  • computed:计算属性(支持逻辑的属性),值是一个(getter)函数,使用同data。会基于其依赖的响应式属性进行缓存:响应式属性变更会触发更新,缓存计算值,重复调用(绑定)复用结果。
  • methods:方法,实现各种业务逻辑,常用于绑定事件

3.2、Vue选项🔖

💠Vue的构造函数参数=Vue选项:

Vue选项 描述
💠选项-数据
data Vue的数据对象,会被递归实现propert响应,vm.$data访问原始数据。
computed 计算属性,值是一个(getter)函数,使用同data。会基于其依赖的响应式属性进行缓存:响应式属性变更会触发更新;缓存计算值,重复调用(绑定)复用结果。
methods 方法,定义方法的地方,可以绑定事件、表达式调用、访问。
watch 对property的监听回调,当属性值变更时触发。也可通过实例方法添加vm.$watch(pName,func)
props 定义组件的参数,作为组件特性使用:Array<string> | Objectprops: ['item','title']
propsData 创建实例时传递 props,便于测试。{ [key: string]: any }
💠选项-Dom
el Vue的DOM根元素,值为一个已存在Dom,(id)选择器或元素实例。
template 字符串模板,优先于el元素内容模板,template: <h3>{{user.name}}</h3>`
render 渲染函数,优先于template
renderError render的替身, render 函数错误时替补
💠选项-资源
directives 指令,注册局部指令,directives: {id:{}}
filters 过滤器,filters{id:func(value,...arg)}
components 注册局部组件,components: { 'todo-box': com_todoBox }
💠选项-组合
parent 指定父级实例
mixins 混入(复用)选项,Array<Object>mixins:[cmixin]
extends 继承另一个组件,复用代码。extends: CompA
provide / inject 依赖注入,父类向子类发红包,在父级定一个provider: {key:obj},后代inject :key,获得父类的红包。用于一些特定对象的注入,后代需要才接收、可跨级。
💠选项-其他
inheritAttrs bool值-默认true,是否继承组件上定义的(非Prop)特性Attribute,不会影响class、style绑定
model 修改v-model绑定的Prop和event,对于文本input默认v-model绑定的是valueinput事件。

computed计算属性

计算属性computed选项中,用于一些复杂逻辑数据的计算。值为(getter)函数,使用同data作为vm的属性用。

主要特点:会基于其依赖的响应式属性进行缓存:响应式属性变更会触发更新,缓存计算值,重复调用(绑定)复用结果。如果用方法methods,每次有任何更新都会被调用。

<div id="app4"> <p>age:{{age}},{{age}},{{getAge()}},{{getAge()}}</p></div><script> let app4 = new Vue({ el: "#app4", data: { user: { name: "sam", birthday: "2000-1-1" } }, computed: { age() { //多次调用缓存属性值 console.log("computed.age"); //computed.age return new Date().getFullYear() - new Date(this.user.birthday).getFullYear(); } }, methods: { getAge() { //多次调用会重复执行 console.log("methods.getAge"); //methods.getAge methods.getAge return new Date().getFullYear() - new Date(this.user.birthday).getFullYear(); } } })</script>

计算属性默认是没有setter的,不过也可以实现setter。

computed: { age: { get: function () { }, set: function (value) { }, }},

watch监听器

针对data中的响应式属性的值变更监听,也可以监听计算属性,存放在watch选项里,用于实现值变更的一些自定义业务逻辑。不需要返回值,支持异步处理,computed计算属性是必须要返回值的,异步就没有意义了。

基础语法属性名: function (newValue, oldValue),更多参考 vm.$watch API

watch: { question: function (newValue) { //当用户问题变更时触发 this.answer = "正在思考..."; // ajax请求搜索答案,这里应该用防抖函数处理一下,避免频繁无意义的调用。 fetchJsonp("https://www.baidu.com/s?wd=" + newValue) .then(res => res.text()) .then(text => { console.log(text); this.answer = text; }); //跨域请求失败 }, //或者对象的形式 question:{deep:true,handler(newValue,oldValue){}}}
  • 属性名可以支持链式属性路径"user.age":function(){ },不支持数组内部对象。
  • 参数{deep:true}可以深度监听对象下面的所有属性,但oldValue可能不准确。{immediate: true}可以立即触发一次监听。

3.3、Vue选项-实例生命周期

Vue实例从①创建阶段、到②运行阶段、再到③销毁终结的过程,就是Vue辉煌的一生。在这个过程中Vue提供了一些钩子函数,这些函数都没有参数,this指向组件自身。

Vue选项-生命周期钩子
beforeCreate 创建前:各项属性配置都还不可用,几乎不能干什么
created 创建后:实例化完成后同步调用。数据、事件、计算属性已完成,还未挂载模板,可发起ajax请求
beforeMount 挂载el前:模板已完成编译(各项指令都解析完成了),但还未加入到页面Dom中
mounted 挂载后-完成渲染:实例被挂载后调用,vm.$el已创建,浏览器Dom完成渲染,用户看到正式的页面了
beforeUpdate 更新前:数据发生改变后(数据最新),虚拟DOM 更新之前(页面未更新)
updated 更新后:页面Dom已更新完成,数据和页面都是最新的,首次渲染不会触发
beforeDestroy 实例销毁之前调用,此时组件还是正常的。
destroyed 实例销毁后调用,组件已销毁并从Dom中移除。
activated 组件激活/显示,被 <keep-alive> 缓存的组件激活时调用
deactivated 组件失活/隐藏,被 <keep-alive> 缓存的组件失活时调用
errorCaptured 捕获后代组件的错误

» 画个图:VUE生命周期(ProcessOn版本

image

📢注意:不要在选项 property 或回调上使用箭头函数,箭头函数没有this,会导致默认的this(vm)丢失。

3.4、Vue实例🔖

💠实例属性 描述
$data vue对象的data实际存储的数据,vue代理了他的数据访问
$el el挂载的视图Dom元素
$options Vue()实例化的选项参数
$refs 通过过ref attribute 注册的所有 DOM 元素和组件实例的一个对象,this.$refs.header
$parent 父实例,根实例的 $parentnull
$root 组建树的根实例,根实例的 $root 为自己
$children 子组件示例数组Array<Vue instance>
$slots 插槽分发的内容,{ [name: string]: ?Array<VNode> }
$scopedSlots 作用域插槽 { [name: string]: props => Array<VNode> | undefined }
$listeners 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器
$props 组件定义的参数列表
$attrs 父作用域中的非Prop的Attribute特性(不含class、style)
$isServer 是否运行于服务器,服务端渲染
💠实例方法
$watch( expOrFn, callback, [options] ) 添加属性变更监听器vm.$watch("title", function (val, old) {});
$set( target, proName/index, value ) 添加响应式的property,并更新视图。用于后续增加的属性,同Vue.set()
$delete( target, proName/index ) 删除对象的 property,同Vue.delete()
💠实例事件
$on( eventName, callback ) 添加一个事件监听,监听当前实例上的自定义事件,事件可以由 vm.$emit 触发
$once( eventName, callback ) 添加一个事件监听,但是只触发一次,触发后被移除。
$off( [eventName, callback] ) 移除自定义事件监听器
$emit( eventName, […args] ) 触发当前实例上的事件,参数eventName为事件名称,注意采用小写命名方式
💠实例方法-生命周期
$mount( [elementOrSelector] ) vue实例挂载一个Dom元素,元素或CSS选择器
$forceUpdate() 强制更新渲染
$nextTick( [callback] ) Vue.nextTick
$destroy() 完全销毁一个实例

Vue静态API

Vue全局静态属性/方法 描述
Vue.extend( options ) 创建一个Vue“子类”(不是实例),选项的data必须是函数,避免组件实例共享数据
Vue.nextTick( [callback, context] ) Dom更新后立即调用回调,常用于手动操作Dom(需等Dom更新完),他返回的是一个Promise
🔸Vue更新都是异步的,类似JS的事件循环队列,不会立即执行,便于去重提高性能
Vue.set( target, proName/index, value ) 向响应式对象中添加一个响应式 property,并触发视图更新。可用于强制更新视图
Vue.delete( target, proName/index ) 删除对象的 property,会触发更新
Vue.directive( id, [definition] ) 注册或获取全局指令
Vue.filter( id, [definition] ) 注册或获取全局过滤器
Vue.component( id, [definition] ) 注册或获取全局组件
Vue.use( plugin ) 安装 Vue.js 插件,为Vue添加一些全局的功能,如 vue-router
Vue.mixin( mixin ) 全局注册一个混入,小心使用,会影响后面所有的Vue实例。
Vue.compile( template ) 将一个模板字符串编译成 render 函数
Vue.observable( object ) 让一个对象可响应
Vue.version 版本号,Vue.version //'2.7.14'

©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK