浅谈Vue.js官方文档

image

最近的工作,需要写点类似自己公司内部bms系统的一些web页面。由于不是对外的,一些简单的页面就交给后端自己来完成。为了符合公司整个前端代码风格,研究了下 Vue.js
Vue.js 官方文档有中文的,整个上手难度也比较低,看完文档再稍加整合下饿了么的 Element 组件基本就能满足大部分像我这样的需要了。js还是啃大学那会用JQuery的老本,并不是很会。自己又习惯做点md笔记,于是干脆在官方文档的基础上加了一点自己的理解,整理出来share一下,再加上本身就是Javaer的角度,很基础,若对看的人有一点点帮助就算有意义了。

打个照面:

  • 自定义标签 嵌入原生HTML标签中去:
Vue.component('todo-item', {
  props: ['todo'],
  template: '
  • {{ todo.text }}
  • ' }) var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { id: 0, text: '蔬菜' }, { id: 1, text: '奶酪' }, { id: 2, text: '随便其它什么人吃的东西' } ] } })

    完了之后调用:

    • 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的:
    var vm = new Vue({
      // 选项
    })
    

    当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

    这个自然也是可以控制的:

    var obj = {
      foo: 'bar'
    }
    
    Object.freeze(obj)
    
    new Vue({
      el: '#app',
      data: obj
    })
    

    这里对foo的任何修改不会生效(后话了 这里应该是涉及到js的浅拷贝和深拷贝问题

    new 出来的Vue实例还会暴露出自己的一些属性和方法:通过这写方法和属性,可以操作对应这个new 出来的实例
    使用 vm.$watch形式来操作,具体参见API

    • Vue实例生命周期:


      image

    上面的生命周期图比较关键,是理解Vue.js很多地方语法结构的助推剂。整体还算比较清晰明了。

    • 一般情况下,使用{{}}引用Vue实例中data域的内容,但是HTML元素标签中并不支持此( {{}} )语法。使用v-bind绑定数据域内内容。(id='xx'形式) 而且{{}}内部支持js语法:
    {{ number + 1 }}
    
    {{ ok ? 'YES' : 'NO' }}
    
    {{ message.split('').reverse().join('') }}
    
    
    • 调用方法去执行计算和调用computed中的方法区别:后者依赖上一次计算后的缓存,只要不需要重新计算(Vue提供支持)就不会重新计算。
    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
    

    上面的代码能同时监听firstName, lastName两个data域值。

    绑定class样式

    这里的绑定比较灵活而且强大:

    这样子灵活的将active类绑定到data里面isActive的true/false身上。

    然后对应的data如下:

    data: {
      classObject: {
        active: true,
        'text-danger': false
      }
    }
    

    可以注意到这里的 class = 后面是一个json格式的对象,那么直接就可以传一个对象进去了:

    data: {
      classObject: {
        active: true,
        'text-danger': false
      }
    }
    

    主要就是这里用json格式来表达一个js对象

    在自定义组件时是一种extend的关系,如下:

    Vue.component('my-component', {
      template: '

    Hi

    ' })
    
    

    其等价于

    Hi


    上面是绑定class相关,大致就是js对象绑定和数组字面量绑定。
    下面是内联样式相关:
    首先仍然是对象语法:

    data: {
      activeColor: 'red',
      fontSize: 30
    }
    

    灵活并且直观。不熟悉弱类型脚本语言的情况下,确实需要时间适应这种松散的语法声明。
    然后就是直接绑定对象:

    data: {
      styleObject: {
        color: 'red',
        fontSize: '13px'
      }
    }
    

    条件渲染

    • 使用template标签(此标签不可见)批量进行渲染:
    
    

    上面的例子中,如果条件成立,页面元素将被渲染出来。但template本身不会显示。

    也有类似于java中的语法:

    A
    B
    C
    Not A/B/C

    使用if else-if else语句,页面渲染时使用的是同一个不显示的template元素。一方面意味高效,另一方面可以实现元素的共用:

    
    
    

    以上代码,实际上是一个template下面的元素。只会渲染其中之一。意味着这里面包裹的元素若是一致的(比如 input ),那么他们在条件变换时也是共用的,即用户在 input 中输入的内容在条件变化过程中不会改变(毕竟是渲染在同一个 input 下的)。
    理解共用的道理比这个语法本身貌似更重要些。
    当然Vue也提供了屏蔽这一细节的处理方式:key绑定

    
    
    

    上面的内容通过key标记的绑定,就可以实现二次渲染。

    • v-show 渲染
      使用 v-show 的元素会被动态切换其css的 display 样式。和上面的动态渲染不同。这个dom元素会始终被渲染在dom树中,只是css样式的变换而已。
      使用如下:

    Hello!

    其也不支持 template 语法。


    列表渲染

    • v-for语句
      类似于java中的 foreach 语法。比较简单:
    • {{ item.message }}
    var example1 = new Vue({
      el: '#example-1',
      data: {
        items: [
          { message: 'Foo' },
          { message: 'Bar' }
        ]
      }
    })
    

    比java好的地方是这里提供一个 index 可选,获取当前元素的下标(毕竟脚本语言,编译语言中要实现这个功能所牺牲的复杂度想必会更高)

    • {{ parentMessage }} - {{ index }} - {{ item.message }}
    var example2 = new Vue({
      el: '#example-2',
      data: {
        parentMessage: 'Parent',
        items: [
          { message: 'Foo' },
          { message: 'Bar' }
        ]
      }
    })
    
    • 如果 for 后面传入的不是数组对象而是其他object,则可以遍历其json格式下的所有属性:
    • {{ value }}
    new Vue({
      el: '#v-for-object',
      data: {
        object: {
          firstName: 'John',
          lastName: 'Doe',
          age: 30
        }
      }
    })
    

    输出会是:

    • John
    • Doe
    • 30

    另外,in 前面的参数若是 (value, key) 的形式,则遍历 k-v 键值对:

    {{ key }}: {{ value }}

    结果显然:

    firstName:John
    lastName:Doe
    age:30

    最后是 value, key, index 的复合使用:

    {{ index }}. {{ key }}: {{ value }}
    • 替换数组

    这里使用到一个 变异 非变异 方法的概念:前者就是会改变原数组,后者而是在返回值体现改变的效果。
    由于使用Vue进行渲染,就必须保证其能检测到我们的修改。但是第三方框架检测不到原生js数组的一些方法。例子中给出:

    var vm = new Vue({
      data: {
        items: ['a', 'b', 'c']
      }
    })
    vm.items[1] = 'x' // 不是响应性的
    vm.items.length = 2 // 不是响应性的
    

    可以使用vue提供的方法:

    // Vue.set
    Vue.set(vm.items, indexOfItem, newValue)
    
    // Array.prototype.splice
    vm.items.splice(indexOfItem, 1, newValue)
    

    即可。
    或者这里使用Vue全局方法: Vue.set

    vm.$set(vm.items, indexOfItem, newValue)
    

    另外,使用下面的方法改变长度:

    vm.items.splice(newLength)
    

    总之,要响应式的改变dom渲染,就必须让Vue感知到这种变化,这里的注意事项给出了一种值得关注的启发:使用Vue就要关注它全方面的js替代性。

    • 添加属性

    使用Vue提供的方式:

    Vue.set(vm.userProfile, 'age', 27)  
    vm.$set(vm.userProfile, 'age', 27)
    

    一次赋值多个属性:

    vm.userProfile = Object.assign({}, vm.userProfile, {
      age: 27,
      favoriteColor: 'Vue Green'
    })
    
    • 使用类似java匿名内部类的比较函数(或者java8的filter的lambda表达函数)返回数组的过滤对象:
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
      evenNumbers: function () {
        return this.numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    
  • {{ n }}
  • 类似的在方法中调用:

    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
      even: function (numbers) {
        return numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    
  • {{ n }}
    • 更加直接地调用常量:
    div>
      {{ n }}