Vue学习笔记(一)

2019-05-29

本文章是阅读https://cn.vuejs.org/v2/guide/官方文档做的笔记

博客的Markdown解释器有些问题,请在Github页面中观看

MVVM模式

Model-View-Viewmodel模式,是前端开发的著名架构模式,将前端的View层和逻辑层、数据层完全解耦,而不像MVC中Controller既需要控制Model,又需要控制View。

MVVM

图来自wiki

  • Model:数据对象模型,或数据访问层,在前端就是大家最喜欢的{}
  • View:指纯布局和外观UI,在前端就是html
  • ViewModel:在View和Model之间进行数据绑定,一般是用框架标记语言完成,在Vue里就是最核心的Vue函数和v-tag做的事。

Vue Hello World

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Vue</title>
   
</head>

<body>
    <div id="app">
        <p></p>
    </div>
    <script src="https://vuejs.org/js/vue.js"></script>
    <script>
        var app = new Vue({
            el:'#app',
            data:{
                message:"helloworld"
            }
        })
    </script>
</body>

</html>
  • 使用new Vue创建的对象称为Vue实例
  • Vue实例通过el属性绑定对应的DOM
  • 通过模板语法将Vue实例中的数据和DOM绑定

Vue实例

一个Vue实例常被看做MVVM中的viewmodel,所以经常出现的变量名字为vm

var vm = new Vue({
  // option object
})

所有的Vue组件都对应一个Vue实例。

option object

定义option object可以配置Vue实例的属性、数据和方法。option object中的this最终会指向Vue实例,而不是Option Object自身。Option Object顶层的对象有以下:

  • 数据data

    var mydata = { a: 1 }
      
    //浅拷贝(只拷贝引用)
    var vm = new Vue({
        data:mydata
    })
      
    //data中的数据会直接赋给vm
    vm.data
    //{a:1}
    

    需要注意的是,仅当定义时的data中的数据才会影响视图的响应式渲染,若后续增加属性,比如vm.b=2,不会触发任何更新。所以对这些后期需要的数据,应在最开始设置空(null)值

    后文中写的XX属性XX:{}都是像data:{}这种形式,省略了

  • 属性

    数据是Vue实例的一种属性,定义Vue实例的属性,只需要在Option Object中定义指定名称的对象属性,比如data。在Vue实例中访问属性,需要加一个$前缀,比如$data。属性还有:

    • $props:组件接受的props对象
    • $el:实例对应的VUE组件根元素
    • $parent:父组件
    • $children:子组件
    • $root:当前组件树(如果是嵌套组件)的根元素
  • 方法

    Vue实例中的方法不要使用带this的箭头函数,显然看Vue实例的创建过程,this的绑定应该会变化,而不是固定指向Option Object。

    方法在methods:{}对象中。

  • 生命周期钩子

    生命周期钩子如created:function()等固定名称的函数,是在实例的固定时间调用的方法。来自官方文档:

Vue模板

Vue使用基于HTML的模板语法进行DOM和Vue实例的绑定,并完成渲染。

插值

插值是指将Vue实例中data的同名属性值插入到HTML DOM中

文本

文本插值使用双大括号语法,将会对html相关字符进行转义。

<span>Message: </span>
  • v-once:一次性插值,不会响应式更新(指实例中的值变化,DOM中的值相应变化)

原始HTML

指令v-html="raw":直接将data.raw渲染为Html(就不需要双大括号语法了)

绑定html特性

指令v-bind

比如绑定id,就是<div v-bind:id="model_id">

JS表达式

JS表达式被双大括号语法和指令语法都支持


<div v-bind:id="'list-' + id"></div>

指令

插值时其实就已经包含一些指令了,比如v-htmlv-bind。语法都是v-name[:option][.modifier][=value]

<p v-if="seen">现在你看到我了</p>
<a v-bind:href="url">...</a>
<a v-on:click="doSomething">...</a>

动态参数

从2.6开始,指令中的option可以动态求值了,语法是用方括号包裹:

<a v-on:[eventname]="doSomething"> ... </a>

动态参数语法有一些限制:

  • 不能有大写字符
  • 不能有空格
  • 不能有引号

    动态参数语法也支持JS表达式,但同样遵循限制

修饰符

修饰符是以[.modifier]指明的后缀,在一些指令中会有用,比如:

<form v-on:submit.prevent="onSubmit">...</form>

.prevent意思是触发事件前先调用event.preventDefault()

缩写

常用指令支持一些缩写语法,比如v-bind:href可以直接写为:href,和完整写没有任何的区别。

计算属性和侦听器

计算属性

Vue例中的属性computed,就是计算属性,形式类似于Getter函数。在模板语法上可以当做有一个同名的数据属性。

在最终视觉效果来看,计算属性和Vue实例中的方法属性method:{}相同,只是模板中不用写()

  <div id="example">
    <p>Original message: ""</p>
    <p>
        Computed reversed message: ""
    </p>
  </div>
  <script>
      var vm = new Vue({
    el: '#example',
    data: {
      message: 'Hello'
    },
    computed: {
      reversedMessage: function () {
        return this.message.split('').reverse().join('')
      }
    }
  })
  </script>

在渲染结果上等价于

  <div id="example">
    <p>Original message: ""</p>
    <p>
        Computed reversed message: ""
    </p>
  </div>
  <script>
    var vm = new Vue({
        el: '#example',
        data: {
            message: 'Hello',
        },
        methods:{
            reversedMessage: function () {
                return this.message.split('').reverse().join('')
            }
        }
    })
  </script>

但和普通方法属性不同的是,计算属性是基于它们的响应式依赖进行缓存的。相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

监听属性

监听属性watch:{},监听数据变动的属性。当数据变化时,调用同名方法。

<div id="demo"></div>
<script>
  var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  },
  watch: {
    firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
    },
    lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
    }
  }
})
</script>

监听属性接近底层,很好用。但在大部分情况下,可以替换为计算属性的写法,从而增加缓存功能提高性能。比如上例可以将fullname属性去掉,用一个计算属性代替。

computed: {
    fullName: function () {
      return this.firstName + ' ' + this.lastName
    }

计算属性的setter

我们定义的计算属性只有一个getter,同样可以定义setter

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}

样式绑定语法

绑定class

对象语法

对象语法为:

<div v-bind:class="{ active: isActive }"></div>
data: {
  isActive: true
}

渲染为:

<div class=active></div>

数组语法

数组语法为:

<div v-bind:class="[activeClass, errorClass]"></div>
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}

渲染为:

<div class="active text-danger"></div>

绑定style(内联样式)

语法与绑定class相同,然而标签为v-bind:style

多重值

多重值用于响应不同的浏览器环境,比如:

<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

会生效最后一个在浏览器中有效的值。