VUE完整系统简介

简介: VUE完整系统简介

一. 认识Vuejs



  1. 为什么学习Vuejs


  • 这几年Vue.js成为前端框架中最火的一个。越来越多的网站前端开始采用Vue.js开发。前端开发必备技能.
  • Vuejs是开源世界华人的骄傲,其作者是我国尤雨溪。学习门槛低,成本低,可跨设备和多平台开发Vue.js.
  • 前端换工作, 面试必问的框架.


  2. 简单认识一下Vuejs


  • 官网地址: https://cn.vuejs.org/
  • 是一套用于构建用户界面的渐进式框架, 什么是渐进式框架呢?

        渐进式框架是说, vue可以作为应用的一部分嵌入.

        比如:之前项目使用的是jquery开发的, 项目体量比较大, 现在知道vue使用上,效果上都更方便, 想要替换为vue, 可问题是之前的页面特别多,如果全部替换,工作量太大,那么没关系, vue允许你部分嵌入, 也就是说原来的页面依然使用jquery, 而后开发的页面使用Vuejs. vue可以作为一部分嵌入到项目中. 后面再逐渐替换.

  • 如果是使用vue开发新项目, 那么可以使用vue的全家桶. 包括核心库和和生态系统. 比如: Core+Vue Router + Vuex.


  3. Vuejs的核心功能


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


二. Vuejs安装方式



vuejs的安装有三种方式,


  1. CDN引入


  • CDN引入有两个版本: 开发环境和生产环境. 也就是说, 不用本地安装vue, 而是引入CDN中vue的包


<!-- 开发环境 -->
<script src= "https://cdn.jsdelivr.net/npm/vue/dist/vue.js></script>
<!-- 生产环境 -->
<script src= "https://cdn.jsdelivr.net/npm/vue/vue.js></script>生产环境建议带上版本号, 避免因版本问题产生异常<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>


  • 使用这个版本的优点是: 速度快. 缺点也很明显: 那就是每次打开都要去cdn上下载, 浪费时间. 学习不建议使用这种方式


  2. 下载和引入


  • 这里也有两个版本, 开发环境和生产环境, 在CDN上下载很慢, 那么我们可以将vue.js下载到本地, 引入到项目中


开发环境
https://vuejs.org/js/vue.js
生产环境
https://vuejs.org/js/vue.min.js
  • 开发时可以使用开发包, 可以看到源码. 生产环境的包更稳定, 体积也会更小


  3. NPM安装管理


  • 在用 Vue 构建大型应用时推荐使用 NPM 安装
  • vuejs可以和webpack和CLI等模块配合使用
  • 后续学习都是用这种方式操作的.


三. Vuejs初体验



  1. Hello Vuejs


    我们学习程序, 经典代码helloworld. 这里说一下开发工具, 开发工具建议使用vscode, 因为里面有很多插件, 但是其他也不是不可以哈


    我们在感受vue的时候, 为了简单, 方便的体验vue, 我们使用第二种方式(注: 后面详细研究还是会使用npm编译的方式),下载vue.js, 并引入到项目中. 接下来开始操作.


  • 第一步: 先搭建一个简单的项目. 我的项目名称就叫vue-study. 在里面创建一个文件夹js, 项目结构如下:


1187916-20210218063231364-754708796.png


  • 第二步: 然后下载vue.js, 将其放入到js文件夹中
  • 第三步: 写一个html页面, 并引入vue.js.
<html>
    <head>
        <title>第一个vue程序</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
    </body>
</html>

我们看到, 第一步引入了vue.js. 其实这里有个简单的办法, 只需要把项目中js拖进来, 就可以了.引入了vue.js, 那么要如何使用呢? vue.js我们可以理解为对象. 使用使用new Vue()的方式.

<html>
    <head>
        <title>第一个vue程序</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="app">{{message}}</div>
        <script>
            const app = new Vue({
                el: "#app",
                data: {
                    message: "hello, 盛开的太阳!"
                }
            });
        </script>
    </body>
