Vue.js官网教程: 学习笔记1

原创
2017/02/09 09:43
阅读数 552

介绍

声明式渲染
绑定插入的文本内容:

// html
<div id="app">
    {{ message }}
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
});

但如果是DOM中的属性, 则我们需要v-bind进行绑定:

// html
<div id="app">
    <span v-bind:title="message">time</span>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: new Date()
    },
});

条件与循环
v-if来表示判断条件:

// html
<div id="app">
    <p v-if="seen">Now you see me</p>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        seen: true
    },
});

v-for来表示循环:

// html
<div id="app">
    <ol>
        <li v-for="todo in todos">
            {{ todo.text }}
        </li>
    </ol>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        todos: [
            {text: 'Learn JavaScript'},
            {text: 'Learn Vue'},
            {text: 'Build something awesome'}
        ]
    },
});

处理用户输入
v-on用于绑定监听事件:

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


这里所有的交互是DOM和Vue的交互, 如果想在DOM层面执行双向数据绑定, 则可以使用v-model:

// html
<div id="app">
    <p>{{message}}</p>
    <input v-model="message">
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello world'
    }
});

用组件构建应用
一个大的应用可以分割成多个组件, 在Vue中可以使用component来创建组件:

// html
<div id="app">
    <ol>
        <todo-item v-for="item in groceryList" v-bind:todo="item"></todo-item>
    </ol>
</div>
// JS
Vue.component('todo-item', {
    props: ['todo'],
    template: '<li>{{todo.text}}</li>'
});
var vm = new Vue({
    el: '#app',
    data: {
        groceryList: [
            {text: 'Vegetables'},
            {text: 'Cheese'},
            {text: 'Whatever else humans are supposed to eat'}
        ]
    }
});

 

Vue实例

构造器
Vue通过构造器产生应用:

var vm = new Vue({

});

甚至可扩展构造器:

var MyComponent = Vue.extend({
    // 扩展选项
});
// 所有的MyComponent实例都将以预定义的扩展选项被创建
var myComponentInstance = new MyComponent()

属性与方法
每个Vue实例都会代理其data对象里的所有的属性:

var data = {a: 1};
var vm = new Vue({
    el: '#app',
    data: data
});

vm.a === data.a;    // true

vm.a = 2;
data.a; // 2

data.a = 3;
vm.a;   // 3

Vue实例暴露了一些有用的实例属性与方法. 这些属性与方法都有前缀$, 以便与代理的data属性区分:

var data = {a: 1};
var vm = new Vue({
    el: '#example',
    data: data
});

vm.$data === data;  // true
vm.$el === document.getElementById('example);   // true

vm.$watch('a', function(newVal, oldVal) {
    // vm.a改变后调用此函数
});

 

模板语法

插值
在插入文本时候, 使用双大括号{{}}进行文本插值:

<span>Message: {{ msg }}</span>

但双括号会解释成纯文本, 而非HTML. 使用v-html可输出真正的HTML(少用, 容易导致XSS攻击):

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

在html属性中使用v-bind进行绑定:

<div v-bind:id="dynamicId"></div>

但在双大括号绑定中, 可执行单个表达式, 例如:

{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}

指令
带有v-前缀的特殊属性为指令. 例如v-bind用于绑定属性, v-on用于监听事件:

<a v-bind:href="url"></a>
<a v-on:click="doSomething"></a>

而具有修饰符点号'.', 指定以特殊的方式绑定, 例如'.prevent'修饰符告诉v-on指令对于触发的事件调用

event.preventDefault():
<form v-on:submit.prevent="onSubmit"></form>

通过管道符可执行过滤操作:

// html
<div id="app">
    <span>{{ message | upper }}</span>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello world'
    },
    filters: {
        upper: function(v) {
            return v.toUpperCase();
        }
    }
});

缩写
v-bind缩写:

<a v-bind:href="url"></a>
<a :href="url"></a>

v-on缩写:

<a v-on:click="doSomething"></a>
<a @click="doSomething"></a>

 

计算属性

考虑一种情况, 我们需要将特定数据反转, 则可能编写如下的代码:

<div id="app">
    {{ message.split('').reverse().join('') }}
</div>

这样会混乱模板, 易读性差. 这时候, 应该定义一个额外的变量, 由message计算出来.

// html
<div id="app">
    <p>Original message: {{ message }}</p>
    <p>Computed reversed message: {{ reverseMessage }}</p>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello world'
    },
    computed: {
        reverseMessage: function() {
            return this.message.split('').reverse().join('');
        }
    }
});

计算属性可以使用方法来实现, 例如上述例子可修改为:

// html
<div id="app">
    <p>Original message: {{ message }}</p>
    <p>Computed reversed message: {{ reverseMessage() }}</p>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        message: 'Hello world'
    },
    methods: {
        reverseMessage: function() {
            return this.message.split('').reverse().join('');
        }
    },
});

但主要的区别在于: 计算属性是具有缓存作用的, 如果需要一个很大的数组或者进行大量的计算, 则如果没有缓存的话, 性能会很低.

在Vue中拥有一个属性为$watch, 用于监测一个变量的改变. 但更好的方法是使用计算属性来完成类似$watch的工作. 例如:

var vm = new Vue({
    el: '#app',
    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;
        }
    }
});

考虑上述例子中, firstName和lastName名字的变换导致fullName的变化, 实际上我们可以使用计算属性轻易解决:

