Vueinstance and 模板语法

深入understandingVueinstance 生命周期, data绑定, 指令system and 模板语法

1. Vueinstance

Vueinstance is Vueapplication 根instance, 它 is Vueapplication 入口点. 每个Vueapplication都 is throughcreation一个Vueinstance开始 .

// creationVueinstance
var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
    methods: {
        greet: function() {
            return this.message;
        }
    },
    computed: {
        reversedMessage: function() {
            return this.message.split('').reverse().join('');
        }
    },
    watch: {
        message: function(newVal, oldVal) {
            console.log('message changed from ' + oldVal + ' to ' + newVal);
        }
    }
});

1.1 Vueinstance 选项

Vueinstance可以接收 many 种选项, 用于configurationinstance behavior and functions.

1.1.1 el选项

el选项用于指定Vueinstance挂载 DOM元素. 可以 is a CSS选择器string, 也可以 is a DOM元素object.

// usingCSS选择器
var app = new Vue({
    el: '#app'
});

// usingDOM元素object
var appElement = document.getElementById('app');
var app = new Vue({
    el: appElement
});

1.1.2 data选项

data选项用于定义Vueinstance data. 可以 is a object, 也可以 is a function ( in componentin必须 is function) .

// object形式
var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        count: 0,
        items: [1, 2, 3, 4, 5]
    }
});

// function形式 ( in componentinusing) 
var app = new Vue({
    el: '#app',
    data: function() {
        return {
            message: 'Hello Vue!',
            count: 0
        };
    }
});

1.1.3 methods选项

methods选项用于定义Vueinstance method. 这些method可以 in 模板in调用, 也可以 in othermethodinthroughthis访问.

var app = new Vue({
    el: '#app',
    data: {
        count: 0
    },
    methods: {
        increment: function() {
            this.count++;
        },
        decrement: function() {
            this.count--;
        },
        reset: function() {
            this.count = 0;
        }
    }
});

1.1.4 computed选项

computed选项用于定义计算property. 计算property is 基于otherdata计算得出 , 具 has cachemechanism, 只 has 当依赖 data发生变化时才会重 new 计算.

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
    computed: {
        reversedMessage: function() {
            return this.message.split('').reverse().join('');
        },
        messageLength: function() {
            return this.message.length;
        }
    }
});

1.1.5 watch选项

watch选项用于监听data 变化. 当监听 data发生变化时, 会调用 for 应 processingfunction.

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        count: 0
    },
    watch: {
        message: function(newVal, oldVal) {
            console.log('message changed from ' + oldVal + ' to ' + newVal);
        },
        count: function(newVal, oldVal) {
            if (newVal > 10) {
                console.log('count is greater than 10');
            }
        }
    }
});

1.2 Vueinstance 生命周期

Vueinstance from creation to 销毁 过程称 for 生命周期. Vueproviding了 many 个生命周期hook, 允许Development者 in 不同阶段执行自定义逻辑.

1.2.1 生命周期hook

  • beforeCreate: instancecreation before 调用, 此时data and methods还未初始化.
  • created: instancecreation after 调用, 此时data and methods已初始化, 但DOM还未挂载.
  • beforeMount: DOM挂载 before 调用, 此时模板已编译, 但还未挂载 to DOM on .
  • mounted: DOM挂载 after 调用, 此时模板已挂载 to DOM on , 可以访问DOM元素.
  • beforeUpdate: dataupdate before 调用, 此时data已update, 但DOM还未update.
  • updated: dataupdate after 调用, 此时data and DOM都已update.
  • beforeDestroy: instance销毁 before 调用, 此时instance仍然可用.
  • destroyed: instance销毁 after 调用, 此时instance已不可用.
var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    },
    beforeCreate: function() {
        console.log('beforeCreate: data and methods are not initialized yet');
    },
    created: function() {
        console.log('created: data and methods are initialized');
    },
    beforeMount: function() {
        console.log('beforeMount: template is compiled but not mounted to DOM');
    },
    mounted: function() {
        console.log('mounted: template is mounted to DOM');
    },
    beforeUpdate: function() {
        console.log('beforeUpdate: data is updated but DOM is not updated yet');
    },
    updated: function() {
        console.log('updated: data and DOM are updated');
    },
    beforeDestroy: function() {
        console.log('beforeDestroy: instance is still available');
    },
    destroyed: function() {
        console.log('destroyed: instance is no longer available');
    }
});

2. Vue模板语法

Vueusing基于HTML 模板语法, 允许Development者声明式地将data绑定 to DOM on .

2.1 插值

using双 big 括号{{}}for文本插值, 将data绑定 to DOM on .