</html>


  • 如上, 我们看到了new Vue(), 相当于把这个对象构建了一份. 然后赋值给了一个常量const app. 这里需要说一下, 以前,我们都是直接使用var, 既可以设置变量也可以设置常量, 但在vue中, 我们的变量和常量都有自己的声明方式

声明方式:  常量使用const, 变量使用let.


  • 创建vue对象的时候, 传入了一个option, option中有两个元素

el:全称element, 表示指向的元素.其值使用的是jquery表达式. 该属性决定了这个vue对象挂载到那个元素上, 可以看出, 我们这里是挂载到了id="app"的元素上


data: 这个属性用来存储数据, 这些数据可以试试手动写的, 也可以是动态从服务端取的


  • data定义数据. 这里需要重点说一下了. vue采用的是VMMV的设计模式, 也就是数据和试图分离. 这里的data指的就是数据. 而id="app"的div是视图. 当页面解析的时候, 解析到script脚本时发现, 我们已经将div交给vue容器了, 那么, 这时候, vue就会去寻找目标元素是否有待填补的变量. 这里我们看到<div id="app">{{message}}</div>里面定义了一个变量message, 而这个变量在vue容器中进行了声明, 因此可以进行对应的自动填充.
    这里如果暂时不理解, 也没关系, 先混个眼熟, 后面还有详细讲解


  • 第四步: 分析浏览器执行代码的流程
<html>
    <head>
        <title>第一个vue程序</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="app">{{message}}</div>
        <script>
            const app = new Vue({
                el: "#app",
                data: {
                    message: "hello, 盛开的太阳!"
                }
            });
        </script>
    </body>
</html>
  • 页面渲染, 首先加载1-10行, 显示出对应的html. 执行到第11行的时候, 创建了vue实例, 并且对照html进行解析和修改.


  2. Vue列表展示


    下面来看一个稍微复杂一点的例子---列表展示

    先来看看效果


1187916-20210218073907239-100167422.png下面思考, 如果我们使用jquery会如何实现呢? 需要些一个for循环, 然后在里面定义n个li, 然后拼装数据. 很复杂.  然而, 使用vue完全不需要在js代码中拼装html元素的数据, 下面来看看怎么做


  • 第一步: 新建一个html页面, 命名为02-list.html, 然后引入vue.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>列表页面</title>
    <script src="../js/vue.js"></script>
</head>
<body>
</body>
</html>

第二步构建vue对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        <h1>{{title}}</h1>
        <ul>
            <li v-for = "item in languages">{{item}}</li>
        </ul>
    </div>
    <script>
        const app = new Vue({
            el: "#app",
            data:{
                title: "常见的后端编程语言有哪些?",
                languages: ["python", "go", "java", "net", "php", "c++"]
            }
        });
    </script>
</body>
</html>

这里指定了当前构建的vue对象挂载在id="app"的元素上. 并填充值title和languages. 和上一个案例不同, 这里有一个数组元素languages. 那么数组元素应该如何取值呢?

<ul>
    <li v-for = "item in languages">{{item}}</li>
</ul>

注意红色粗体部分. 使用了一个vue的指令v-for, 这是表示for循环, 这个第一次见到, 先熟悉一下. 后面还会具体讲. 我们以前使用jquery会怎么写呢?

<ul>
    <li >python</li>
    <li >go</li>
    <li >java</li>
    <li >php</li>
    <li >.net</li>
    <li >...</li>
</ul>


  • 以前我们要这么写一大堆, 如果是动态从服务端取数据, 那么还要拼li代码, 很容易出错, 还很费劲. 但使用了vue指令, 我们发现一句话就搞定了, 这里是不是可以傲娇一下. 怪不得vue能这么流行.

  3. 案例:计数器


    计数器是一个小的综合案例, 通过这个案例来再次感受一下vue的强大. 我们先来看一下效果


1187916-20210218114219783-1813186113.png


分析: 这里有一个变量, 两个按钮. 点击+, 数字加1, 点击-, 数字减1. 下面我们就来实现这个功能

  • 第一步: 创建一个html文件03-计数器.html 


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        当前数字: {{counter}}
        <br>
        <button v-on:click="counter++"> + </button>
        <button v-on:click="counter--"> - </button>
    </div>
    <script>
        const app  = new Vue({
            el: "#app",
            data:{
                counter: 0
            }
        });
    </script>
