Vue详细介绍及使用

一、Vue定义及简介

1、Vue定义

    关于Vue简介,百度百科给出的解释是:Vue.js是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。

    Vue.js 是一个提供了 MVVM 风格双向数据绑定的 Javascript 库(无依赖别的js库,直接引入一个js文件就可以使用,跟jquery差不多),专注于View 层。它的核心是 MVVM 中的 VM,也就是 ViewModel。 ViewModel负责连接 View 和 Model,保证视图和数据的一致性,这种轻量级的架构让前端开发更加高效、便捷。

2、Vue背景简介

2.1、Vue诞生的背景

    从历史的潮流来说,人们从之前的:原生JS -> Jquery之类的类库 -> 前端模板引擎 ,他们都有一个共同的特点需要我们去操作dom元素。近几年来,得益于手机设备的普及和性能的提升,移动端的web需求大量增加,产生了一种叫webapp的东西,也就是移动端的网页应用。为了更好满足当前移动webapp项目的开发需求,MVVM框架诞生,而Vue便是这样的一种框架。那么什么是Vue?

    官网有一句对它的介绍:通过尽可能简单的API实现响应的数据绑定和组合的视图组件。Vue的核心主要包括下面两块:

    Vue的数据驱动:数据改变驱动了视图的自动更新,传统的做法你得手动改变DOM来改变视图,vuejs只需要改变数据,就会自动改变视图;

    视图组件化:把整一个网页的拆分成一个个区块,每个区块我们可以看作成一个组件。网页由多个组件拼接或者嵌套组成(可维护、可重用)。

2.2、MVVM框架的发展

    MVC(View Model Controller )模式:

    MVC框架最早出现在Java领域,在经典的MVC模式中,是用户通过Controller来操作Model以达到View的变化。MVC 即 Model-View-Controller 的缩写,就是 模型—视图—控制器,也就是说一个标准的Web 应用程式是由这三部分组成的:

    View :用来把数据以某种方式呈现给用户;

    Model :其实就是数据;

    Controller :接收并处理来自用户的请求,并将 Model 返回给用户;

    MVP(Model View Presenter)模式:

    而后的MVP模式(MVC模式的演变)逻辑层在Presenter里实现,而且Presenter与具体的View 是没有直接关联的,而是通过定好的接口进行交互(在MVC中View会直接从Model中读取数据而不是通过 Controller)。 View 与 Model 不发生联系,都通过 Presenter 传递。

    在HTML5 还未火起来的那些年,MVC 作为Web 应用的最佳实践是很OK 的,这是因为 Web 应用的View 层相对来说比较简单,前端所需要的数据在后端基本上都可以处理好,View 层主要是做一下展示,那时候提倡的是 Controller 来处理复杂的业务逻辑,所以View 层相对来说比较轻量,就是所谓的瘦客户端思想  

    相对 HTML4,HTML5 最大的亮点是它为移动设备提供了一些非常有用的功能,使得 HTML5 具备了开发App的能力, HTML5开发App 最大的好处就是跨平台、快速迭代和上线,节省人力成本和提高效率,因此很多企业开始对传统的App进行改造,逐渐用H5代替Native,到2015年的时候,市面上大多数App 或多或少嵌入都了H5 的页面。既然要用H5 来构建 App, 那View 层所做的事,就不仅仅是简单的数据展示了,它不仅要管理复杂的数据状态,还要处理移动设备上各种操作行为等等。因此,前端也需要工程化,也需要一个类似于MVC 的框架来管理这些复杂的逻辑,使开发更加高效。

    注:Native(使用原生制作APP,即在基于目前的智能手机的操作系统(如安卓android、苹果IOS,另外还有 (windows phone) 的基础上,使用相应平台支持的开发工具和语言 ( 比如 iOS 平台支持 Xcode 和 Objective-C,安平台支持 Eclipse 和 Java) 编写的第三方移动应用程序,简称原生APP。)

    但实际上,随着H5 的不断发展,人们更希望使用H5 开发的应用能和Native 媲美,或者接近于原生App 的体验效果:

    1)开发者在代码中大量调用相同的 DOM API,处理繁琐 ,操作冗余,使得代码难以维护。

 2)大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。

 3)当 Model 频繁发生变化,开发者需要主动更新到View ;当用户的操作导致 Model 发生变化,开发者同样需要将变化的数据同步到Model 中,这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。

    MVVM(Model View ViewModel) 模式:

    其实,早期jquery 的出现就是为了前端能更简洁的操作DOM 而设计的,但它只解决了第一个问题,另外两个问题始终伴随着前端一直存在。MVVM 的出现,完美解决了以上三个问题MVVM 由 Model、View、ViewModel 三部分构成,Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。

    在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理(用到这种的有来自Google的AngularJS,还有Vue.js、Knockout、Ember.js)。

3、主流前端框架/库简介

    目前的流行前端框架/库有:VueReactAngular(三大霸主)以及BootstrapAPICloudjQuery等;(jQuery、React为库)

    Vue毫无疑问是当前最流行最火爆的前端框架之一。vue作为渐进式前端框架,由当时的谷歌工程师尤雨溪大神业余时间所写,一放到github就引起流行,github上点赞数百万。vue现在几乎作为前端必备框架,特点高效,灵活,稳定,功能强大,代码少,运行速度快,整个文件只有200多K。Vue所关注的核心是MVC模式中的视图层,同时,它也能方便地获取数据更新,并通过组件内部特定的方法实现视图与模型的交互。vue做了必须的事,又不会做职责之外的事。做为前端,不懂vue是不行了。

    React是Facebook在2013年开源的前端框架,由于 React的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。也就是说同一组人只需要写一次 UI ,就能同时运行在服务器、浏览器和手机。开发效率高,事半功倍。

    AngularJS诞生于2009年,由Misko Hevery 等人创建,是为了克服HTML在构建应用上的不足而设计的。后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVC(Model–view–controller)、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。2016年angular2正式被发布,在Anguar2.0之前的版本都叫做AngularJS(Angular2不是从Angular1升级过来的,Angular2是重写的)。

    jQuery是一个快速、简洁的JavaScript库,是继Prototype之后又一个优秀的JavaScript代码库。jQuery设计的宗旨是写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。代码十分精炼,代码量小,速度快,犀利。使用量非常大。

    Bootstrap(react是Facebook开发的,那么做为Facebook的竞争对手,Twitter公司也不甘示弱,开源了Bootstrap。)是由美国Twitter公司的设计师Mark Otto和Jacob Thornton合作基于HTML、CSS、JavaScript 开发的简洁、直观、强悍的前端开发框架,使得 Web 开发更加快捷。Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成。Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目。国内一些移动开发者较为熟悉的框架,如WeX5前端开源框架等,也是基于Bootstrap源码进行性能优化而来。Bootstrap 能给你的 Web 开发提供了时尚的版式,表单,buttons,表格,网格系统等等。

    apicloud(包括api.js和api.css)专门为移动端APP开发而设计的框架,适应不同的移动设备,而且可以和其他框架一起引入项目中使用,非常灵活,优秀。

注:框架和库的区别

    库(插件):是一种封装好的特定方法集合,对项目的侵入性较小,提供给开发者使用,控制权在使用者手中,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
    框架:是一套架构,会基于自身特点向用户提供一套相当完整的解决方案,而且控制权在框架本身;对项目的侵入性较大,使用者要按照框架所规定的某种特定规范进行开发,项目如果需要更换框架,则需要重新架构整个项目。

4、Vue与AngularJS、React区别

4.1、与AngularJS的区别

    相同点:
    都支持指令:内置指令和自定义指令。
    都支持过滤器:内置过滤器和自定义过滤器。
    都支持双向数据绑定。
    都不支持低端浏览器。

    不同点:
    AngularJS的学习成本高,比如增加了Dependency Injection特性,而Vue.js本身提供的API都比较简单、直观。
    在性能上,AngularJS依赖对数据做脏检查,所以Watcher越多越慢。
    Vue.js使用基于依赖追踪的观察并且使用异步队列更新。所有的数据都是独立触发的。
    对于庞大的应用来说,这个优化差异还是比较明显的。

4.2、与React的区别

    相同点:
    React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,两者都需要编译后使用。
    中心思想相同:一切都是组件,组件实例之间可以嵌套。
    都提供合理的钩子函数,可以让开发者定制化地去处理需求。
    都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载。
    在组件开发中都支持mixins的特性。
    不同点:
    React依赖Virtual DOM,而Vue.js使用的是DOM模板。React采用的Virtual DOM会对渲染出来的结果做脏检查。
    Vue.js在模板中提供了指令,过滤器等,可以非常方便,快捷地操作DOM。

5、Vue特性

    1) 轻量级的框架

        Vue.js 能够自动追踪依赖的模板表达式和计算属性,提供 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API

    2) 双向数据绑定

        声明式渲染是数据双向绑定的主要体现,同样也是 Vue.js 的核心,它允许采用简洁的模板语法将数据声明式渲染整合进 DOM。

    3) 指令

        Vue.js 与页面进行交互,主要就是通过内置指令来完成的,指令的作用是当其表达式的值改变时相应地将某些行为应用到 DOM 上。

    4) 组件化

        组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。

        在 Vue 中,父子组件通过 props 传递通信,从父向子单向传递。子组件与父组件通信,通过触发事件通知父组件改变数据。这样就形成了一个基本的父子通信模式。

        在开发中组件和 HTML、JavaScript 等有非常紧密的关系时,可以根据实际的需要自定义组件,使开发变得更加便利,可大量减少代码编写量。

        组件还支持热重载(hotreload)。当我们做了修改时,不会刷新页面,只是对组件本身进行立刻重载,不会影响整个应用当前的状态。CSS 也支持热重载。

    5) 客户端路由

        Vue-router 是 Vue.js 官方的路由插件,与 Vue.js 深度集成,用于构建单页面应用。Vue 单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来,传统的页面是通过超链接实现页面的切换和跳转的。

    6) 状态管理

        状态管理实际就是一个单向的数据流,State 驱动 View 的渲染,而用户对 View 进行操作产生 Action,使 State 产生变化,从而使 View 重新渲染,形成一个单独的组件。

    注:Vue必须在ES5版本以上的环境下使用,一些不支持ES5的旧浏览器中无法运行Vue。

6、Vue发展历史

时间事件
2013年在 Google 工作的尤雨溪,受到 Angular 的启发,开发出了一款轻量框架,最初命名为 Seed 。
2013年12月更名为 Vue,图标颜色是代表勃勃生机的绿色,版本号是 0.6.0。
2014年01月24日Vue 正式对外发布,版本号是 0.8.0。
2014年02月25日0.9.0 发布,有了自己的代号:Animatrix,此后,重要的版本都会有自己的代号。
2015年06月13日0.12.0,代号Dragon Ball,Laravel 社区(一款流行的 PHP 框架的社区)首次使用 Vue,Vue 在 JS 社区也打响了知名度。
2015年10月26日1.0.0 Evangelion 是 Vue 历史上的第一个里程碑。同年,vue-router、vuex、vue-cli 相继发布,标志着 Vue从一个视图层库发展为一个渐进式框架。
2016年10月01日2.0.0 是第二个重要的里程碑,它吸收了 React 的虚拟 Dom 方案,还支持服务端渲染。自从Vue 2.0 发布之后,Vue 就成了前端领域的热门话题。
2019年02月05日Vue 发布了 2.6.0 ,这是一个承前启后的版本,在它之后,将推出 3.0.0。
2019年12月05日在万众期待中,尤雨溪公布了 Vue 3 源代码,目前 Vue 3 处于 Alpha 版本。
2020年09月18日Vue发布了3.0.0版本(https://github.com/vuejs/vue-next/releases)中。但是目前官网上只有vue3.x-beta (测试版API)

二、Vue安装及环境配置

    在搭建vue的开发环境之前,一定一定要先下载node.js,vue的运行是要依赖于node的npm的包管理工具来实现,node可以在官网或者中文网里面下载。官网地址:https://nodejs.org/en/download/

    备注:windows7 环境下只能使用Node.js 12.x及以下版本,官网下载地址:https://nodejs.org/en/download/releases/

1、windows下搭建vue开发环境

    1)在官网下载好需要的版本,我下载的版本为:node-v12.20.0-x64.msi,下载完成安装,安装完成在CMD中查看是否安装成功;

    

    2)设置缓存文件夹

npm config set cache "D:\program files\nodejs\node_cache"

    设置全局模块存放路径(之后用命令npm install XXX -g安装以后模块就在D:\program files\nodejs\node_global里)

npm config set prefix "D:\program files\nodejs\node_global"

    3)高版本的nmp(Node包管理器:Node Package Manager,服务器在国外)是自带的,由于在国内使用npm是非常慢的,推荐使用淘宝npm镜像。在cmd中输入安装命令:

#安装命令
npm install -g cnpm --registry=https://registry.npm.taobao.org#删除命令
npm uninstall -g cnpm --registry=https://registry.npm.taobao.org

   4)设置环境变量

    (设置环境变量可以使得住任意目录下都可以使用cnpm、vue等命令,而不需要输入全路径)

    在PATH中新增:D:\program files\nodejs\node_global(新增完成后重新打开CMD)

    5)安装Vue

#安装Vue
cnpm install vue -g

    6)安装vue命令行工具,即vue-cli 脚手架

    如果只是简单的写几个Vue的Demo程序,那么你不需要Vue-Cli。Cli是(Command-Line Interface,翻译为命令行界面,俗称脚手架,他是官方发布的Vue.js项目脚手架,使用Vue-cli可以快速搭建Vue开发环境以及对应的webpack配置)

    7)创建新项目:webpack-simple / webpack

     打开开始菜单,输入 CMD,或使用快捷键 win+R,输入 CMD,敲回车,弹出命令提示符。打开你将要新建的项目目录;

     vue init webpack-simple这样的方式适合小项目,vue init webpack这样的方式适合中大型项目;

     输入:vue init webpack-simple vue-test    (注:vue init webpack-simple+项目名称  名称不能有大写字母)

    

    输入:vue init webpack vue-test-big

        8)项目生成情况