<div id="app">
    <!-- 文本插值 -->
    <p>{{ message }}</p>
    
    <!-- HTML插值 (usingv-html指令)  -->
    <p v-html="rawHtml"></p>
    
    <!-- JavaScript表达式 -->
    <p>{{ message.split('').reverse().join('') }}</p>
    <p>{{ count + 1 }}</p>
    <p>{{ ok ? 'Yes' : 'No' }}</p>
</div>

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!',
        rawHtml: '<span style="color: red;">This is red text</span>',
        count: 0,
        ok: true
    }
});

提示

Vue模板语法supportJavaScript表达式, 但不support语句 (such asif语句, for循环) and 流程控制.

2.2 指令

指令 is 带 has v- before 缀 特殊property, 用于 in DOM on applicationresponse式behavior.

2.2.1 in 容指令

  • v-text: update元素 文本 in 容.
  • v-html: update元素 HTML in 容.
<div id="app">
    <p v-text="message"></p>
    <p v-html="rawHtml"></p>
</div>

2.2.2 条件指令

  • v-if: 根据表达式 真fake条件渲染元素.
  • v-else: and v-if搭配using, 渲染else块.
  • v-else-if: and v-if搭配using, 渲染else if块.
  • v-show: 根据表达式 真fake条件显示 or 隐藏元素 (throughCSS displayproperty) .
<div id="app">
    <!-- v-if/v-else-if/v-else -->
    <p v-if="type === 'A'">Type A</p>
    <p v-else-if="type === 'B'">Type B</p>
    <p v-else>Type C</p>
    
    <!-- v-show -->
    <p v-show="isVisible">This is visible</p>
</div>

var app = new Vue({
    el: '#app',
    data: {
        type: 'A',
        isVisible: true
    }
});

提示

v-if and v-show 区别:

  • v-if is 条件渲染, 条件 for fake时元素不会被渲染 to DOMin.
  • v-show is 条件显示, 条件 for fake时元素会被渲染 to DOMin, 但throughCSS display: none隐藏.
  • v-if适合条件不经常变化 场景, v-show适合条件经常变化 场景.

2.2.3 循环指令

  • v-for: 根据data循环渲染元素.
<div id="app">
    <!-- 遍历array -->
    <ul>
        <li v-for="(item, index) in items" :key="index">
            {{ index }}: {{ item }}
        </li>
    </ul>
    
    <!-- 遍历object -->
    <ul>
        <li v-for="(value, key, index) in object" :key="key">
            {{ index }}. {{ key }}: {{ value }}
        </li>
    </ul>
    
    <!-- 遍历整数 -->
    <ul>
        <li v-for="n in 5" :key="n">
            {{ n }}
        </li>
    </ul>
</div>

var app = new Vue({
    el: '#app',
    data: {
        items: ['apple', 'banana', 'orange'],
        object: {
            name: 'Vue.js',
            version: '2.6.14',
            author: 'Evan You'
        }
    }
});

提示

usingv-for时, 建议 for 每个list项添加:keyproperty, 以便Vueable to更 high 效地updateDOM. keyproperty 值应该 is 唯一 .

2.2.4 event指令

  • v-on: 绑定event监听器. 可以缩写 for @.
<div id="app">
    <!-- basic用法 -->
    <button v-on:click="increment">Increment</button>
    
    <!-- 缩写形式 -->
    <button @click="increment">Increment</button>
    
    <!-- 传递eventobject -->
    <button @click="handleClick">Click me</button>
    
    <!-- 传递自定义parameter -->
    <button @click="handleClickWithParam('hello', $event)">Click with param</button>
    
    <!-- event修饰符 -->
    <button @click.stop="handleClick">Stop propagation</button>
    <form @submit.prevent="handleSubmit">
        <button type="submit">Submit</button>
    </form>
    
    <!-- 按键修饰符 -->
    <input @keyup.enter="handleEnter" placeholder="Press Enter">
</div>

var app = new Vue({
    el: '#app',
    data: {
        count: 0
    },
    methods: {
        increment: function() {
            this.count++;
        },
        handleClick: function(event) {
            console.log('Clicked', event);
        },
        handleClickWithParam: function(message, event) {
            console.log(message, event);
        },
        handleSubmit: function(event) {
            console.log('Form submitted');
        },
        handleEnter: function(event) {
            console.log('Enter pressed');
        }
    }
});

2.2.5 绑定指令

  • v-bind: 动态绑定property. 可以缩写 for :.