</body>
</html>

引入vue.js, 并创建一个Vue对象. 这些之前都说过, 就不多说了. 接下来看看

<button v-on:click="counter++"> + </button
  • 这是什么意思呢? 这是vue的写法. v-on是vue的指令, 这里先有个印象, 后面会详细讲解. v-on表示要执行一个事件, :click就是具体的事件, 这里是点击事件, 点击后执行什么逻辑呢? 执行counter ++. 是不是很神奇? 也许还没有感觉, 那么我们来看看, 如果是jQuery, 要怎么做吧?


1. 给+按钮添加一个点击事件

2. 获取counter计数器对象的值

3. 对counter进行++

4. 再讲counter计算后的结果赋值给计数器对象.


  • 现在感受到了吧, jquery是命令式编程, 一行命令执行一个语句. 这里要执行好几句话, 而vue一句话就搞定了.
     
  • 第二步: 这里click事件中就有一句话, counter++, 那么要是有好多逻辑怎么办呢? 那需要提出来单独处理了.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="../js/vue.js"></script>
</head>
<body>
    <div id="app">
        当前数字: {{counter}}
        <br>
        <button v-on:click="add"> + </button>
        <button v-on:click="sub"> - </button>
    </div>
    <script>
        const app  = new Vue({
            el: "#app",
            data:{
                counter: 0
            },
            methods: {
                add: function() {
                    console.info("add方法被执行")
                    this.counter ++;
                },
                sub: function () {
                    console.info("sub方法被执行")
                    this.counter --;
                }
            }
        });
    </script>
</body>
</html>
  • 在vue里面,要想增加一个事件, 那就放在methods属性里就可以了. 这里有一点需要注意. 在方法里要对data中的变量执行counter ++, 直接这么写是不行的, 需要加上this.counter++. this表示的是new出来的Vue对象. 有朋友可能就要说了, this在方法里面, 不应该是表示当前方法么?vue做了一层代理, 所以, 这里的this指的是new Vue()对象.  


四. Vuejs的MVVM



  1. 什么是MVVM


    MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。View绑定到ViewModel,然后执行一些命令在向它请求一个动作。而反过来,ViewModel跟Model通讯,告诉它更新来响应UI。这样便使得为应用构建UI非常的容易。


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


  2. MVVM的优点


    MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大优点

  • 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
  • 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
  • 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
  • 可测试。界面素来是比较难于测试的,测试可以针对ViewModel来写。

 

  3. MVVM模式的组成部分


  • 模型

      模型是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。

  • 视图

      就像在MVCMVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观(UI)。

  • 视图模型

      视图模型是暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器之间进行通信。

  • 绑定器
    声明性数据和命令绑定隐含在MVVM模式中。绑定器使开发人员免于被迫编写样板逻辑来同步视图模型和视图。在微软的堆之外实现时,声明性数据绑定技术的出现是实现该模式的一个关键因素


  4. Vue中的VMMV


    下图不仅概括了MVVM模式(Model-View-ViewModel),还描述了在Vue.js中ViewModel是如何和View以及Model进行交互的。

1187916-20210219050939915-1485402147.png ViewModel是Vue.js的核心,它是一个Vue实例。Vue实例是作用于某一个HTML元素上的,这个元素可以是HTML的body元素,也可以是指定了id的某个元素。


    当创建了ViewModel后,双向绑定是如何达成的呢?


    首先,我们将上图中的DOM Listeners和Data Bindings看作两个工具,它们是实现双向绑定的关键。


    从View侧看,ViewModel中的DOM Listeners工具会帮我们监测页面上DOM元素的变化,如果有变化,则更改Model中的数据;


    从Model侧看,当我们更新Model中的数据时,Data Bindings工具会帮我们更新页面中的DOM元素。


    拿第一个案例来说