vue init webpack-simple vue-test  生成目录:

vue init webpack vue-test-big 生成目录:

目录/文件说明
build

最终发布代码的存放位置

config配置目录,包括端口号等
node_modules这是执行npm install后产生的,里面包含了Node.js和npm依赖文件以及后续安装的第三方组件或者功能
src我们要开发的目录,用于存放页面相关的文件,基本上要做的事情都在这个目录里面
src\assets图片文件目录,如:logo
src\components存放了一个组件文件
src\router项目的路由
src\App.vue主文件,项目的入口文件,可以直接将组件写在这里,而不使用components目录
src\amin.js项目的核心文件
static一般用于存放静态资源,如:图片、字体等
.babelrc用来设置转码的规则和插件,一般情况下不需要设置

    9)安装工程依赖模块

    vue-test:

#切换到当前目前,一定切换进来:
D:\vueTest>cd vue-test#运行cnpm install,下载当前项目所依赖的包,在目录下会生成node_modules
D:\vueTest\vue-test>cnpm install#运行cnpm run dev,启动当前的项目
D:\vueTest\vue-test>cnpm run dev

  第一个简单版的vue的项目,就好了打开链接:http://localhost:8080/

  vue-test-big:

#切换到项目目录
D:\vueTest>cd vue-test-big#运行cnpm run dev,启动当前项目
D:\vueTest\vue-test-big>cnpm run dev

    10)使用Visual Studio Code来开发Vue程序(当然也可以使用HBuilderX)

    a)导入项目:File->Open Folder->vue-test-big  

    b)打开集成终端(open integrated terminal):快捷键(Ctrl+`

    c)运行命令(cnpm run dev)

    d)打开页面(http://localhost:8080/)

    但是我们看到的是http://localhost:8080/#/,关于生成的URL地址http://localhost:8080/#/后面的/#/,是路由的hash和history之分,默认是hash模式,会有#,把mode改成history:

    vue 项目往往会搭配 vue-router 官方路由管理器,它和 vue.js 的核心深度集成,让构建单页面应用变得易如反掌。vue-router 默认为 hash 模式,使用 URL 的 hash 来模拟一个完整的 URL,所以当 URL 改变时,页面不会重新加载,只是根据 hash 来更换显示对应的组件,这就是所谓的单页面应用。

//只需要在index.js加上一行mode: 'history',
export default new Router({// 路由模式:hash(默认),history模式mode: 'history',//路由规则routes:[{path:'/',name:'index',component:'Index'}],})

2、如何使用Vue.js

    1)直接通过script加载CDN文件或者直接加载本地vue.js文件

    2)npm(vue- cli)基于npm管理依赖使用nmp(vue- cli)来安装Vue

    即前面的Vue环境搭建,不过官方文档上说:我们不推荐新手直接使用 vue- cli ,尤其是在你还不熟悉基于 Node.js 的构建工具时。

二、Vue基础知识

1、Vue学习内容    

    学习Vue不要在想着怎么操作DOM,而是想着如何操作数据。那么Vue做了什么,我们要学习什么,先来一张总结性质的思维导图(此图为Vue2.x版本):

2、数据绑定

    数据绑定是将数据和视图关联,当数据发生变化是,可以自定更新视图。

2.1、语法-插值:{{msg|表达式}}

    文本插值是最基本的形式,使用双大括号{{}},类似于Mustache(Mustache是一个logic-less(轻逻辑)模板解析引擎,它的优势在于可以应用在Javascript、PHP、Python、Perl等多种编程语言中。)

    {{msg|表达式}}标签将会被替换为 data 对象上对应的 msg 属性的值,也支持写入表达式(表达式是各种数值、变量、运算符的综合体)。

    注意:Mustache 语法不能作用在 HTML 元素的属性上。

2.2、语法-使用指令插值

      指令是带有v-前缀的特殊特性,其值限定为绑定表达式,也就是JavaScript表达式和过滤器。指令的作用是当表达式值发生变化是,将这个变化也反映到DOM上。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><!--使用CDN:CDN的全称是Content Delivery Network,即内容分发网络。	CDN是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容--><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><!--直接引用本地<script src="js/vue.js"></script>--></head><body><div id="app" v-if="show"><h4>----------------Vue版本号:{{myversion}}--------------</h4>基本插值:{{msg}}<br />表达式:{{flag?1:0}}</div></body><script>new Vue({el:"#app",data:{myversion:Vue.version,msg:"Hello World",flag:true,show:true //改成false将会隐藏}});</script>
</html>

3、分隔符

    Vue.js中数据绑定的语法被涉及为可配置的。如果不习惯Mustache风格的语法,则可以自己设置。在Vue 1.x 中它定义在(src/config.js源码)里,但是在Vue2.x后有所改变。

    全局使用:Vue.options.delimiters = ['语法格式'];

    实例选项定义:delimiters:['语法格式’]

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">#{msg}</div></body><script>//Vue 1.x中的全局设置方式
//		Vue.config.delimiters = ["${', '}"];//Vue 2.x中的全局设置方式Vue.options.delimiters = ['${', '}'];var vm = new Vue({//在实例中使用选项设置的方式delimiters:['#{','}'],el:"#app",data:{msg:"Hello World"}});</script>
</html>

三、Vue指令

    前面的案例中我们已经接触到了一个指令v-show,这种带有前缀 v-的指令,用于表示它们是 Vue 提供的特殊特性。在Vue中还定义了许多这种的内置指令。

1、插入数据指令(v-text、v-html )

1.1、v-text

    预期string

    详细:更新元素的 textContent。如果要更新部分的 textContent,需要使用 {{ Mustache }} 插值。

1.2、v-html 

    预期string

    详细:更新元素的 innerHTML

    注意:内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。如果试图使用 v-html 组合模板,可以重新考虑是否通过使用组件来替代。

示例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><span v-text="msg"></span><br /><!-- 和下面的一样,如果是只更新标签里的部分内容,则使用下面这种方式 --><span>{{msg}}</span><div v-html="html"></div></div></body><script>var vm = new Vue({el:"#app",data:{msg:"Hello World",html:"<h4>我是v-html指令</h4>"}});</script>
</html>

2、条件渲染指令(v-show、v-if、v-else、v-else-if)

2.1、v-show

    预期any

    用法:根据表达式之真假值,切换元素的 display CSS property。当条件变化时该指令触发过渡效果。

2.2、v-if

    预期any

    用法:根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提出它的内容作为条件块。当条件变化时该指令触发过渡效果。

    注意:当和 v-if 一起使用时,v-for 的优先级比 v-if 更高。v-show是css切换,v-if是完整的销毁和重新创建使用频繁切换时用v-show,运行时较少改变时用v-if

2.3、v-else

    用法:不需要表达式,为 v-if 或者 v-else-if 添加“else 块”。

    限制:前一兄弟元素必须有 v-if 或 v-else-if

2.4、 v-else-if

    类型any

    用法:表示 v-if 的“else if 块”。可以链式调用。

    限制:前一兄弟元素必须有 v-if 或 v-else-if。(2.1.0 新增)

示例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><!--指令:v-show--><span v-show="show">我是v-show</span><br /><!--指令:v-if--><div v-if="Math.random() > 0.5">你看见的是:v-if</div><!--指令:v-else--><div v-else>你看见的是:v-else</div><!--指令:v-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></div></body><script>var vm = new Vue({el:"#app",data:{show:false,type:"C"}});</script>
</html>

3、循环渲染指令(v-for)

    预期Array | Object | number | string | Iterable (2.6 新增)

    用法:基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><!--Vue2.0不同于Vue1.0版本,它把$index和$key都移除了,取而代之的是:key属性--><!--简单数组--><div v-for="(item,i) in list_sz">索引:{{i}}-->值:{{item}}</div><br /><!--对象数组--><div v-for="(dx,i) in list_dx">索引:{{i}}-->id:{{dx.id}}--Name:{{dx.name}}</div><br /><!--对象--><div v-for="(val,key,index) of list_user">  索引:{{index}} --> 键:{{key}} 值:{{val}}</div>  </div></body><script>var vm = new Vue({el:"#app",data:{list_sz:[1,2,3,4,5],list_dx:[{id:2,name:'李四'},{id:3,name:'王五'},{id:1,name:'张三'}],list_user:{id:1,name:'Mike',age:22,gender:'男'}}});</script>
</html>

3.1、v-for :key的使用

  官网有一句:v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示。

    官方对key的解释:key 的特殊 attribute 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。而使用 key 时,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。重复的 key 会造成渲染错误。

    要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了。vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。

    

    当页面的数据发生变化时,Diff算法只会比较同一层级的节点:如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。

    对于相同类型的节点更新,如下图:我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的:即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?

    

    不用index做为key的原因也是如此,如果用index作为key,[1,2,3]那么删除第二项的时候,index就会从1,2,3变成1,2,index永远是连续的,同样无法解决上诉问题。

    所以一句话,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>v-for :key的使用</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><div><input type="text" v-model="name"><button @click="add">添加</button></div><ul><li v-for="(item, i) in list"><!--<li v-for="(item, i) in list" :key="item.id">--><input type="checkbox"> {{item.name}}</li></ul></div></body><script>new Vue({el: '#app',data: {name:'',list: [{id: 1,name: '典韦'},{id: 2,name: '凯'},{id: 3,name: '虞姬'},{id:4,name:'蔡文姬'}]},methods: {add:function(){var thisd = this.list.length+1;console.log(thisd+this.name);this.list.unshift({id:+thisd,name: this.name});this.name = ''}}});</script>
</html>

3.2、关于v-for对应的数组的更新

    Vue重写了这些方法,使得他们具备响应式更新

  • push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
  • pop() 方法用于删除并返回数组的最后一个元素。
  • shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
  • unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。
  • splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
  • sort() 方法用于对数组的元素进行排序。
  • reverse() 方法用于颠倒数组中元素的顺序。

4、属性绑定指令(v-bind)

    缩写:

    预期any (with argument) | Object (without argument)

    参数attrOrProp (optional)

    修饰符

  • .prop - 作为一个 DOM property 绑定而不是作为 attribute 绑定。
  • .camel - (2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持)
  • .sync (2.3.0+) 语法糖,会扩展成一个更新父组件绑定值的 v-on 侦听器。

    用法:v-bind 主要用于属性绑定,比方你的class属性,style属性,value属性,href属性等等,只要是属性,就可以用v-bind指令进行绑定    

    动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。

    在绑定 class 或 style attribute 时,支持其它类型的值,如数组或对象。可以通过下面的教程链接查看详情。

    在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。

    没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。

    语法:v-bind:属性名.修饰符="属性值"

4.1、绑定普通属性attribute

<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">
<!-- 缩写 -->
<img :src="imageSrc">

4.2、动态特性名

<!-- 动态特性名 (2.6.0+) -->
<button v-bind:[key]="value"></button>
<!-- 动态特性名缩写 (2.6.0+) -->
<button :[key]="value"></button>

4.3、内联字符串拼接

<!-- 内联字符串拼接:fileName ,'img/'加上单引号之后,并不会进行属性值绑定,而是将字符串原样渲染后绑定属性上。-->
<img :src="'img/' + fileName">

4.4、class 绑定   

    对应class绑定官网给出的三种类型:class对象绑定、class数组绑定、class数组中嵌套对象绑定

<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">

    4.4.1、class对象绑定

<!--传统的html的css类引用语法:-->
<div class="css类名1 css类名2">html传统写法</div><!----------------------------v-bind对象语法-----------------------------------><!--v-bind对象语法,我们需要队css-class类名赋一个boolean值,来决定css类是否生效。-->
<div v-bind:class="{css类名1: true|false, css类名2: true|false}">{{message}}</div><!--使用了v-bind对象语法,仍然可以使用传统css引用法:vue会帮我合并-->
<div v-bind:class="{css类名1: true|false, css类名2: true|false}" class="css类名3">{{message}}</div>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.blue{color: blue;}.red{color: red;}.jc{font-weight:bold}</style></head><body><div id="app"><p :class="{blue:isBlue,red:isRed}">{{name}}</p><!--效果一样--><p :class="getPClass()" class="jc">{{name}}</p></div></body><script>var vm = new Vue({el:"#app",data:{name:"v-bind:class对象绑定",isBlue:true,isRed:false},methods:{getPClass:function(){return {blue:this.isBlue,red:this.isRed}}}});</script>
</html>

效果图:

    4.4.2、class数组绑定、class数组中嵌套对象绑定

<!--数组语法绑定class类--><div :class="['css类名1','css类名2']">数组语法</div><!--数组中嵌套对象--><div :class="['css类名1', 'css类名2', {css类名3: true|false}]"> 数组中嵌套对象</div>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>.blue{color: blue;}.red{color: red;}.jc{font-weight:bold;}.cl{font-size: 30px;}</style></head><body><div id="app"><p :class="cssArray">{{name}}</p><button v-on:click="changeColor" class="jc">切换颜色</button></div></body><script>var vm = new Vue({el:"#app",data:{name:"v-bind:class对象绑定",cssArray:['blue','jc',{cl:true}]},methods:{changeColor:function(){if(this.cssArray[0]!=='blue'){//Vue响应式:数据发生变化后,会重新对页面渲染//使用响应式的操作函数push/pop/shift/unshift/splice/sort/reversethis.cssArray.shift();//移除数组第一个元素this.cssArray.unshift('blue');//加入元素到数组的头部//这种写法不是响应式的,数据发生变化,但是页面颜色不会发生改变//this.cssArray[0]='blue';//unshift可以,原因在于:Vue中重写了Array中的这7个函数}else{this.cssArray.shift();this.cssArray.unshift('red');//this.cssArray[0]='red';}}}});</script>
</html>

效果图:

4.5、style 绑定

    对于style绑定,官网给出了两种:style对象绑定、style数组绑定

<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><p :style="{'font-size':fontSize+'px'}">{{name}}</p><p :style="[style1,style2]">{{name}}</p><button @click="addSize">增大字体</button></div></body><script>var vm = new Vue({el:"#app",data:{name:"v-bind:style绑定",fontSize:20,style1:{color:'red'},style2:{fontWeight:'bold'}},methods:{addSize:function(){this.fontSize++;}}});</script>
</html>

效果图:

4.6、prop 绑定—通过 prop 修饰符绑定 DOM 属性

    官网的解释:作为一个 DOM property 绑定而不是作为 attribute 绑定。

<!-- 通过 prop 修饰符绑定 DOM attribute --> 
<div v-bind:text-content.prop="text"></div>

    4.6.1、从DOM节点properties(属性),attributes(特性)说起    

    property 是 dom 元素在 js 中作为对象拥有的属性;

  attribute 是 dom 元素在文档中作为 html 标签拥有的属性;

    我们可以认为 property 是一个 DOM 对象创建的时候就会初始化在对象中的一些属性(我们也可以自定义属性),而 attribute 是附在 HTML 文档中的某个元素上的特性,我们可以改变、删除、自定义一个特性,但是对 property 不可以,对于 DOM 内置的属性我们无法删除,也只能按照规定类型赋值,并且内置属性会在每次 DOM 对象初始化的时候产生,比如 name 属性,无论我们设置什么类型的值,最后返回的都是字符类型。但是对于我们自定义的 DOM 属性,则可以是任何 JS 支持的数据类型,而 attribute 的数据类型只能是字符串。

    对于 html 的标准属性来说,attribute 和 property 是同步的,是会自动更新的,但是对于自定义的属性来说,他们是不同步的。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title></head><body><input type="text" value="Name" id="app" class="hh" addUserDefine="zidingyi"></body><script>window.onload = function(){var ipt = document.getElementById('app');console.log(ipt);//HTMLInputElementconsole.log(ipt.attributes);//object NamedNodeMap//html自带的dom属性会自动转换成property,但是自定义的属性没有这个'权利'console.log(ipt.className);           //hhconsole.log(ipt.addUserDefine);    //打印 undefinedconsole.log(ipt.name);//打印 "" 虽然没写,但是默认为""//浏览器解析之前全都是特性,解析之后:标准特性的值将被解析并挂载到 DOM属性上,//非标准特性只可用DOM的 getAttribute 等方法取值。getAttribute(attr),attr是大小写不敏感的console.log(ipt.getAttribute('addUserDefine'));//zidingyi}</script>
</html>

    当浏览器解析:<input type="text" value="Name" id="app" class="hh" addUserDefine="zidingyi">这段代码之后,一个HTMLInputElement对象将会被创建,这个对象包含了很多的properties,如:accept, accessKey, align, alt, attributes, autofocus, baseURI, checked, childElementCount, childNodes, children, classList, className, clientHeight等。

    对于DOM节点对象,properties就是这个对象(ipt)的属性集,而attributes是这个对象(ipt)中名为attributes的一个属性。在这些properties中,我们可以看到:className: "hh",等HTMLInputElement中存在的属性,properties同样继承了(标准属性),addUserDefine(非标准属性)却没有出现在js对象的property中。

    如果我们修改了:property的值

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title></head><body><input type="text" value="Name" id="app" class="hh" addUserDefine="zidingyi"></body><script>window.onload = function(){var ipt = document.getElementById('app');console.log(ipt);//HTMLInputElementconsole.log(ipt.attributes);//object NamedNodeMap//html自带的dom属性会自动转换成property,但是自定义的属性没有这个'权利'console.log(ipt.className);           //hhconsole.log(ipt.addUserDefine);    //打印 undefinedconsole.log(ipt.name);//打印 "" 虽然没写,但是默认为""//浏览器解析之前全都是特性,解析之后:标准特性的值将被解析并挂载到 DOM属性上,//非标准特性只可用DOM的 getAttribute 等方法取值。getAttribute(attr),attr是大小写不敏感的console.log(ipt.getAttribute('addUserDefine'));//zidingyi//如果设置的属性属于DOM元素本身所具有的标准属性,不管是通过ele.setAttribute还是ele.title的方式设置,都能正常获取。//通过setAttribute设置的自定义属性,只能通过标准的getAttribute方法来获取;同样通过点号方式设置的自定义属性也无法通过 标准方法getAttribute来获取。ipt.mytitle = 'initTitle';console.log(ipt.value);//initTitleconsole.log(ipt.getAttribute('mytitle'));//null//使用setAttributeipt.setAttribute('mytitle','newTitle');console.log(ipt.mytitle);//initTitle}</script>
</html>

    这就是prop 修饰符的真正意义所在:v-bind 默认绑定到 DOM 节点的 attribute 上,使用 .prop 修饰符后,会绑定到 property上。attribute 设置的自定义属性会在渲染后的 HTML 标签里显示,property 不会:通过自定义属性存储变量,避免暴露数据防止污染 HTML 结构

    4.6.2、通过 prop 修饰符绑定 DOM 属性

<!-- 通过 prop 修饰符绑定 DOM attribute -->
<div v-bind:text-content.prop="text"></div><!--组件中再介绍-->
<!-- prop 绑定。“prop”必须在 my-component 中声明。-->
<my-component :prop="someThing"></my-component><!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><div :aaa.prop="[inputData]" id="pry">{{name}}</div><div :aaa="[inputData]" id="prn">没有修饰符</div></div></body><script>var vm = new Vue({el:"#app",data:{name:"测试prop修饰符",inputData:"hello"}});window.onload=function(){var div = document.getElementById("pry");var divs = document.getElementById("prn");console.log(div.aaa); //helloconsole.log(div.getAttribute('aaa'));//nullconsole.log(div.aaa==vm.inputData);//trueconsole.log(divs.aaa);//undefinedconsole.log(divs.getAttribute('aaa'));//helloconsole.log(divs.getAttribute('aaa')==vm.inputData);//true}</script>
</html>

DOM效果:

4.7、.camel 修饰符

    只有props和.prop会默认将kebab-case转化为camelCase,剩下的作为attribute的不会。而.camel修饰符正是针对attribute的。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><h2 :msg-text="msgText">原本</h2><!-- 编译后为<h2 msg-text="aaa">原本</h2> --><h2 :msg-text.camel="msgText">加camel修饰符</h2><!-- 编译后为<h2 msgtext="aaa">加camel修饰符</h2>,由于camel将msg-text转化为msgText,	html中不区分大小写,所以会将大写都转化为小写,则最终结果为msgtext --><input type="text" v-model="message"><child :my-message="message"></child><!--此处的my-message只能是短横线命名(若为驼峰式则全部转换为小写。)--></div></body><script>Vue.component('child',{//props中传递的数据可以为驼峰式也可以为短横线式,他们在此处是相互转换的//props:['my-message'],props:['myMessage'],//props中使用驼峰命名,则template:'<p>{{myMessage}}</p>'// 此处有限制,是字符串模板,{{ }}语法中不能是短横线连接方式。此处只能是驼峰命名方式。若为短横线的命名方式,则会报错。});new Vue({el:"#app",data:{msgText: 'aaa',message:''}});</script>
</html>

效果图:

5、数据双向绑定指令(v-model)

    预期:随表单控件类型不同而不同。

    限制

  • <input>
  • <select>
  • <textarea>
  • components

    修饰符

  • .lazy - 取代 input 监听 change 事件
  • .number - 输入字符串转为有效的数字
  • .trim - 输入首尾空格过滤

    用法:在表单控件或者组件上创建双向绑定。

案例:

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><input v-model="test">value:{{test}}<br /><!--原理-语法糖:使用v-model,相当于v-bind+v-on--><!--<input :value="test" @input="test= $event.target.value"><br />--><!-- 在每次 input 事件触发后将输入框的值与数据进行同步,添加 lazy 修饰符,从而转变为使用 change 事件进行同步 --><input v-model.lazy="msg" >lazy:{{msg}}<br /><!--去除字符串首尾的空格--><input v-model.trim="trm">trim:{{trm}}<br /><!--将数据转化为值类型--><input v-model.number="age" type="number">number:{{age}}<br /><!--下拉项绑定--><select v-model="selected"><option value="A被选">A</option><option value="B被选">B</option><option value="C被选">C</option></select><span>Selected: {{ selected }}</span><br /><!--单选按钮--><input type="radio" id="small" value="small_value" v-model="picked"><label for="small">small</label><br><input type="radio" id="big" value="big_value" v-model="picked"><label for="big">big</label><br><span>Picked: {{ picked }}</span><br /><!--复选框--><input type="checkbox" id="one" value="value_one" v-model.lazy="checkedNames"><label for="one">选项一</label><input type="checkbox" id="two" value="value_two" v-model.lazy="checkedNames"><label for="two">选项二</label><input type="checkbox" id="three" value="value_three" v-model.lazy="checkedNames"><label for="three">选项三</label><br><span>Checked names: {{ checkedNames }}</span></div></body><script>new Vue({el: '#app',data: {test: '',msg:'',trm:'',age:'',selected: '',picked: '',checkedNames: []}});</script>
</html>

效果:

6、事件绑定指令(v-on)

    缩写@

    预期Function | Inline Statement | Object

    参数event

    修饰符

  • .stop - 调用 event.stopPropagation()
  • .prevent - 调用 event.preventDefault()
  • .capture - 添加事件侦听器时使用 capture 模式。
  • .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  • .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
  • .native - 监听组件根元素的原生事件。
  • .once - 只触发一次回调。
  • .left - (2.2.0) 只当点击鼠标左键时触发。
  • .right - (2.2.0) 只当点击鼠标右键时触发。
  • .middle - (2.2.0) 只当点击鼠标中键时触发。
  • .passive - (2.3.0) 以 { passive: true } 模式添加侦听器

    用法:绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。

    用在普通元素上时,只能监听原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件

    在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event property:v-on:click="handle('ok', $event)"

    从 2.4.0 开始,v-on 同样支持不带参数绑定一个事件/监听器键值对的对象。注意当使用对象语法时,是不支持任何修饰器的。

6.1、事件处理器

    6.1.1、绑定方法

<!-- 方法处理器 -->
<button v-on:click="doThis"></button><!-- 缩写 -->
<button @click="doThis"></button><!-- 动态事件 (2.6.0+) -->
<button v-on:[event]="doThis"></button><!-- 动态事件缩写 (2.6.0+) -->
<button @[event]="doThis"></button>

    案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="example-1"><button v-on:click="counter += 1">Add 1</button><p>The button above has been clicked {{ counter }} times.</p><button @click="greet">Greet</button></div></body><script>var vm = new Vue({el:"#example-1",data:{counter:0,name: 'Vue.js'},methods: {greet: function (event) {// `this` 在方法里指向当前 Vue 实例alert('Hello ' + this.name + '!')// `event` 是原生 DOM 事件if (event) {console.log(event.target.tagName)}}}});</script>
</html>

效果:    

    6.1.2、使用内联

<!-- 内联语句 --> 
<button v-on:click="doThat('hello', $event)"></button>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="example-3"><button v-on:click="say('hi')">Say hi</button><br /><a href="www.baidu.com" v-on:click="say2('you jump',$event)">www.baidu.com</a></div></body><script>var vm = new Vue({el:"#example-3",methods: {say: function (message) {alert(message)},say2: function (message,event) {if (event) {//event.preventDefault()是通知浏览器不要执行与事件关联的默认动作,则a标签不会跳转链接event.preventDefault()}alert(message)}}});</script>
</html>

效果:

6.2、事件修饰符

    在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符

    6.2.1、.stop、.prevent、.capture、.self

<!-- 阻止单击事件继续传播 -->
<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>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><div @click="stop_show2()"><input type="button" value="按钮" @click="stop_show($event)"/><!--这里只会弹出一次--><input type="button" value="按钮.stop" @click.stop="stop_show2()"/></div></div><div id="app1"> <input type="button" value="鼠标右击" @contextmenu="prevent_show($event)"/><!--不会弹出右键菜单--><input type="button" value="鼠标右击.prevent" @contextmenu.prevent="prevent_show()"/></div><div id="app2"><div id="obj1" v-on:click.capture="doc">obj1<div id="obj2" v-on:click.self="doc">obj2<div id="obj3" v-on:click="doc">obj3<div id="obj4" v-on:click="doc">obj4</div></div></div></div></div></body><script>var vm = new Vue({el:"#app",methods:{stop_show:function(ev){alert("我是执行stop_show方法")//注释掉这里会弹出两个//ev.cancelBubble=true;//阻止事件冒泡},stop_show2:function(){alert("我是执行stop_show2方法")}}});var vm1 = new Vue({el:"#app1",methods:{prevent_show:function(ev){alert("我是执行prevent_show方法")//等效于加了这个,加了该方法鼠标右击事件被屏蔽
//					ev.preventDefault();//阻止默认行为}}});var vm2 = new Vue({el:"#app2",methods: {doc: function () {//点击obj4的时候,弹出的顺序为:obj1、obj4、obj3;//由于1有capture修饰符,故而先触发事件,2有self修饰符不是自己不会触发 然后就是4本身触发,最后冒泡事件3触发。this.id= event.currentTarget.id;alert(this.id)}}});</script>
</html>

    6.2.1、.once、.passive

<!-- 点击事件将只会触发一次:2.1.4 新增 -->
<a v-on:click.once="doThis"></a><!--2.3.0 新增-->
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 这其中包含 `event.preventDefault()` 的情况 -->
<div v-on:scroll.passive="onScroll">...</div><!--passive是:Chrome提出的一个新的浏览器特性,Web开发者通过一个新的属性passive来告诉浏览器,当前页面内注册的事件监听器内部是否会调用preventDefault函数来阻止事件的默认行为,以便浏览器根据这个信息更好地做出决策来优化页面性能。当属性passive的值为true的时候,
代表该监听器内部不会调用preventDefault函数来阻止默认滑动行为,Chrome浏览器称这类型的监听器为被动(passive)监听器。目前Chrome主要利用该特性来优化页面的滑动性能,所以Passive Event Listeners特性当前仅支持mousewheel/touch相关事件。 
Passive Event Listeners特性是为了提高页面的滑动流畅度而设计的,页面滑动流畅度的提升,直接影响到用户对这个页面最直观的感受。在监听元素滚动事件的时候,会一直触发onscroll事件,在pc端是没啥问题的,但是在移动端,会让我们的网页变卡,
因此我们使用这个修饰符的时候,相当于给onscroll事件整了一个.lazy修饰符-->
<!--不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。请记住,.passive 会告诉浏览器你不想阻止事件的默认行为。-->

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><input type="button" @click.once="ageadd" value="年龄加1"/>{{18+age}}</div></body><script>var vm = new Vue({el:"#app",data:{age:""},methods:{ageadd:function(){this.age++}}});</script>
</html>

6.3、按键修饰符

    在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符,记住所有的keyCode比较困难(有一些按键 [.esc 以及所有的方向键)]在 IE9 中有不同的 key 值, 如果你想支持 IE9,这些内置的别名应该是首选),所以Vue为最常用的键盘事件提供了别名:

  • .enter:回车键
  • .tab:制表键
  • .delete (捕获“删除”和“退格”键):含delete和backspace键
  • .esc:返回键
  • .space:空格键
  • .up:向上键
  • .down:向下键
  • .left:向左键
  • .right:向右键

2.1.0 新增:

  • .ctrl
  • .alt
  • .shift
  • .meta:在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)

 

2.2.0 新增:

  • .left:只当点击鼠标左键时触发。
  • .right:只当点击鼠标右键时触发。
  • .middle:只当点击鼠标中键时触发。

2.5.0 新增:

  • .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>

    注:可以通过全局 config.keyCodes 对象自定义按键修饰符别名:Vue.config.keyCodes.f1 = 112

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div><div id="box"> <input type="text" value="按下按钮" @keydown="show($event)"/></div></div><div id="app"><!-- enter回车键 -->enter: <input type="text" v-model="msg" @keyup.enter="keys('enter')"><br><!-- tab键:进入时触发 -->tab: <input type="text" v-model="msg" @keyup.tab="keys('tab')"><br><!-- delete键 -->delete: <input type="text" v-model="msg" @keyup.delete="keys('delete/backspace')"><br><!-- esc键 -->esc: <input type="text" v-model="msg" @keyup.esc="keys('esc')"><br><!-- space键 -->space: <input type="text" v-model="msg" @keyup.space="keys('space')"><br><!-- up键 -->up: <input type="text" v-model="msg" @keyup.up="keys('up')"><br><!--ctrl+Q:按住ctrl+Q放开Q的时候触发-->ctrl+Q: <input type="text" v-model="msg" @keyup.ctrl.81="keys('ctrl+Q')"><br><!--鼠标右键-->鼠标右键:<div :style="right_style" @contextmenu.prevent="mouseclick('右')"></div></div></body><script>new Vue({el: '#box',data: {},methods:{show:function(ev){alert(ev.keyCode)}}});new Vue({el:"#app",data : {msg : '',right_style:{border:'solid 2px blue',height:'100px',width:'100px'}},methods : {keys:function(key) {alert('您按下的是' + key);},mouseclick:function(where){alert('点击鼠标'+where+'键触发');}}});</script>
</html>

7、其他指令(v-pre、v-once、v-slot、v-cloak)

7.1、v-pre

    不需要表达式,例如:<span v-pre>{{ this will not be compiled }}</span>

    用法:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。

7.2、v-cloak

    不需要表达式,例如:[v-cloak] { display: none; },<div v-cloak> {{ message }} </div>

    用法:这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕。

    作用:由于浏览器网速问题,Vue在渲染{{msg}}数据时可能会有延迟,这延迟的一瞬间{{msg}}会原样输出,如:原本输出的是 自如初,延迟的结果就是{{msg}}被原样输出了。可以使用v-textv-cloak解决。v-text只会输出文本,不会对HTML进行解析,若要输出HTML内容,那么v-text有着明显的局限性,也不灵活。v-cloak解决闪屏的问题。使用该指令时,要为该指令加display:none的样式。

7.3、v-once

    不需要表达式

    详细:只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。

<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 有子元素 -->
<div v-once><h1>comment</h1><p>{{msg}}</p>
</div>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- `v-for` 指令-->
<ul><li v-for="i in list" v-once>{{i}}</li>
</ul>

案例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><style>/** 为v-cloak指令设置样式 **/[v-cloak] {display: none;}</style><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><!-- 输出结果为 {{ webUrl }}--><div v-pre>{{ webUrl }}</div><!-- 输出结果为 个人博客--><div v-cloak>{{ webName }}</div><!--加了v-once--><div v-once><input v-model="msg"><br />This will never change: {{msg}}</div><span>This will change: {{msg}}</span></div></body><script type="text/javascript">var vm=new Vue({el:'#app',data:{msg:'hello vue',webName:"个人博客"}});</script>
</html>

效果:

7.4、v-slot

    缩写#

    预期:可放置在函数参数位置的 JavaScript 表达式 (在支持的环境下可使用解构)。可选,即只需要在为插槽传入 prop 的时候使用。

    参数:插槽名 (可选,默认值是 default)

     限用于:

  • <template>
  • 组件 (对于一个单独的带 prop 的默认插槽)

    用法:提供具名插槽或需要接收 prop 的插槽。

    示例后面用到了再介绍

<!-- 具名插槽 -->
<base-layout><template v-slot:header>Header content</template>Default slot content<template v-slot:footer>Footer content</template>
</base-layout><!-- 接收 prop 的具名插槽 -->
<infinite-scroll><template v-slot:item="slotProps"><div class="item">{{ slotProps.item.text }}</div></template>
</infinite-scroll><!-- 接收 prop 的默认插槽,使用了解构 -->
<mouse-position v-slot="{ x, y }">Mouse position: {{ x }}, {{ y }}
</mouse-position>

8、特殊 attribute(key、ref、is) 

8.1、key

    预期number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增)

    用法:最常见的用例是结合 v-for,前面也已经介绍过了。

    它也可以用于强制替换元素/组件而不是重复使用它。当你遇到如下场景时它可能会很有用。

  • 完整地触发组件的生命周期钩子
  • 触发过渡

    注:这个在过渡中再介绍

<transition><span :key="text">{{ text }}</span>
</transition><!--当 text 发生改变时,<span> 总是会被替换而不是被修改,因此会触发过渡。-->

8.2、ref

    预期string

  作用:ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件。

    注:这个在组件中再介绍

<!-- `vm.$refs.p` will be the DOM node -->
<p ref="p">hello</p><!-- `vm.$refs.child` will be the child component instance -->
<child-component ref="child"></child-component>

8.3、 is

    预期string | Object (组件的选项对象)

    作用:用于动态组件且基于 DOM 内模板的限制来工作。

    示例:这个在组件中再介绍

<!-- 当 `currentView` 改变时,组件也跟着改变 -->
<component v-bind:is="currentView"></component><!-- 这样做是有必要的,因为 `<my-row>` 放在一个 -->
<!-- `<table>` 内可能无效且被放置到外面 -->
<table><tr is="my-row"></tr>
</table>

四、Vue实例及选项

    每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的。前面我们已经用了很多次 new Vue({...})的代码,而且Vue初始化的选项都已经用了datamethodsel等,估计,应该已经都明白了他们的作用。当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

    Vue中支持很多选项,如下图所示:

 

    Vue实例的基本结构:

new Vue({el:'#app',//所有的挂载元素会被 Vue 生成的 DOM 替换data:{  },// this->windowmethods:{ },// this->vm//注意,不应该使用箭头函数来定义 method 函数 ,this将不再指向vm实例props:{} ,// 可以是数组或对象类型,用于接收来自父组件的数据//对象允许配置高级选项,如类型检测、自定义验证和设置默认值watch:{ },// this->vmcomputed:{},render:{},
})

1、创建Vue实例

1.1、构造器

    vue实例的创建:一般通过new关键字的方式来创建,构造函数的参数列表需要传入一个选项对象

var vm = new Vue(paramObj);

1.2、创建Vue实例的三种方式

    Vue有三个属性和模板有关,官网上是这样解释的:

    el:提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标;

    template:一个字符串模板作为 Vue 实例的标识使用。模板将会 替换 挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽;

    render:字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode;

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><title>vue实例创建方式</title></head><body><div id="app1">{{msg}}</div><div id="app2"></div><div id="app3"></div></body><script>new Vue({el: "#app1", //用el做模板data: {msg: "hello vue"}})new Vue({el: "#app2",data: {msg: "hello vue"},template: "<p id='cs'> {{msg}}</p>" //用template做模板})new Vue({el: "#app3",data: {msg: "hello vue"},render: function(h) { //直接用render函数渲染return h('div', this.msg)}})</script>
</html>

效果:

2、 Vue实例化过程理解

    Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载 Dom、渲染 → 更新 → 渲染、销毁等一系列过程,我们称这是 Vue 的生命周期,通俗说就是 Vue 实例从创建到销毁的过程。每一个组件或者实例都会经历一个完整的生命周期,总共分为三个阶段:初始化、运行中、销毁。四个主要过程:创建挂载、更新、销毁。八个阶段(在这个过程中也会运行一些生命周期钩子):beforeCreate(创建前)、created(创建后)、beforeMount(挂载前)、mounted(载入后)、beforeUpdate(更新前)、updated(更新后)、beforeDestroy(销毁前)、destroyed(销毁后)。

    引用官网一张图:

2.1、定义Vue

    Vue 构造函数只执行了 this._init(options) 这么一句代码。

function Vue (options) {if ("development" !== 'production' &&!(this instanceof Vue)) {warn('Vue is a constructor and should be called with the `new` keyword');}this._init(options);
}
initMixin(Vue);  // 定义 _init(初始化就已经加载了,里面定义了Vue的原型方法_init)
stateMixin(Vue);  // 定义 $set $get $delete $watch 等
eventsMixin(Vue);   // 定义事件  $on  $once $off $emit
lifecycleMixin(Vue); // 定义 _update  $forceUpdate  $destroy
renderMixin(Vue); // 定义 _render 返回虚拟dom  

2.2、initMixin

    实例化Vue时,执行 _init, _init 定义在 initMixin 中,调用原型上的方法_init。这里主要做了这几件事情:

    1)初始化 options 参数,将 _renderProxy 设置为 vm

    2)生命周期变量初始化:vm.$parent vm.$root vm.$children vm.$refs等

    3)初始化 渲染Render

    4)初始化 vm的状态,prop/data/computed/method/watch都在这里完成初始化

    5)挂载实例

  Vue.prototype._init = function (options) {// 合并 optionsif (options && options._isComponent) {initInternalComponent(vm, options); // 组件合并} else {// 非组件合并vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options || {},vm);}initLifecycle(vm); // 定义 vm.$parent vm.$root vm.$children vm.$refs 等(生命周期变量初始化)initEvents(vm);   // 定义 vm._events  vm._hasHookEvent 等(事件监听初始化)initRender(vm); // 定义 $createElement $c (初始化渲染)callHook(vm, 'beforeCreate'); // 回调 beforeCreate 钩子函数initInjections(vm); // resolve injections before data/props (初始化注入)initState(vm);  // 初始化 props methods data computed watch 等方法 (状态初始化)initProvide(vm); // resolve provide after data/propscallHook(vm, 'created'); // 回调 created 钩子函数// 如果有el选项,则自动开启模板编译阶段与挂载阶段// 如果没有传递el选项,则不进入下一个生命周期流程// 用户需要执行vm.$mount方法,手动开启模板编译阶段与挂载阶段if (vm.$options.el) {vm.$mount(vm.$options.el); // 实例挂载渲染dom}};

2.3、$mount

    mount 调用 mountComponent函数,这里主要做了这几件事:

    1)判断是否有render选项,如果有则直接构建虚拟DOM

    2)如果没有render选项,则判断是否有template 或者el挂载了元素

    3)回调挂载前函数beforeMount

    4)执行vm._update(vm._render(), hydrating); 将虚拟dom转为真实的dom并挂载到页面

    5)使用Watcher函数检测数据是否更新,如果有更新则回调更新前函数beforeUpdate和更新后函数updated,如果检测到已经没有虚拟DOM了,回调载入后函数。

  Vue.prototype.$mount = function (el,hydrating) {el = el && inBrowser ? query(el) : undefined;return mountComponent(this, el, hydrating)};function mountComponent (vm,el,hydrating) {vm.$el = el;if (!vm.$options.render) {  //如果选项中没有render选项vm.$options.render = createEmptyVNode; //如果有render选项就创建虚拟DOM{/* istanbul ignore if */if ((vm.$options.template && vm.$options.template.charAt(0) !== '#') ||vm.$options.el || el) {//在判断选项中是否有template选项 或者 el挂载元素warn('You are using the runtime-only build of Vue where the template ' +'compiler is not available. Either pre-compile the templates into ' +'render functions, or use the compiler-included build.',vm);} else {warn('Failed to mount component: template or render function not defined.',vm);}}}callHook(vm, 'beforeMount');//回调 挂载前函数var updateComponent;/* istanbul ignore if */if (config.performance && mark) {updateComponent = function () {var name = vm._name;var id = vm._uid;var startTag = "vue-perf-start:" + id;var endTag = "vue-perf-end:" + id;mark(startTag);var vnode = vm._render();mark(endTag);measure(("vue " + name + " render"), startTag, endTag);mark(startTag);vm._update(vnode, hydrating);mark(endTag);measure(("vue " + name + " patch"), startTag, endTag);};} else {updateComponent = function () {vm._update(vm._render(), hydrating); //将虚拟dom转为真实的dom并挂载到页面};}// we set this to vm._watcher inside the watcher's constructor// since the watcher's initial patch may call $forceUpdate (e.g. inside child// component's mounted hook), which relies on vm._watcher being already definednew Watcher(vm, updateComponent, noop, {before: function before () {if (vm._isMounted && !vm._isDestroyed) {callHook(vm, 'beforeUpdate'); //回调更新前函数}}}, true /* isRenderWatcher */);hydrating = false;// manually mounted instance, call mounted on self// mounted is called for render-created child components in its inserted hookif (vm.$vnode == null) {vm._isMounted = true;callHook(vm, 'mounted'); //mounted(载入后)}return vm}

3、实例选项DOM(el、template、render、renderError)

3.1、el

    类型string | Element

    限制:只在用 new 创建实例时生效

    详细:提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

    如果在实例化时存在这个选项,实例将立即进入编译过程,否则,需要显式调用 vm.$mount() 手动开启编译。如果 render 函数和 template property 都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板。

3.2、template

    类型string

    详细:一个字符串模板作为 Vue 实例的标识使用。模板将会替换挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发插槽。

3.3、render

    类型(createElement: () => VNode) => VNode

    详细:字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode

    注:Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

3.4、renderError(2.2.0 新增)

    类型(createElement: () => VNode, error: Error) => VNode

    详细只在开发者环境下工作。

 

案例:在Vue实例创建中,就已经展示了三种模板创建方式。在Vue实例化过程介绍中,提到过如果没有el挂载元素,则需手动挂载。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"></div></body><script>new Vue({render(h) {throw new Error('oops')},renderError(h, err) {//只在开发环境使用return h('pre', {style: {color: 'red'}}, err.stack)}}).$mount('#app')//手动挂载到app上</script>
</html>

效果:

4、实例选项数据(data、props、propsData、computed、methods、watch)

4.1、methods

    类型{ [key: string]: Function }

    详细:methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><title>methods</title>
</head>
<body><div id="app">{{msg}}<button @click="ChangeMessage">测试按钮</button></div><script>new Vue({el:'#app',data:{msg:"Hello World!"},methods:{ChangeMessage:function(){this.msg="Hello Vue!";}}})</script>
</body>
</html>

methods源码分析执行initState()过程中做了很多的初始化工作(初始化:props => methods =>data => computed => watch),如果有定义(if (opts.methods) { initMethods(vm, opts.methods); } ),则进行初始化

function initMethods (vm, methods) {var props = vm.$options.props;for (var key in methods) {{if (typeof methods[key] !== 'function') {//遍历methods对象,key是每个键,即函数名称warn("Method \"" + key + "\" has type \"" + (typeof methods[key]) + "\" in the component definition. " +"Did you reference the function correctly?",vm);}if (props && hasOwn(props, key)) {//如果props中有同名属性,则报错warn(("Method \"" + key + "\" has already been defined as a prop."),vm);}if ((key in vm) && isReserved(key)) {//如果key是以$或_开头则,也报错warn("Method \"" + key + "\" conflicts with an existing Vue instance method. " +"Avoid defining component methods that start with _ or $.");}}vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);//如果key对应的值不是null,则执行bind()函数,将其绑定到Function的原型上}}

4.2、data

    类型Object | Function

    限制:组件的定义只接受 function

    详细:Vue 实例的数据对象。Vue 将会递归将 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。一旦观察过,你就无法在根数据对象上添加响应式 property。因此推荐在创建实例之前,就声明所有的根级响应式 property。实例创建之后,可以通过 vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a 等价于访问 vm.$data.a。以 _ 或 $ 开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如 vm.$data._property 的方式访问这些 property。

    当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。如果需要,可以通过将 vm.$data 传入 JSON.parse(JSON.stringify(...)) 得到深拷贝的原始数据对象。

    (如果组件选项中的 data 是对象而不是函数,当存在多个该组件时,引用的是相同的组件选项对象,组件操作data会互相影响。)

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">{{msg}}</div></body><script>var vm = new Vue({el:"#app",data:{msg:"hello vue"}});//在组件中必须是函数Vue.component( 'component-name', Vue.extend({//The "data" option should be a function that returns a per-instance value in component definitions.data : function() {return {msg : 'hello vue'};}}));</script>
</html>

data源码分析:执行initState()过程中,如果有 if (opts.data) {initData(vm);}则调用initData方法。data中的属性不能和methods和props重名,调用observe方法对数组和对象分别进行了响应式设置(get/set)

function initData (vm) {var data = vm.$options.data;// 如果data是一个方法 就执行这个方法data = vm._data = typeof data === 'function'? getData(data, vm): data || {};if (!isPlainObject(data)) {data = {};warn('data functions should return an object:\n' +'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',vm);}// proxy data on instancevar keys = Object.keys(data);// 所有定义的data的第一层的keyvar props = vm.$options.props;// 所有定义的propsvar methods = vm.$options.methods; // 所有定义的methodsvar i = keys.length;while (i--) {//判断是否和methods和props重名var key = keys[i];{if (methods && hasOwn(methods, key)) {// key不能和方法名相同warn(("Method \"" + key + "\" has already been defined as a data property."),vm);}}if (props && hasOwn(props, key)) {// key不可以和props定义的名称相同warn("The data property \"" + key + "\" is already declared as a prop. " +"Use prop default value instead.",vm);} else if (!isReserved(key)) {// 看看是不是以$_开头 如果是以他们开头的 就给你抛异常proxy(vm, "_data", key);// 设置代理}}// observe dataobserve(data, true /* asRootData */); // 走observe方法,响应式设置}

4.3、computed

    类型{ [key: string]: Function | { get: Function, set: Function } }

    详细:计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。

    注意如果你为一个计算属性使用了箭头函数,则 this 不会指向这个组件的实例,不过你仍然可以将其实例作为函数的第一个参数来访问。

    计算属性的结果会被缓存,除非依赖的响应式 property 变化才会重新计算。注意,如果某个依赖 (比如非响应式 property) 在该实例范畴之外,则计算属性是不会被更新的。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>computed</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><p>computed={{sumab}}</p><p>computed={{sumab}}</p><p>methods={{sumabs()}}</p><p>methods={{sumabs()}}</p></div><div id="app1"><select v-model="fullNamesx" ><option value="上官 飞燕">上官 飞燕</option><option value="慕容 云海">慕容 云海</option><option value="长孙 无忌">长孙 无忌</option></select><!--双向绑定--><input v-model="fullNamesx"/></div></body><script>var data={a: 1,b: 2,c: 3};new Vue({el: "#app",data: data,computed: {//不需要设定处理可以不写set方法sumab: function() {console.log('这是cpmputed实现的a+b处理')return Number(this.a) + Number(this.b)}},methods: {sumabs:function(){console.log('这是methods实现的a+b处理')return Number(this.a) + Number(this.b)}}})
//		[{"上官 飞燕"},{"慕容 云海"},{"长孙 无忌"}]new Vue({el: "#app1",data: {firstName:"",lastName:""},computed: {//什么时候执行:初始化显示""相关的data属性发生变化及使用fullNamesx属性时fullNamesx:{get:function(){console.log("get:"+this.firstName + ' ' + this.lastName);//计算属性中的get方法,方法的返回值就是属性值return this.firstName + ' ' + this.lastName},set: function (val) {//val=取到的结果值console.log("set:"+val);var names = val.split(' ');if(names.length>=2){this.firstName =names[0];this.lastName = names[names.length - 1];}}}}})</script>
</html>

效果:

源码分析:在initState()执行中,if (opts.computed) { initComputed(vm, opts.computed); }则调用initComputed。computed实际上就是watcher实现的

function initComputed (vm, computed) {// $flow-disable-linevar watchers = vm._computedWatchers = Object.create(null);//存放computed的观察者// computed properties are just getters during SSRvar isSSR = isServerRendering();for (var key in computed) {var userDef = computed[key];var getter = typeof userDef === 'function' ? userDef : userDef.get;if (getter == null) {warn(("Getter is missing for computed property \"" + key + "\"."),vm);}if (!isSSR) {// create internal watcher for the computed property.//computed实际上就是watcher实现的,这个实例的参数分别为vm实例,上方得到的getter,noop为回调函数,watcheroptions配置watchers[key] = new Watcher( //生成观察者(Watcher实例)vm,getter || noop, noop,computedWatcherOptions );}// component-defined computed properties are already defined on the// component prototype. We only need to define computed properties defined// at instantiation here.if (!(key in vm)) {defineComputed(vm, key, userDef); //将 computed 属性添加到组件实例上,并通过 get、set 获取或者设置属性值,并且重定义 getter 函数} else {if (key in vm.$data) {warn(("The computed property \"" + key + "\" is already defined in data."), vm);} else if (vm.$options.props && key in vm.$options.props) {warn(("The computed property \"" + key + "\" is already defined as a prop."), vm);}}}}

扩展:methods与computed区别与总结

4.4、watch

    类型{ [key: string]: string | Function | Object | Array }

    详细:一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个 property。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>watch</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><input type="button" @click="changeB" value="改变b值" /> <p :style="{'color':isRed}">b = {{b}}</p><p>{{array}}</p><button @click='addArray()'>点击改变数组</button><input type="text" v-model="c.name"/></div><script>var vm = new Vue({el:"#app",data: {a: 1,b: 6,c: {name: "JohnZhu"},array:['zs','ls','ww','emz'],isRed:"black"},watch: {//监测a的变化a: function(val, oldVal) {console.log('new a: %s, old a: %s', val, oldVal)},//监测b的变化b: 'someMethod',// 方法名array:{//官网提示:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。handler:function(newVal,oldVal){console.log(newVal+'--'+oldVal)//旧值与新值相同},deep:true,immediate:true},//监听对象的属性变化'c.name':function(val, oldVal){console.log('new c.name: %s, old c.name: %s', val, oldVal);}},methods: {someMethod: function() {this.isRed="red";alert("b is changed");},changeB: function() {this.b++;},addArray:function(){this.array.push('66')}}})vm.a = 2; // new: 2, old: 1</script></body>
</html>

效果:

4.5、props

    类型Array<string> | Object

    详细:props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义验证和设置默认值。

  • type:可以是下列原生构造函数中的一种:StringNumberBooleanArrayObjectDateFunctionSymbol、任何自定义构造函数、或上述内容组成的数组。会检查一个 prop 是否是给定的类型,否则抛出警告。Prop 类型的更多信息在此。
  • defaultany
    为该 prop 指定一个默认值。如果该 prop 没有被传入,则换做用这个值。对象或数组的默认值必须从一个工厂函数返回。
  • requiredBoolean
    定义该 prop 是否是必填项。在非生产环境中,如果这个值为 truthy 且该 prop 没有被传入的,则一个控制台警告将会被抛出。
  • validatorFunction
    自定义验证函数会将该 prop 的值作为唯一的参数代入。在非生产环境下,如果该函数返回一个 falsy 的值 (也就是验证失败),一个控制台警告将会被抛出。你可以在这里查阅更多 prop 验证的相关信息。
//更多内容将在组件中讲解
// 简单语法
Vue.component('props-demo-simple', {props: ['size', 'myMessage']
})// 对象语法,提供验证
Vue.component('props-demo-advanced', {props: {// 检测类型height: Number,// 检测类型 + 其他验证age: {type: Number,default: 0,required: true,validator: function (value) {return value >= 0}}}
})

4.6、propsData

    类型{ [key: string]: any }

    限制:只用于 new 创建的实例中。

    详细:创建实例时传递 props。主要作用是方便测试。

var Comp = Vue.extend({props: ['msg'],template: '<div>{{ msg }}</div>'
})var vm = new Comp({propsData: {msg: 'hello'}
})

5、实例选项生命周期钩子

    前面讲过实例的创建过程,每个 Vue 实例在被创建时都要经过一系列的初始化过程,同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

5.1、beforeCreate

  • 类型Function

  • 详细:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

5.2、created

  • 类型Function

  • 详细:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),property 和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el property 目前尚不可用。

从created到beforeMount的过程中,首先会判断vue实例中有没有el选项,如果有的话则进行下面的编译,但是如果没有el选项,则停止生命周期,直到vue实例上调用vm.$mount(el)。
如果有el,再判断是否有template参数,如果有,则把其当作模板编译成render函数,如果没有,则把外部的html作为模板编译。template中的模板优先级高于outer HTML模板。
在vue对象中还有一个render函数,它是以createElement作为参数,然后做渲染操作,而且我们可以直接嵌入JSX.
综合排名优先级:render函数选项 > template选项 > outer HTML.

5.3、beforeMount

  • 类型Function

  • 详细:在挂载开始之前被调用:相关的 render 函数首次被调用。该钩子在服务器端渲染期间不被调用。

5.4、mounted

  • 类型Function

  • 详细:实例被挂载后调用,这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上,当 mounted 被调用时 vm.$el 也在文档内。该钩子在服务器端渲染期间不被调用。

    注意 mounted 不会保证所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以在 mounted 内部使用 vm.$nextTick:

mounted: function () {this.$nextTick(function () {// Code that will run only after the// entire view has been rendered})
}

5.5、beforeUpdate

  • 类型Function

  • 详细:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。

5.6、updated

  • 类型Function

  • 详细:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。该钩子在服务器端渲染期间不被调用。

    当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

    注意 updated 不会保证所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以在 updated 里使用 vm.$nextTick:

updated: function () {this.$nextTick(function () {// Code that will run only after the// entire view has been re-rendered})
}

5.7、beforeDestroy

  • 类型Function

  • 详细:实例销毁之前调用。在这一步,实例仍然完全可用。该钩子在服务器端渲染期间不被调用。

5.8、destroyed

  • 类型Function

  • 详细:实例销毁后调用。该钩子被调用后,对应 Vue 实例的所有指令都被解绑,所有的事件监听器被移除,所有的子实例也都被销毁。该钩子在服务器端渲染期间不被调用。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title>vue生命周期学习</title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><h1>{{message}}</h1><button @click="destroy">手动销毁</button></div></body><script>var vm = new Vue({el: '#app',data: {message: 'Vue的生命周期'},methods:{destroy:function(){this.$destroy()//手动销毁console.log("我执行了呀!");//销毁后解绑了app,再次改变message值,vue不再对此动作进行响应了//如果注释掉:this.$destroy()则生效this.message="Vue的生命周期2";}},beforeCreate: function() {console.group('------beforeCreate创建前状态------');console.log("%c%s", "color:red", "el     : " + this.$el); //undefinedconsole.log("%c%s", "color:red", "data   : " + this.$data); //undefined console.log("%c%s", "color:red", "message: " + this.message)//undefinedconsole.log("data、computed、watch、methods和DOM都不能使用");},created: function() {console.group('------created创建完毕状态------');console.log("%c%s", "color:red", "el     : " + this.$el); //undefinedconsole.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化 console.log("%c%s", "color:red", "message: " + this.message); //已被初始化console.log("可以操作data、computed、watch、methods,但DOM还没挂载。通常在此进行页面初始化操作或简单的Ajax请求");},beforeMount: function() {console.group('------beforeMount挂载前状态------');console.log("%c%s", "color:red", "el     : " + (this.$el)); //已被初始化console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化  console.log("%c%s", "color:red", "message: " + this.message); //已被初始化},mounted: function() {console.group('------mounted 挂载结束状态------');console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化console.log("%c%s", "color:red", "message: " + this.message); //已被初始化console.log("实例被挂载到DOM上。通常用于执行Ajax请求。");},beforeUpdate: function() {console.group('beforeUpdate 更新前状态===============》');console.log("%c%s", "color:red", "el     : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data);console.log("%c%s", "color:red", "message: " + this.message);},updated: function() {console.group('updated 更新完成状态===============》');console.log("%c%s", "color:red", "el     : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data);console.log("%c%s", "color:red", "message: " + this.message);},beforeDestroy: function() {console.group('beforeDestroy 销毁前状态===============》');console.log("%c%s", "color:red", "el     : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data);console.log("%c%s", "color:red", "message: " + this.message);},destroyed: function() {console.group('destroyed 销毁完成状态===============》');console.log("%c%s", "color:red", "el     : " + this.$el);console.log(this.$el);console.log("%c%s", "color:red", "data   : " + this.$data);console.log("%c%s", "color:red", "message: " + this.message)}})</script>
</html>

效果:

   在Vue的整个生命周期中,它提供了一系列的事件,可以让我们注册js方法,可以让我们达到控制整个过程的目的地。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。以上这8个方法就是生命周期钩子函数。

5.9、activated

  • 类型Function

  • 详细:被 keep-alive 缓存的组件激活时调用。该钩子在服务器端渲染期间不被调用。

5.10、deactivated

  • 类型Function

  • 详细:被 keep-alive 缓存的组件停用时调用。该钩子在服务器端渲染期间不被调用。

5.11、errorCaptured(2.5.0+新增)

  • 类型(err: Error, vm: Component, info: string) => ?boolean

  • 详细: 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

5.12、其他(选项 / 资源、选项 / 组合、选项 / 其它

    关于Vue的选项还有一些,如下(都将在介绍全局API/组件中的时候在讲解):

    选项 / 资源:directives、filters、components

    选项 / 组合:parent、mixins、extends、provide / inject

    选项 / 其它:name、delimiters、functional、model、inheritAttrs、comments

五、Vue实例的属性和方法

    Vue 实例暴露了一些有用的实例属性与方法。这些属性与方法都有前缀 $,以便与代理的数据属性区分。

1、Vue实例属性-DOM访问(vm.$el

 1.1、vm.$el

  • 类型Element

  • 只读

  • 详细:Vue 实例使用的根 DOM 元素。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">{{ message }}</div></body><script>var vm2 = new Vue({el: "#app",data: {message: "hello vue."}});console.log(vm2.$el); //vm2.$el === 原生js中document.getElementById("app") vm2.$el.style.color = "red"; //变成红色</script>
</html>

2、Vue实例属性-数据访问(vm.$data、vm.$options、vm.$props

2.1、vm.$data

  • 类型Object

  • 详细:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象 property 的访问。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">{{ message }}</div></body><script>var vm = new Vue({el: "#app",data: {message: "hello vue."}});console.log(vm.$data) //{__ob__: Observer}console.log(vm._data); //{__ob__: Observer}console.log(vm.$data == vm._data); //true//三种方式都可以访问到messageconsole.log(vm.$data.message); //hello vueconsole.log(vm._data.message); //hello vueconsole.log(vm.message);  //hello vue</script>
</html>

效果:

    通过vm.$data.message、vm._data.message甚至是vm.message,都可以获取到message,实际上都是访问的vm._data.xxx。具体的实现可以参考这篇文章:https://blog.csdn.net/xiaoxianer321/article/details/112637956

2.2、vm.$options

  • 类型Object

  • 只读

  • 详细:用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处

2.3、vm.$props(2.2.0 新增)

  • 类型Object

  • 详细:当前组件接收到的 props 对象。Vue 实例代理了对其 props 对象 property 的访问。

3、Vue实例属性-组件树访问(vm.$parent、vm.$root、vm.$children、vm.$refs

3.1、vm.$parent

  • 类型Vue instance

  • 只读

  • 详细:父实例,如果当前实例有的话。

3.2、vm.$root

  • 类型Vue instance

  • 只读

  • 详细:当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。

3.3、vm.$children

  • 类型Array<Vue instance>

  • 只读

  • 详细:当前实例的直接子组件。需要注意 $children 并不保证顺序,也不是响应式的。如果你发现自己正在尝试使用 $children 来进行数据绑定,考虑使用一个数组配合 v-for 来生成子组件,并且使用 Array 作为真正的来源。

3.4、vm.$refs

  • 类型Object

  • 只读

  • 详细:一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例。

4、Vue实例属性-作用域/插槽(vm.$slots、vm.$scopedSlots、vm.$attrs、vm.$listeners

4.1、vm.$slots

  • 类型{ [name: string]: ?Array<VNode> }

  • 只读

  • 响应性:否

  • 详细:用来访问被插槽分发的内容。每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。

    请注意插槽不是响应性的。如果你需要一个组件可以在被传入的数据发生变化时重渲染,我们建议改变策略,依赖诸如 props 或 data 等响应性实例选项。

4.2、vm.$scopedSlots

  • 类型{ [name: string]: props => Array<VNode> | undefined }

  • 只读

  • 详细:用来访问作用域插槽。对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。vm.$scopedSlots 在使用渲染函数开发一个组件时特别有用。

    注意:从 2.6.0 开始,这个 property 有两个变化:

    1)作用域插槽函数现在保证返回一个 VNode 数组,除非在返回值无效的情况下返回 undefined

    2)所有的 $slots 现在都会作为函数暴露在 $scopedSlots 中。如果你在使用渲染函数,不论当前插槽是否带有作用域,我们都推荐始终通过 $scopedSlots 访问它们。这不仅仅使得在未来添加作用域变得简单,也可以让你最终轻松迁移到所有插槽都是函数的 Vue 3。

4.3、vm.$attrs(2.4.0 新增)

  • 类型{ [key: string]: string }

  • 只读

  • 详细:包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

4.4、vm.$listeners(2.4.0 新增)

  • 类型{ [key: string]: Function | Array<Function> }

  • 只读

  • 详细:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。

5、Vue实例属性-其他(vm.$isServer

5.1、vm.$isServer

  • 类型boolean

  • 只读

  • 详细:当前 Vue 实例是否运行于服务器。

源码如下:

//源码
Object.defineProperty(Vue.prototype, '$isServer', {get: isServerRendering});var _isServer;var isServerRendering = function () {if (_isServer === undefined) {/* istanbul ignore if *///对应源码var inBrowser = typeof window !== 'undefined'; 利用浏览器的全局对象 window 做区分,因为在 nodejs 环境下是没有 window 这个全局对象的//对应源码var inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;//如果不是浏览器运行环境  不是微信运行环境 不是Node环境(Node顶层对象是global)if (!inBrowser && !inWeex && typeof global !== 'undefined') {// detect presence of vue-server-renderer and avoid// Webpack shimming the process//检测是否存在vue服务器渲染器并避免Webpack填充过程_isServer = global['process'] && global['process'].env.VUE_ENV === 'server';} else {_isServer = false;}}return _isServer};

6、Vue实例方法-数据(vm.$watch、vm.$set、vm.$delete)

6.1、vm.$watch( expOrFn, callback, [options] )

    参数:

  • {string | Function} expOrFn 要观测的属性
  • {Function | Object} callback 可以是一个回调函数, 也可以是一个纯对象(这个对象要包含handle属性)
  • {Object} [options]  
    • {boolean} immediate  immediate立即执行回调
    • {boolean} deep  deep指的是深度观测

    返回值{Function} unwatch

    用法:观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。表达式只接受简单的键路径。对于更复杂的表达式,用一个函数取代。

    注意:在变更 (不是替换) 对象或数组时,旧值将与新值相同,因为它们的引用指向同一个对象/数组。Vue 不会保留变更之前值的副本。

6.1.1、要观测的属性{string | Function}

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">firstName:<input v-model="firstName"><br/>lastName:<input v-model="lastName"><p>fullName: {{fullName}}</p></div></body><script>var vm=new Vue({el:'#app',data:{firstName:"Dell",lastName:"Lee",fullName:'Dell Lee',}});//vm.$watch( expOrFn, callback, [options] )//expOrFn-键路径  监听firstName的变化,并在控制台打印vm.$watch('firstName',function (newVal,oldVal) {console.log(newVal);console.log(oldVal);})//expOrFn-函数  监听两者的变化vm.$watch(function () {this.fullName=this.firstName+' '+this.lastName;})</script>
</html>

效果:

6.1.2、deep选项

    为了发现对象内部值的变化,可以在选项参数中指定 deep: true 。 注意监听数组的变动不需要这么做。(前面解释过重写了数组的操作方法)

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">firstName:<input v-model="firstName"><br/>lastName:<input v-model="lastName"><p>fullName: {{fullName}}</p></div></body><script>var vm=new Vue({el:'#app',data:{firstName:"Dell",lastName:"Lee",fullName:'Dell Lee',info:{age:20,sex:'man'}}});//vm.$watch( expOrFn, callback, [options] )vm.$watch('info.age',  //直接用键值指定,没有deep也可以找到function (newVal,oldVal) {console.log("我没有deep,有键:"+newVal);})//函数中没有指定deep选项vm.$watch('info',function (newVal,oldVal) {console.log("我没有deep,没有键:"+newVal.age);})//有deep选项:可深度观测vm.$watch('info',function (newVal,oldVal) {console.log("我有deep:"+newVal.age);},{deep:true})</script>
</html>

效果:

注:不使用键值单独使用函数也可以原因在于第一个参数如果是函数,调用属性会直接调用get方法。

//..源码
if (typeof expOrFn === 'function') {this.getter = expOrFn} else {this.getter = parsePath(expOrFn)}this.value =  this.get()
}
//..

6.1.3、immediate选项

    在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app">firstName:<input v-model="firstName"><br/>lastName:<input v-model="lastName"><p>fullName: {{fullName}}</p></div></body><script>var vm=new Vue({el:'#app',data:{firstName:"Dell",lastName:"Lee",fullName:'Dell Lee',info:{age:20,sex:'man'}}});//vm.$watch( expOrFn, callback, [options] )vm.$watch('info',function (newVal,oldVal) {console.log(newVal.age);},{ deep:true,immediate: true })</script>
</html>

效果:

6.2、vm.$set( target, propertyName/index, value ) 

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index
    • {any} value
  • 返回值:设置的值。

  • 用法:这是全局 Vue.set 的别名。在

  • 参考:Vue.set

6.3、vm.$delete( target, propertyName/index )

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index
  • 用法

    这是全局 Vue.delete 的别名

  • 参考:Vue.delete

7、Vue实例方法-事件(vm.$on、vm.$once、vm.$off、vm.$emit)

7.1、vm.$on( event, callback )

  • 参数

    • {string | Array<string>} event (数组只在 2.2.0+ 中支持)
    • {Function} callback
  • 用法

    监听当前实例上的自定义事件。事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。常用在子组件向父组件派发事件的时候。

7.2、vm.$emit( eventName, […args] )

  • 参数

    • {string} eventName
    • [...args]
  • 用法:触发当前实例上的事件。附加参数都会传给监听器回调。

示例:前面我们接触过v-on指令,v-on:可监听普通dom的原生事件;可监听子组件emit的自定义事件;vm.$on:监听当前实例的自定义事件。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id='app'><button id="emit" @click='emit' >触发事件</button><button id="emitother" @click='emitother' >触发事件</button></div></body><script>new Vue({el: '#app',data:{msg1: "饭后要洗碗",msg2: "周末要一起看电影",msg3: "周末要出去逛街"},created:function(){this.$on('need_wash', this.handleEvent); //实例监听:need_washthis.$on(['need_other','need_wash'], this.handleEvents); //实例监听:need_other、need_wash},methods: {handleEvent:function(es){console.log(this.msg1,es); //},handleEvents:function(es){if(es == "emitother"){console.log("handleEvents:"+this.msg2,es); //console.log("handleEvents:"+this.msg3,es); //}else{console.log("handleEvents:"+this.msg1,es); //}},emit:function(es){this.$emit('need_wash', es.target.id);},emitother:function(es){this.$emit('need_other', es.target.id);}}})</script>
</html>

效果:

7.3、vm.$once( event, callback )

  • 参数

    • {string} event
    • {Function} callback
  • 用法

    监听一个自定义事件,但是只触发一次。一旦触发之后,监听器就会被移除。

7.4、vm.$off( [event, callback] )

  • 参数

    • {string | Array<string>} event (只在 2.2.2+ 支持数组)
    • {Function} [callback]
  • 用法:移除自定义事件监听器。

    • 如果没有提供参数,则移除所有的事件监听器;

    • 如果只提供了事件,则移除该事件所有的监听器;

    • 如果同时提供了事件与回调,则只移除这个回调的监听器。

示例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id='app'><button id="emit" @click='emit' >触发事件</button><button id="emitother" @click='emitother' >触发事件</button></div></body><script>
var vm = new Vue({el: '#app',data:{msg1: "饭后要洗碗",msg2: "周末要一起看电影",msg3: "周末要出去逛街"},created:function(){this.$once('need_wash', this.handleEvent); //只监听一次this.$on(['need_other','need_wash'], this.handleEvents); //实例监听:need_other、need_wash},methods: {handleEvent:function(es){console.log(this.msg1,es); //},handleEvents:function(es){if(es == "emitother"){console.log("handleEvents:"+this.msg2,es); //console.log("handleEvents:"+this.msg3,es); //}else{console.log("handleEvents:"+this.msg1,es); //}},emit:function(es){this.$emit('need_wash', es.target.id);},emitother:function(es){this.$emit('need_other', es.target.id);}}});
//		vm.$off();  //无参数时默认移除所有监听vm.$off('need_other'); //移除事件need_other的所有监听vm.$off('need_wash', vm.handleEvents); //指定只移除这个回调的监听器</script>
</html>

效果:

8、Vue实例方法-生命周期(vm.$mount、vm.$forceUpdate、vm.$nextTick、vm.$destroy)

8.1、vm.$mount( [elementOrSelector] )

  • 参数

    • {Element | string} [elementOrSelector]
    • {boolean} [hydrating]
  • 返回值vm - 实例自身

  • 用法:如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可以使用 vm.$mount() 手动地挂载一个未挂载的实例。

    如果没有提供 elementOrSelector 参数,模板将被渲染为文档之外的的元素,并且你必须使用原生 DOM API 把它插入文档中。

    这个方法返回实例自身,因而可以链式调用其它实例方法。前面已经介绍过。

8.2、vm.$forceUpdate()

    用法:迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

//源码
Vue.prototype.$forceUpdate = function(){const vm = this;if(vm._watcher){vm._watcher.update();}
}//vm._watcher就是实例的watcher,每当组件内依赖的数据发生变化时,都会自动触发实例中_watcher的update方法。
//vm.$forceUpdate是手动通知实例重新渲染。

8.3、vm.$nextTick( [callback] )

  • 参数

    • {Function} [callback]
  • 用法

    将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。

    2.1.0 起新增:如果没有提供回调且在支持 Promise 的环境中,则返回一个 Promise。请注意 Vue 不自带 Promise 的 polyfill,所以如果你的目标浏览器不是原生支持 Promise (IE:你们都看我干嘛),你得自行 polyfill。 

new Vue({// ...methods: {// ...example: function () {// 修改数据this.message = 'changed'// DOM 还没有更新this.$nextTick(function () {// DOM 现在更新了// `this` 绑定到当前实例this.doSomethingElse()})}}
})

8.4、vm.$destroy()

  • 用法

    完全销毁一个实例。清理它与其它实例的连接,解绑它的全部指令及事件监听器。

    会触发 beforeDestroy 和 destroyed 的钩子。

    在大多数场景中你不应该调用这个方法。最好使用 v-if 和 v-for 指令以数据驱动的方式控制子组件的生命周期。

 六、Vue的全局配置与全局API

1、Vue的全局配置

    Vue.config是一个对象,包含 Vue 的全局配置。可以在启动应用之前修改下列属性,这部分用到在做介绍,直接引用官网的。

1.1、silent

  • 类型boolean

  • 默认值false

  • 用法Vue.config.silent = true    -->取消 Vue 所有的日志与警告。

1.2、optionMergeStrategies

  • 类型{ [key: string]: Function }

  • 默认值{}

Vue.config.optionMergeStrategies._my_option = function (parent, child, vm) {return child + 1
}const Profile = Vue.extend({_my_option: 1
})// Profile.options._my_option = 2//自定义合并策略的选项。
//合并策略选项分别接受第一个参数作为父实例,第二个参数为子实例,Vue实例上下文被作为第三个参数传入。

1.3、devtools

  • 类型: boolean

  • 默认值: true (生产版为 false)

  • 用法:

// 务必在加载 Vue 之后,立即同步设置以下内容
Vue.config.devtools = true
//配置是否允许 vue-devtools 检查代码。开发版本默认为 true,生产版本默认为 false。生产版本设为 true 可以启用检查。

1.4、errorHandler

  • 类型Function

  • 默认值undefined

  • 用法

Vue.config.errorHandler = function (err, vm) {
// handle error
}
//指定组件的渲染和观察期间未捕获错误的处理函数。这个处理函数被调用时,可获取错误信息和 Vue 实例。
//Sentry, an error tracking service, provides official integration using this option.

1.5、warnHandler(2.4.0 新增)

  • 类型Function

  • 默认值undefined

  • 用法

Vue.config.warnHandler = function (msg, vm, trace) {// `trace` 是组件的继承关系追踪
}
//为 Vue 的运行时警告赋予一个自定义处理函数。注意这只会在开发者环境下生效,在生产环境下它会被忽略

1.6、ignoredElements 

  • 类型Array<string | RegExp>

  • 默认值[]

  • 用法

Vue.config.ignoredElements = ['my-custom-web-component','another-web-component',// 用一个 `RegExp` 忽略所有“ion-”开头的元素// 仅在 2.5+ 支持/^ion-/
]//须使 Vue 忽略在 Vue 之外的自定义元素 (e.g. 使用了 Web Components APIs)。否则,它会假设你忘记注册全局组件或者拼错了组件名称,从而抛出一个关于 Unknown custom element 的警告。

1.6、keyCodes 

  • 类型{ [key: string]: number | Array<number> }

  • 默认值{}

  • 用法

Vue.config.keyCodes = {v: 86,f1: 112,// camelCase 不可用mediaPlayPause: 179,// 取而代之的是 kebab-case 且用双引号括起来"media-play-pause": 179,up: [38, 87] //给 v-on 自定义键位别名。
}<input type="text" @keyup.media-play-pause="method">

1.7、performance(2.2.0 新增)

  • 类型boolean

  • 默认值false (自 2.2.3 起)

  • 用法:设置为 true 以在浏览器开发工具的性能/时间线面板中启用对组件初始化、编译、渲染和打补丁的性能追踪。只适用于开发模式和支持 performance.mark API 的浏览器上。

1.8、productionTip(2.2.0 新增)

  • 类型boolean

  • 默认值true

  • 用法:设置为 false 以阻止 vue 在启动时生成生产提示。

2、全局API

    Vue的全局API提供大量的功能。

2.1、Vue.extend( options )

  • 参数

    • {Object} options
  • 用法

    使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

    data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数。其主要用来服务于Vue.component,用来生成组件。

    Vue.extend(),说白了,有点类似java中的继承(父类与子类)的关系。extend,这个词对我们来说并不陌生,jQuery为开发插件就提供了两个方法(.jQuery.extend(object)、jQuery.fn.extend(object)); 前者为扩展jQuery类本身,后者为自身添加新的方法。Vue.extend()会返回一个子(Sub)构造函数,Sub类似于继承了Vue构造函数。

示例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body></body><script>const Com = Vue.extend({template: '<h1 @click="handleClick">{{msg}}</h1>',data:function(){ //必须是函数return {msg: 'Hello Vue.extend'}},methods: {handleClick:function(){this.msg = this.msg.split('').reverse().join('')}}})var vmfb = new Com();document.body.appendChild(vmfb.$mount().$el);console.log(vmfb.$data.msg);//Hello Vue.extendconsole.log(vmfb.$options);</script>
</html>

效果:

2.2、Vue.nextTick( [callback, context] )

  • 参数

    • {Function} [callback]
    • {Object} [context]
  • 用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

    Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><h id="h">{{msg}}</h><button @click = "changeTxt">改变值</button></div></body><script>var vm = new Vue({el: "#app",data: {msg: "Hello nextTick"},methods: {//$nextTick方法changeTxt: function() {this.msg = "Hello nextTick Update"; //修改dom结构this.$nextTick(function() { //使用vue.$nextTick()方法可以dom数据更新后延迟执行后续代码var domTxt = document.getElementById('h').innerText;console.log(domTxt); //输出可以看到vue数据修改后并没有DOM没有立即更新if(domTxt === "Hello nextTick") {console.log("文本data被修改后dom内容没立即更新");} else {console.log("文本data被修改后dom内容被马上更新了"); //输出结果}});}}})//全局方法:nextTickvm.msg = "Hello nextTick 全局方法"var domTxt = document.getElementById('h').innerText; //这个时候去操作DOM某些数据可能会无效console.log(domTxt); //hello nextTick  这个时候并未取到新更新的值Vue.nextTick(function () {// DOM 更新了var domTxt = document.getElementById('h').innerText; //这个时候就是最新的了console.log(domTxt); //Hello nextTick 全局方法})</script>
</html>

效果:

2.3、Vue.set( target, propertyName/index, value )

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index
    • {any} value
  • 返回值:设置的值。

  • 用法:向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property (比如 this.myObject.newProperty = 'hi')。 

    受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue转换它,才能让它是响应的。如:给对象新增一个data中没有的属性,或者通过数组下标新增时都无法让视图刷新。这时,就可以使用Vue.set()或者this.$set()

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title></head><body></body><!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><div v-for="(item,index) in msg" :key="index"><div v-if="index == 3"><!--双重循环遍历--><li v-for="(it,i) in item" :key="i">{{i+'-'+it}}</li></div><div v-else>{{index+'-'+item}}</div></div><button @click="changedata">方法中添加属性</button></div></body><script>var sz = ["1","2","3",{name:"老王",age:18,sex:"男"}];var vm = new Vue({el: "#app",data: {msg:sz},methods: {changedata: function() {this.msg[3].job = "自由职业new";//this.msg.push("5");  //使用这个方法会更新,因为vue重写了数组的操作方法//this.$set(this.msg,1,'two');console.log(sz);}}})//视图不会更新vm.msg[4] = "4"; vm.msg[3].job = "自由职业";console.log(vm.msg);
//		Vue.set(vm.msg, 1, 'two'); </script>
</html>

效果:

2.4、Vue.delete( target, propertyName/index )

  • 参数

    • {Object | Array} target
    • {string | number} propertyName/index

    仅在 2.2.0+ 版本中支持 Array + index 用法。目标对象不能是一个 Vue 实例或 Vue 实例的根数据对象。

  • 用法

    删除对象的 property。如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开 Vue 不能检测到 property 被删除的限制,但是你应该很少会使用它。这个与set是反向的操作。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title></head><body></body><!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"><div v-for="(item,index) in msg" :key="index"><div v-if="index == 3"><!--双重循环遍历--><li v-for="(it,i) in item" :key="i">{{i+'-'+it}}</li></div><div v-else>{{index+'-'+item}}</div></div><br /><button @click="changedata">方法中添加属性</button></div></body><script>var sz = ["1","2","3",{name:"老王",age:18,sex:"男"}];var vm = new Vue({el: "#app",data: {msg:sz},methods: {changedata: function() {this.msg[3].job = "自由职业new";
//					this.msg.push("5");  //使用这个方法会更新,因为vue重写了数组的操作方法delete this.msg[4];
//					this.$delete(this.msg[4]);console.log(sz);}}})//视图不会更新sz[4] = "4";sz[5] = "5";console.log(vm.msg);
//		Vue.delete(vm.msg,4); //删除4</script>
</html>

效果:

2.5、Vue.directive( id, [definition] ) 

  • 参数

    • {string} id
    • {Function | Object} [definition]
  • 用法:注册或获取全局指令。

// 注册全局
Vue.directive('my-directive', {bind: function () {},inserted: function () {},update: function () {},componentUpdated: function () {},unbind: function () {}
})// 注册 (指令函数)
Vue.directive('my-directive', function () {// 这里将会被 `bind` 和 `update` 调用
})// getter,返回已注册的指令
var myDirective = Vue.directive('my-directive')//注册局部
directives: {focus: {// 指令的定义inserted: function (el) {el.focus()}}
}

    前面我们用过很多v-指令。在Vue2.x 中,代码复用和抽象的主要形式是组件。然而,有的情况下,我们仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。

举个简单的栗子:设置一个焦点

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id='app'>{{msg}}聚焦:<input v-focus type="text" /></div></body><script>// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()}})var vm = new Vue({el:"#app",data:{msg:"vue directive"}})</script>
</html>

    上面我们使用到了一个钩子函数:inserted,一个指令定义对象可以提供如下几个钩子函数 (均为可选):

指令钩子函数:

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

  • unbind:只调用一次,指令与元素解绑时调用。

钩子函数参数:

指令钩子函数会被传入以下参数:

  • el:指令所绑定的元素,可以用来直接操作 DOM。
  • binding:一个对象,包含以下 property:
    • name:指令名,不包括 v- 前缀。
    • value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2
    • oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"
    • arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"
    • modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }
  • vnode:Vue 编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id='app'>{{msg}}聚焦:<input id="txt" v-focus v-model="msg" type="text" /></div></body><script>// 注册一个全局自定义指令 `v-focus`Vue.directive('focus', {bind: function(el, binding, vnode){//只需要执行一次的一些操作el.style.background="#FFFDD6";console.log("我是bind");},// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus();console.log("我是inserted"); },update: function(){//根据获得的新值执行对应的更新console.log("我是update");  },componentUpdated: function(){//指令所在组件的 VNode 及其子 VNode 全部更新后调用console.log("我是componentUpdated");  },unbind: function(){//做清理操作//比如移除bind时绑定的事件监听器console.log("我是unbind");}})var vm = new Vue({el:"#app",data:{msg:"vue directive"}})</script>
</html>

效果:

2.6、Vue.filter( id, [definition] )

  • 参数

    • {string} id
    • {Function} [definition]
  • 用法:注册或获取全局过滤器。

//全局注册
// 注册
Vue.filter('my-filter', function (value) {// 返回处理后的值
})// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')//局部注册
filters:{myFilter:function(value){value+='hello world'return value}
}

     Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示:

<!-- 在双花括号中 -->
{{ message | capitalize }}<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div><!-- 过滤器可以串联,也可以接收参数 -->
{{ message | filterA | filterB }}{{ message | filterA('arg1', arg2) }}

过滤器原理简述:

{{message|myFilter}}//这个过滤器在模板编译后_s(_f('myFilter')(message))//_f这个函数是resolveFilter的别名:找到我们写的过滤器,并将参数传入进去并执行//_s函数是toString函数的别名

示例:

<!DOCTYPE html>
<html><head><meta charset="utf-8" /><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id='app'>全局/局部过滤器:<input v-model="message"/>{{ message | capitalize | capitalizes}}<br />过滤器搜索:<input type="text" placeholder="请输入搜索内容" v-model="isSearch"><div v-for="(item,index) in search" :key="index">{{ item.name }}</div></body><script>//注册全局过滤器Vue.filter('capitalize', function (value) {if (!value) {return '';}value = value.toString();return value.charAt(0).toUpperCase() + value.slice(1);})new Vue({el: '#app',data: {message:"hello vue",list: [ {id: '1',name: 'AAA'},{id: '2',name: 'BBB'},{id: '3',name: 'CCC'},{id: '4',name: 'AAA'},{id: '5',name: 'BBB'},{id: '6',name: 'DDD'}],isSearch: '' //},//局部过滤器,如果同名则会覆盖全局的filters: {capitalizes: function (value) {if (!value){return ''}value = value.toString()return value.slice(0,5)+value.charAt(6).toUpperCase() + value.slice(7);}},//实现搜索功能computed: {search:function(){var arr=[];for (var i=0;i<this.list.length;i++) {if(this.list[i].name.indexOf(this.isSearch)!=-1){arr.push(this.list[i]);}}console.log(arr);return arr;}}})</script>
</html>

效果:

 2.7、Vue.use( plugin )

  • 参数

    • {Object | Function} plugin
  • 用法

    安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

    该方法需要在调用 new Vue() 之前被调用。

    当 install 方法被同一个插件多次调用,插件将只会被安装一次。

2.8、Vue.compile( template )

  • 参数

    • {string} template
  • 用法:将一个模板字符串编译成 render 函数。只在完整版时可用

    compile 的内容非常多,大致分为三块主要内容,我也称他们是Vue的 渲染三巨头,就是: parse,optimize,generate。

    Parse的作用:接收 template 原始模板,按照模板的节点和数据生成对应的 ast(一种语法树)

    Optimize的作用:遍历递归每一个ast节点,标记静态的节点。减少去比对这部分DOM,从而达到性能优化的目的。

    Generate的作用:把前两步生成完善的 ast 组装成 render 字符串。

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title></title><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></head><body><div id="app"></div></body><script>var res = Vue.compile('<div><span>{{ msg }}</span></div>')new Vue({data: {msg: 'hello vue compile'},render: res.render,staticRenderFns: res.staticRenderFns}).$mount("#app");</script>
</html>

效果:

2.8、Vue.observable( object ) (2.6.0 新增)

  • 参数

    • {Object} object
  • 用法

    让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

    返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器,用于简单的场景:

const state = Vue.observable({ count: 0 })const Demo = {render(h) {return h('button', {on: { click: () => { state.count++ }}}, `count is: ${state.count}`)}
}

    在 Vue 2.x 中,被传入的对象会直接被 Vue.observable 变更,所以如这里展示的,它和被返回的对象是同一个对象。在 Vue 3.x 中,则会返回一个可响应的代理,而对源对象直接进行变更仍然是不可响应的。因此,为了向前兼容,我们推荐始终操作使用 Vue.observable 返回的对象,而不是传入源对象。

2.9、Vue.version

  • 细节:提供字符串形式的 Vue 安装版本号。这对社区的插件和组件来说非常有用,你可以根据不同的版本号采取不同的策略。

  • 用法

var version = Number(Vue.version.split('.')[0])if (version === 2) {// Vue v2.x.x
} else if (version === 1) {// Vue v1.x.x
} else {// Unsupported versions of Vue
}

2.10、Vue.mixin( mixin )

  • 参数

    • {Object} mixin
  • 用法

    全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用

2.11、Vue.component( id, [definition] )

  • 参数

    • {string} id
    • {Function | Object} [definition]
  • 用法:注册或获取全局组件。注册还会自动使用给定的 id 设置组件的名称

// 注册组件,传入一个扩展过的构造器
Vue.component('my-component', Vue.extend({ /* ... */ }))// 注册组件,传入一个选项对象 (自动调用 Vue.extend)
Vue.component('my-component', { /* ... */ })// 获取注册的组件 (始终返回构造器)
var MyComponent = Vue.component('my-component')

    在Vue2.x 中,代码复用和抽象的主要形式是组件。关于组件、路由、过渡动画、vue脚手架等内容将在后续文章中介绍。^_^

查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. React最小系统的搭建

    与Angular、Vue.js和微信小程序等开发一样&#xff0c;React也是一门数据驱动的语言&#xff08;相对而言的dom驱动代表是jquery&#xff09;&#xff0c;其中Angular、Vue和React又称是新兴框架的三巨头。总的来说&#xff0c;React和Angular、Vue等的模式类似&#xff0c;一要…...

    2024/4/21 15:43:13
  2. ionic2入门

    最近公司准备使用angular4ionic2开做移动端开发&#xff0c;因此我暂时放下了之前的vue&#xff0c;现在在学习ionic和angular&#xff0c;把自己总结的一些东西在此和大家分享一下 1、创建一个ionic的项目 1.1 安装环境 1) 安装node&#xff0c;地址为https://nodejs.org/en/…...

    2024/4/23 9:28:35
  3. Vue学习手册(一)-----脚手架初体验

    本页目录一、简介二、初始配置2.1. 安装node2.2 安装Vue脚手架2.2.1 项目初始化2.2.2 项目测试三、项目结构四、改造并初始化4.1 清除无用文件4.2 修改有用文件内容4.2.1 基本4.2.2 核心文件五、最终展示页面六、调试一、简介 Vue简介&#xff1a;Vue为web编程前端三大框架之一…...

    2024/5/4 16:43:30
  4. 华亚双眼皮割的太深可以修复吗

    ...

    2024/4/21 15:43:10
  5. React学习(1)-create-react-app

    前言 如今,对于现今前端热门的三大框架Vue,Angular,React,对于web开发者来说,早已不是什么陌生的词 尽管三者实现业务最终的目的都能达成一致,但是各有特色,其中任何一框架,个人觉得,都博大精深,可圈可点,要学习的内容有很多,我也仅仅是浅尝辄止而已. 有时候,因为工作项目的需要…...

    2024/4/21 15:43:08
  6. ionic环境搭建详细步骤

    ionic环境搭建详细步骤 环境搭建步骤&#xff1a; 1、安装node.js 这是为了使用npm来安装ant&#xff0c;cordova&#xff0c;ionic 验证是否安装好node.js的方法是在命令提示符中输入“node -v” 若出现版本号&#xff0c;证明安装成功。 nodejs 中文网站 http://nodejs…...

    2024/4/21 15:43:07
  7. vue知识点总结

    1 ### Vue.js 五天 1 ### Vue.js 五天 2 3 ## 一、 组件component4 5 ### 1. 什么是组件&#xff1f;6 组件&#xff08;Component&#xff09;是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素&#xff0c;封装可重用的代码7 组件是自定义元素&#xff08;对象&am…...

    2024/5/5 17:22:00
  8. ionic-最全常用命令

    文章目录一、常用命令一、常用命令 安装脚手架 npm i -g ionic/cli安装ionic npm install -g ionic查看ionic版本 ionic -v创建ionic不同骨架的项目 // 这边需要重点关注&#xff0c;每个版本的cli创建项目的命令都不尽相同 // 在ionic-cli3的版本中创建ionic2的项目 默认是ta…...

    2024/5/1 15:16:18
  9. 割双眼皮医院价格

    ...

    2024/4/21 15:43:05
  10. 全切双眼皮开眼角正在恢复

    ...

    2024/4/25 6:59:13
  11. 双眼皮全切手术日记

    ...

    2024/4/20 14:50:24
  12. 开眼角全切双眼皮恢复日记

    ...

    2024/5/4 15:36:56
  13. Angular 路由和传值

    一、路由和传值 跳转和传值 <ul><li *ngFor"let item of list;let keyindex;"><a [routerLink]"[/newscontent]" [queryParams]"{aid:key}">{{key}} --- {{item}}</a></li> </ul> 接收 import { Compone…...

    2024/4/28 3:26:12
  14. 开扇形双眼皮明星

    ...

    2024/5/4 14:38:56
  15. 埋线双眼皮会越来越小吗

    ...

    2024/4/21 15:43:02
  16. 双眼皮胶水 埋线

    ...

    2024/5/4 18:35:43
  17. 全切双眼皮拆线前后

    ...

    2024/4/24 11:54:33
  18. 江苏省人民医院三点定位双眼皮拆除后多久能修复

    ...

    2024/4/21 6:09:06
  19. 双眼皮眼睛小怎么办

    ...

    2024/4/21 15:42:59
  20. 虞城哪里双眼皮做得好

    ...

    2024/4/21 15:42:58

最新文章

  1. RK3568平台(基础篇)linux错误码

    一.概述 linux应用程序开发过程中&#xff0c;经常会遇到一些错误信息的返回&#xff0c;存在的可能性有&#xff0c;参数有误、非法访问、系统资源限制、设备/文件不存在、访问权限限制等等。对于这类错误&#xff0c;可以通过perror函数输出具体描述&#xff0c;或者通过str…...

    2024/5/5 19:26:30
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. MongoDB初探:安装与图形化界面保姆级使用指南

    文章目录 前言一、MongoDB下载安装下载解压配置环境变量打开mongoDB 二、配置本地MongoDB服务创建文件下载服务测试服务 三、图形化界面Compass GUINavicat GUI 总结 前言 MongoDB是一种流行的开源、面向文档的NoSQL数据库程序。与传统的关系型数据库不同&#xff0c;MongoDB将…...

    2024/5/4 12:21:04
  4. 从头开发一个RISC-V的操作系统(二)RISC-V 指令集架构介绍

    文章目录 前提ISA的基本介绍ISA是什么CISC vs RISCISA的宽度 RISC-V指令集RISC-V ISA的命名规范模块化的ISA通用寄存器Hart特权级别内存管理与保护异常和中断 目标&#xff1a;通过这一个系列课程的学习&#xff0c;开发出一个简易的在RISC-V指令集架构上运行的操作系统。 前提…...

    2024/5/5 1:33:57
  5. C# 抽象类、接口

    &#xff08;1&#xff09;、抽象类和抽象方法的定义和实现&#xff1a;abstract override abstract class Vehicle{ public abstract void Run(); } 继承抽象类并且实现抽象方法 class RaceCar : Vehicle{ public override void Run(){ } } &#xff08;2&#xff09;、接口的…...

    2024/5/5 8:37:24
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/4 23:54:56
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/4 23:54:56
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/5/4 23:54:56
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/4 23:55:17
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/5/4 23:54:56
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/5/4 23:55:05
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/5/4 23:54:56
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/5/4 23:55:16
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/5/4 23:54:56
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/4 18:20:48
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/5/4 23:54:56
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/5/4 23:55:17
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/5/4 23:55:06
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/5/4 23:54:56
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/4 23:55:06
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/5/5 8:13:33
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/5/4 23:55:16
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/5/4 23:54:58
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/4 23:55:01
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/5/4 23:54:56
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57