var vm = new Vue({
    el: '#app',
    data: {
        firstName: 'Foo',
        lastName: 'Bar'
    },
    computed: {
        fullName: function() {
            return this.firstName + ' ' + this.lastName;
        }
    }
});

而计算属性默认只有getter操作, 需要情况下可以提供setter操作:    

computed: {
    fullName: {
        get: function() {
            return this.firstName + ' ' + this.lastName;
        },
        set: function(newVal) {
            var names = newVal.split(' ');
            this.firstName = names[0];
            this.lastName = names[1];
        }
    }
}

 

Class与Style绑定

绑定HTML Class
给V-bind:class一个对象, 用于动态切换class:

// html
<div id="app" v-bind:class="{active: isActive}">Hello</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        isActive: true
    },
});

也可以传递一个对象:

// html
<div id="app" v-bind:class="classObject">Hello</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        classObject: {
            active: true,
            'text-danger': false
        }
    },
});

甚至可以使用一个数组, 包含多个class对象:

// html
<div v-bind:class="[activeClass, errorClass]"></div>

 

条件渲染

v-if/v-else/v-else-if
可以使用v-if/v-else来执行if/else的操作:

// html
<div id="app">
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        ok: false 
    },
});

如果我们想使用v-if一次性判断多个元素, 则可以使用template包含起来, 而最终的渲染不会喊喊template:

// html
<template v-if="ok">
    <h1>Title</h1>
    <p>Paragraph 1</p>
    <p>Paragraph 2</p>
</template>

而使用v-else-if来链式多次使用:

<div v-if="type === 'A'">
    A
</div>
<div v-else-if="type === 'B'">
    B
</div>
<div v-else-if="type === 'C'">
    C
</div>
<div v-else>
    Not A/B/C
</div>

使用key控制元素的可重用
Vue尝试尽可能高效的渲染元素, 通常会服用已有元素而不是从头开始渲染.

// html
<div id="app">
    <template v-if="loginType === 'username'">
        <label>Username</label>
        <input placeholder="Enter your username">
    </template>
    <template v-else> 
        <label>Email</label>
        <input placeholder="Enter your Email">
    </template>

    <button v-on:click="toggle">Toggle login type</button>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        loginType: 'username'
    },
    methods: {
        toggle: function() {
            this.loginType = this.loginType === 'username' ? 'email' : 'username';
        }
    }
});

点击toggle时候, 并不会删除用户已经输入的内容. 两个模板由于使用了相同的元素, <input>会被复用, 仅仅是替换了他们的placeholder.
 

列表渲染

v-for
v-for的基本用法如下:

// html
<div id="app">
    <ul>
        <li v-for="item in items">
            {{ item.message }}
        </li>
    </ul>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        items: [
            {message: 'Foo'},
            {message: 'Bar'}
        ]
    },
});

但如果我们想要列表索引, 则可这样编写:

// html
<div id="app">
    <ul>
        <li v-for="(item, index) in items">
            {{ item.message }} -- {{ index }}
        </li>
    </ul>
</div>

也可以对一个对象进行迭代:

// html
<div id="app">
    <ul>
        <li v-for="value in object">
            {{ value }}
        </li>
    </ul>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        object: {
            FirstName: 'John',
            LastName: 'Doe',
            Age: 30
        }
    },
});

我们可以提供第二个参数作为key:

<div v-for="{value, key} in object">
    {{ key }} : {{ value }}
</div>

第三个参数作为索引:

<div v-for="{value, key, index} in object">
    {{ index }}. {{ key }} : {{ value }}
</div>

v-for也可以对整数进行循环:

<div>
    <span v-for="n in 10">{{ n }}</span>
</div>

在组件中我们也可以使用v-for. 组件之间的数据传递用到props:

// html
<div id="app">
    <input 
        v-model="newTodoText" 
        v-on:keyup.enter="addNewTodo"
        placeholder="Add a todo"
    >
    <ul>
        <li
            is="todo-item"
            v-for="(todo, index) in todos"
            v-bind:title="todo"
            v-on:remove="todos.splice(index, 1)"
        ></li>
    </ul>
</div>
// JS
Vue.component('todo-item', {
    template: '<li>{{ title }}<button v-on:click="$emit(\'remove\')">X</button></li>',
    props: ['title']
});

var vm = new Vue({
    el: '#app',
    data: {
        newTodoText: '',
        todos: [
            'Do the dishes',
            'Take out the trash',
            'Mow the lawn'
        ]
    },
    methods: {
        addNewTodo: function() {
            this.todos.push(this.newTodoText);
            this.newTodoText = '';
        },
    }
});


事件处理器

可以使用v-on指令监听DOM事件:

// html
<div id="app">
    <button v-on:click="counter += 1">click</button
    <p>{{counter}}</p>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        counter: 0
    }
});

但是更好的编写方法为: 写成方法, 而非直接写在html里面:

// html
<div id="app">
    <button v-on:click="add">click</button
    <p>{{counter}}</p>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
        counter: 0
    },
    methods: {
        add: function() {
            this.counter += 1;
        }
    }
});

有时候, 需要在内联语句处理器中访问原生DOM事件, 可以用特殊变量$event把它传入方法:

// html
<div id="app">
    <button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>
</div>
// JS
var vm = new Vue({
    el: '#app',
    data: {
    },
    methods: {
        warn: function(msg, event) {
            if (event) event.preventDefault();
            alert(msg);
        }
    }
});

 

 

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
2 收藏
0
分享
返回顶部
顶部