Vue 学习

195 阅读2分钟

Vue 响应式原理

我们或多或少都听过“数据绑定”这个词,“数据绑定”的关键在于监听数据的变化,可是对于这样一个对象:var obj = {value: 1},我们该怎么知道 obj 发生了改变呢?

definePropety

语法

Object.defineProperty(obj, prop, descriptor)

几行代码看他怎么用

var a= {}
    Object.defineProperty(a,"b",{
      value:123
    })
console.log(a.b);//123

参数

obj: 要在其上定义属性的对象。

prop:  要定义或修改的属性的名称。

descriptor: 将被定义或修改的属性的描述符。

举个例子:

var obj = {};
Object.defineProperty(obj, "num", {
    value : 1,
    writable : true,
    enumerable : true,
    configurable : true
});
//  对象 obj 拥有属性 num,值为 1

虽然我们可以直接添加属性和值,但是使用这种方式,我们能进行更多的配置。

函数的第三个参数 descriptor 所表示的属性描述符有两种形式:数据描述符和存取描述符 详细了解

get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。

set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。

这就意味着你可以:

Object.defineProperty({}, "num", {
    value: 1,
    writable: true,
    enumerable: true,
    configurable: true
});

也可以:

var value = 1;
Object.defineProperty({}, "num", {
    get : function(){
      return value;
    },
    set : function(newValue){
      value = newValue;
    },
    enumerable : true,
    configurable : true
});

但是不可以:

// 报错
Object.defineProperty({}, "num", {
    value: 1,
    get: function() {
        return 1;
    }
});

什么是defineProperty

defineProperty 其实并不是核心的为一个对象做数据双向绑定,而是去给对象做属性标签,只不过属性里面的getset实现了响应式。

2020-02-22_025557.png

    var ob = {
        a: 1,
        b: 2
    }
    Object.defineProperty(ob, "a", {
        writable: false
    });
    console.log(Object.getOwnPropertyDescriptor(ob, "a"));

Vue 如何实现双向数据绑定

Vue 基础

前端框架回顾

2020-03-07_144503.png

基于MVC模式的框架

  • Model和View解耦(model和view没有必然的关系)
  • Controller控制DOM
  • 完全照搬MVC模式

基于MVVM模式的框架

  • Model绑定View
  • 没有控制器概念
  • 数据驱动,状态管理

Vue概括以及核心思想

  • vue本身并不是一个框架
  • vue结合周边生态构成一个灵活的、渐进式的框架
    2020-03-07_145232.png

基本语法

获取DOM节点

<div ref="hello">hello world</div>

this.$refs.hello

用is 属性来写组件

//tbody里面要用一个组件,但不能直接用这个组件,所以写了一个tr标签
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>

给组件绑定原生事件

//这样给组件绑定事件不起作用
<child @click="handleClick"></child>

//应该这样加个事件修饰符
<child @click.native="handleClick"></child>

//或这样绑定事件
<div @click="handleClick">child</div>

Vue.js 的目的

Vue的产生核心是为了解决如下三个问题:

  • 数据驱动,解决数据绑定的问题
  • Vue框架产生的主要目的是为了开发大型单页面应用。Vue主要支持移动端,也支持PC端
  • 组件化。将页面封装成若干个组件,采用积木式编程,使页面的复用度达到最高

vue-cli 脚手架

脚手架的使用

vue init webpack project

项目代码结构介绍

  • README.md 项目的说明文件
  • package.json 依赖包(第三方模块的一些依赖)
  • package-lock.json (package的一个锁文件)安装的依赖的具体版本
  • postcssrc 对postcss的一个配置项
  • .gitignore 用git上传代码的管理
  • .editorconfig 编辑器里的一些语法配置

Vue 基础

vue 组件的引入

方法一

import HelloWorld from '@/components/HelloWorld'

方法二

import homeHeader from "./header/header"

MVVM 模式

业务模型model中的数据发生改变的时候,用户视图view也随之变化,用户视图view改变的时候,业务模型model中的数据也发生改变。

  • M:model 业务模型,用处,处理数据,提供数据
  • V:view 用户界面,用户视图

Vue来实现一个TodoList

<div id="app">
    <input type="text" v-model="inputValue">
    <button v-on:click="handleBtnClick">提交</button>
    <ul>
        <li v-for="item in list">{{item}}</li>
    </ul>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            list: [],
            inputValue: ""
        },
        methods: {
            handleBtnClick: function () {
                this.list.push(this.inputValue);
                this.inputValue = "";
            }
        }
    })
</script>

MVP 模式

Presenter层是MVP设计模式里面最核心的一层。它里面放的业务逻辑,是视图和模型层之间的一个中转站。在MVP这种设计模式里面,Presenter层是最核心的,而model层非常边缘。使用这种模式的时候,有大量的代码写在Presenter层里,而这些代码中,很大一部分是DOM操作。在写大型项目的时候,我们用这种设计模式,有70%的代码都是在操作DOM。

M-数据 V-视图 P-控制器

2020-03-02_224837.png

jquery来实现一个TodoList

<input id="input" type="text">
<button id="btn">提交</button>
<ul id="list"></ul>

<script src="https://cdn.bootcss.com/jquery/2.2.1/jquery.min.js"></script>
<script type="text/javascript">
    function Page() {

    }

    $.extend(Page.prototype, {
        init: function () {
            this.bindEvents();
        },
        bindEvents: function () {
            var btn = $("#btn");
            // 将this永久性指向handleBtnClick方法
            btn.on("click", $.proxy(this.handleBtnClick, this));
        },
        handleBtnClick: function () {
            var inputValue = $("#input").val();
            var ulElem = $("#list");
            ulElem.append("<li>" + inputValue + "</li>");
            $("#input").val("");
        },
    });
    
    var page = new Page();
    page.init();
</script>

Vue实例的生命周期钩子

计算属性、方法和侦听器