<div id="app">
    <!-- 绑定srcproperty -->
    <img v-bind:src="imageSrc" alt="Vue logo">
    
    <!-- 缩写形式 -->
    <img :src="imageSrc" alt="Vue logo">
    
    <!-- 绑定classproperty -->
    <div :class="{ active: isActive, 'text-danger': hasError }">Class binding</div>
    <div :class="classObject">Class object binding</div>
    <div :class="[activeClass, errorClass]">Class array binding</div>
    
    <!-- 绑定styleproperty -->
    <div :style="{ fontSize: fontSize + 'px', color: color }">Style binding</div>
    <div :style="styleObject">Style object binding</div>
    <div :style="[baseStyles, overridingStyles]">Style array binding</div>
</div>

var app = new Vue({
    el: '#app',
    data: {
        imageSrc: 'https://vuejs.org/images/logo.png',
        isActive: true,
        hasError: false,
        classObject: {
            active: true,
            'text-danger': false
        },
        activeClass: 'active',
        errorClass: 'text-danger',
        fontSize: 18,
        color: 'red',
        styleObject: {
            fontSize: '18px',
            color: 'red'
        },
        baseStyles: {
            fontSize: '18px'
        },
        overridingStyles: {
            color: 'blue'
        }
    }
});

2.2.6 表单指令

  • v-model: 双向data绑定, 用于表单元素.
<div id="app">
    <!-- 文本输入 -->
    <input v-model="message" placeholder="Enter message">
    <p>Message: {{ message }}</p>
    
    <!--  many 行文本 -->
    <textarea v-model="textarea" placeholder="Enter text"></textarea>
    <p>Textarea: {{ textarea }}</p>
    
    <!-- 单选按钮 -->
    <div>
        <input type="radio" id="option1" value="option1" v-model="selectedOption">
        <label for="option1">Option 1</label>
        <input type="radio" id="option2" value="option2" v-model="selectedOption">
        <label for="option2">Option 2</label>
    </div>
    <p>Selected option: {{ selectedOption }}</p>
    
    <!-- 复选框 -->
    <div>
        <input type="checkbox" id="checkbox1" value="checkbox1" v-model="checkedItems">
        <label for="checkbox1">Checkbox 1</label>
        <input type="checkbox" id="checkbox2" value="checkbox2" v-model="checkedItems">
        <label for="checkbox2">Checkbox 2</label>
    </div>
    <p>Checked items: {{ checkedItems }}</p>
    
    <!--  under 拉选择框 -->
    <select v-model="selectedValue">
        <option disabled value="">Please select</option>
        <option value="value1">Value 1</option>
        <option value="value2">Value 2</option>
        <option value="value3">Value 3</option>
    </select>
    <p>Selected value: {{ selectedValue }}</p>
    
    <!-- 修饰符 -->
    <input v-model.lazy="lazyMessage" placeholder="Lazy update">
    <p>Lazy message: {{ lazyMessage }}</p>
    
    <input v-model.number="numberValue" type="number" placeholder="Number input">
    <p>Number value: {{ numberValue }}, type: {{ typeof numberValue }}</p>
    
    <input v-model.trim="trimmedMessage" placeholder="Trim whitespace">
    <p>Trimmed message: "{{ trimmedMessage }}"</p>
</div>

var app = new Vue({
    el: '#app',
    data: {
        message: '',
        textarea: '',
        selectedOption: '',
        checkedItems: [],
        selectedValue: '',
        lazyMessage: '',
        numberValue: 0,
        trimmedMessage: ''
    }
});

3. 模板语法 best practices

  • usingv-for时, 始终添加:keyproperty.
  • 避免 in 模板inusing complex JavaScript表达式, 将 complex 逻辑放 to 计算property or methodin.
  • usingv-if and v-for时, 避免 in 同一个元素 on using, 因 for v-for priority high 于v-if.
  • usingevent修饰符 and 按键修饰符简化eventprocessing逻辑.
  • using计算propertycache计算结果, 避免重复计算.
  • usingwatch监听data变化, 执行asynchronous or complex 逻辑.

练习 1: Vueinstance and 生命周期

  1. creation一个Vueinstance, 添加所 has 生命周期hook, 并 in 控制台输出log.
  2. 观察生命周期hook 执行顺序.
  3. modifydata, 观察beforeUpdate and updatedhook 执行.
  4. 销毁instance, 观察beforeDestroy and destroyedhook 执行.

练习 2: 模板语法综合练习

  1. creation一个Vueinstance, package含以 under data:
    • 一个待办事项list (package含id, title, completed字段)
    • 一个 new 待办事项 输入框
  2. usingv-for渲染待办事项list, 显示标题 and completionstatus.
  3. usingv-if/v-else显示不同 completionstatus样式.
  4. usingv-model双向绑定 new 待办事项 输入框.
  5. usingv-on绑定添加待办事项 event.
  6. usingv-on绑定切换待办事项completionstatus event.
  7. using计算property显示已completion and 未completion 待办事项数量.