Vue 学习笔记

11.18'24

介绍

作为前端主流框架之一,vue.js 生态系统日益完善。了解和学习 vue.js,可以学到很多新的思维观念。

参考

入门

在 HTML 中引入 vue.js 文件即可使用。

下载到本地或使用远程 CDN

<!-- development version, includes helpful console warnings -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<div id='app'>
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">Reverse Message</button>
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split(' ').reverse().join(' ');
    }
  }
})

语法

实例化 Vue 对象

const vm = new Vue(options)

vm(ViewModel) 为 Vue 的实例,在 options 的函数中可以通过this访问定义在实例上的数据和方法。

标签内容绑定对象

<tag>{{ variable }}</tag>
<div id="app">
  {{ message }}
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

标签属性/事件绑定对象

<tag v-bind:attr="variable" v-on:event="expression/method">...</tag>

:后面为指令的参数,可以通过[argument]动态计算。

v-bind:, v-on:可以简写为:@

v-bind:title => :title
v-on:click   => @click
<span v-bind:title="message">
  Hover your mouse over me for a few seconds
  to see my dynamically bound title!
</span>

<button v-on:click="reverseMessage">Reverse Message</button>

条件和循环

v-if
v-show
v-for
<span v-if="seen">Now you see me</span>

<li v-for="todo in todos">
  {{ todo.text }}
</li>
const app = new Vue({
  el: '#app-3',
  data: {
    seen: true,
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})

data 中数组、对象修改

对于数组、对象等复杂数据结构,使用的都是这些变量的引用。修改时需要做额外处理,以实现 UI 的即时刷新。

  • 使用 Vue 内部处理过的方法:

    push(), pop(), shift(), unshift(), splice(), sort(), reverse()

  • 使用 Vue.set 或 vm.$set 方法

以修改数组某个元素为例

vm.items.splice(itemIndex, 1, newValue)
vm.$set(vm.items, itemIndex, newValue)

import Vue from 'vue'
Vue.set(items, itemIndex, newValue)
// object in array
Vue.set(object, 'propName', newValue)

修改数组长度(变小)

vm.items.splice(newLength);

Vue 不允许添加 root 级别的属性到实例上。但是当属性本身是一个对象时,可以在该对象上添加属性

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

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: '27', 
  favoriteColor: 'Vue Green',
});

双向绑定

常用于表单输入标签。本质上是语法糖,基于用户输入事件来更新数据。

v-model
<div>
  <p>{{ message }}</p>
  <input v-model="message">
</div>

自定义组件

Vue.component方法可以自定义组件,组件是可复用的 Vue 实例, definition 基本上与 options一致。

Vue.component(id, definition);

组件的数据

  • data

    () => Object - 组件内部、私有的数据

  • props

    [propA, propB, ...] || { propA: { type: String, default: '' } } - 组件外部传递过来、公开的数据

  • computed

    { dataA() {}, dataB() {} } - 根据 data 或 props 动态计算出来的数据。

指令

v-model, v-for, v-if, v-bind, v-on 等都是内置指令,用户也可以自定义指令,主要用于底层的 DOM 操作。

Vue.directive(id, definition);

v-html: Raw HTML

<span v-html="rawHtml"></span>

<span>{{ plainText }}</span>

父子组件数据传递

父组件 -> 子组件:通过props单向传递数据。父组件数据变化后子组件会自动刷新

子组件 -> 父组件:调用 events 手动修改父组件的数据

组件内部:$emit('event')

组件外部:v-on:event="method"

Vue.component('test-component', {
    template: '#test-template', 
    props: ['value'], 
    methods: {
        onInput: function (event) {
            this.$emit('input', event.target.value)
        }
    }
})

Vue.component('show-component', {
    template: '#show-template', 
    props: ['user'],
})

new Vue({
    el: '#app',
    data: {
        user: 'John'
    }
})

<template id='test-template'>
  <input v-bind:value='value' v-on:input='onInput' type='text'/>
</template>
<template id='show-template'>
  <div>{{ user }}</div>
</template>

<div id='app'>
  <test-component v-model='user'></test-component>
  <show-component v-bind:user='user'></show-component>
</div>

一些报错及原因

[Vue warn]: Property or method "addItem" is not defined on the instance but referenced during render.

一个常见原因为没在组件上定义好属性或方法;另一个原因是div#app中包含了templatetemplate的内容被 Vue 解析到 root 中,导致报错。

预处理器

.vue 单文件由vue-loader预加载和处理。文件中的 HTML, JavaScript, CSS 都可以进行预处理。

参考:Using Pre-Processors

Pug -> HTML

npm install -D pug pug-plain-loader
// webpack.config.js -> module.rules
{
  test: /\.pug$/,
  loader: 'pug-plain-loader'
}
<template lang="pug">
div
  h1 Hello world!
</template>

SASS/LESS -> CSS

Coffee/TypeScript -> JavaScript

vue-cli

npm i -g @vue/cli

vue create <project-name>
cd <project-name>
npm start

在线交互

Try Vue :)

Input: {{ text }}
// Init Vue with el, data and methods
new Vue({
  el: '#app-demo',
  data: {
    text: 'hello'
  },
  methods: {
    sayHello: function () {
      console.log(this.text);
    }
  }
})
📖