<html>
    <head>
        <title>第一个vue程序</title>
        <script src="../js/vue.js"></script>
    </head>
    <body>
        <div id="app">{{message}}</div>
        <script>
            const app = new Vue({
                el: "#app",
                data: {
                    message: "hello, 盛开的太阳!"
                }
            });
        </script>
    </body>
</html>

在这里, 定义了一个View, 定义了model, 创建了一个Vue实例(view-model), 它用于连接view和model


在创建Vue实例时,需要传入一个选项对象,选项对象可以包含数据、挂载元素、方法、模生命周期钩子等等。


在这个示例中,选项对象的el属性指向View,el: ‘#app’表示该Vue实例将挂载到<div id="app">...</div>这个元素;data属性指向Model,data: { message: "hello, 盛开的太阳" 表示我们的Model是一个对象。


Vue.js有多种数据绑定的语法,最基础的形式是文本插值,使用一对大括号语法,在运行时{{ message }}会被数据对象的message属性替换,所以页面上会输出”hello, 盛开的太阳!”。

 

五. Vue实例的生命周期



每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

比如 created 钩子可以用来在一个实例被创建之后执行代码:

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` 指向 vm 实例
    console.log('a is: ' + this.a)
  }
})
// => "a is: 1"

也有一些其它的钩子,在实例生命周期的不同阶段被调用,如 mountedupdateddestroyed。生命周期钩子的 this 上下文指向调用它的 Vue 实例。


注意:


不要在选项 property 或回调上使用箭头函数,比如

 created: () => console.log(this.a) 或 vm.$watch('a', newValue => this.myMethod())。

因为箭头函数并没有 thisthis 会作为变量一直向上级词法作用域查找,直至找到为止,经常导致

Uncaught TypeError: Cannot read property of undefined 或

Uncaught TypeError: this.myMethod is not a function 之类的错误。


 

1. 生命周期图示


下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它的参考价值会越来越高。

1187916-20210219061532116-1196518192.png



2. Vue生命周期函数


如上图, 常用的生命周期函数有: beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestory, destoryed, 这些钩子函数都是回调函数, 在vue生命周期执行过重,方便用户操作控制的入口

 

六. Vue源码


我们知道了vue的生命周期了, 接下来看看vue的源码, 对vue的生命周期加深理解

源码下载地址: https://github.com/vuejs/vue

我们选择一个release版本. 下载代码到本地

1187916-20210219063113576-1738388427.png


下载好以后, 打开项目, 我们来看看项目结构.


image.png

刚开始, 我们不熟悉, 那么先猜测一下, 哪个是主要文件, 经验告诉我们, src里面的才是主目录, 在src中和核心目录是core.

1187916-20210219063516344-2115161360.png

我们看到了index.js, 通常一个网站的入口是index.html, 而对应的js脚本就是index.js. 打开index.js


import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
initGlobalAPI(Vue)
Object.defineProperty(Vue.prototype, '$isServer', {
  get: isServerRendering
})
Object.defineProperty(Vue.prototype, '$ssrContext', {
  get () {
    /* istanbul ignore next */
    return this.$vnode && this.$vnode.ssrContext
  }
})
// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
  value: FunctionalRenderContext
})
Vue.version = '__VERSION__'
export default Vue

这里面有两句非常重要的话, 第一句

export default Vue

这句话表示export导出Vue, 我们new的就是这里导出的Vue. 我们看到index.js中没有主逻辑, 那主逻辑在哪里呢? 在第二句话里面:

import Vue from './instance/index'

导入了./instance/index中的文件. 我们来看看这个文件

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }
  this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue

首先, 我们看到定义了一个Vue对象, 在对象里面执行了很多操作, 初始化, 事件监听, 生命周期处理, 渲染等等. 这就是vue的整个流程. 我们进入到initMixin(Vue)初始化方法里面看一下

/* @flow */
import config from '../config'
import { initProxy } from './proxy'
import { initState } from './state'
import { initRender } from './render'
import { initEvents } from './events'
import { mark, measure } from '../util/perf'
import { initLifecycle, callHook } from './lifecycle'
import { initProvide, initInjections } from './inject'
import { extend, mergeOptions, formatComponentName } from '../util/index'
let uid = 0
export function initMixin (Vue: Class<Component>) {
  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    // a uid
    vm._uid = uid++
    let startTag, endTag
    /* istanbul ignore if */
    if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
      startTag = `vue-perf-start:${vm._uid}`
      endTag = `vue-perf-end:${vm._uid}`
      mark(startTag)
    }
    // a flag to avoid this being observed
    vm._isVue = true
    // merge options
    if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {
      initProxy(vm)
    } else {
      vm._renderProxy = vm
    }
    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
   ......


初始化的时候又做了一系列的操作. 注意在方法创建之前有一个钩子函数callHook(vm, 'beforeCreate'),  方法创建之后, 有一个callHook(vm, 'created')函数, 这里可以和上面的生命周期图对比研究, 就能更加熟悉Vue的声明周期了

相关文章
|
1天前
|
存储 JavaScript 前端开发
【Vue】绝了!这生命周期流程真...
【Vue】绝了!这生命周期流程真...
|
1天前
|
JavaScript 索引
【vue】框架搭建
【vue】框架搭建
6 1
|
1天前
|
JavaScript 前端开发 容器
< 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>
Vue 的 `Transition` 和 `TransitionGroup` 是用于状态变化过渡和动画的组件。`Transition` 适用于单一元素或组件的进入和离开动画,而 `TransitionGroup` 用于 v-for 列表元素的增删改动画,支持 CSS 过渡和 JS 钩子。
< 每日小技巧: 基于Vue状态的过渡动画 - Transition 和 TransitionGroup>
|
1天前
|
JavaScript
【vue】setInterval的嵌套实例
【vue】setInterval的嵌套实例
5 1
|
1天前
|
JavaScript 前端开发 安全
【Vue】内置指令真的很常用!
【Vue】内置指令真的很常用!
|
1天前
|
JavaScript
【Vue】过滤器Filters
【Vue】过滤器Filters
|
1天前
|
存储 JavaScript
Vue的状态管理:Vuex的使用和最佳实践
【4月更文挑战第24天】Vue状态管理库Vuex用于集中管理组件状态,包括State(全局状态)、Getters(计算属性)、Mutations(同步状态变更)和Actions(异步操作)。Vuex还支持Modules,用于拆分大型状态树。使用Vuex时,需安装并创建Store,定义状态、getter、mutation和action,然后在Vue实例中注入Store。遵循最佳实践,如保持状态树简洁、使用常量定义Mutation类型、避免直接修改状态、在Actions中处理异步操作、合理划分Modules,以及利用Vuex提供的插件和工具,能提升Vue应用的稳定性和可维护性。
|
1天前
|
资源调度 JavaScript 前端开发
Vue的路由管理:VueRouter的配置和使用
【4月更文挑战第24天】VueRouter是Vue.js的官方路由管理器,用于在单页面应用中管理URL路径与组件的映射。通过安装并引入VueRouter,设置路由规则和创建router实例,可以实现不同路径下显示不同组件。主要组件包括:`&lt;router-link&gt;`用于创建导航链接,`&lt;router-view&gt;`负责渲染当前路由对应的组件。此外,VueRouter还支持编程式导航和各种高级特性,如嵌套路由、路由参数和守卫,以应对复杂路由场景。
|
1天前
|
JavaScript 前端开发 开发者
Vue的响应式原理:深入探索Vue的响应式系统与依赖追踪
【4月更文挑战第24天】Vue的响应式原理通过JavaScript getter/setter实现,当数据变化时自动更新视图。它创建Watcher对象收集依赖,并通过依赖追踪机制精确通知更新。当属性改变,setter触发更新相关Watcher,重新执行操作以反映数据最新状态。Vue的响应式系统结合依赖追踪,有效提高性能,简化复杂应用的开发,但对某些复杂数据结构需额外处理。
|
JavaScript 测试技术 容器
Vue2+VueRouter2+webpack 构建项目
1). 安装Node环境和npm包管理工具 检测版本 node -v npm -v 图1.png 2). 安装vue-cli(vue脚手架) npm install -g vue-cli --registry=https://registry.
982 0