[WIP]Vue 基础
创建: 2019/05/30
更新: 2019/11/02 补充组件基础里未完成部分
https://cn.vuejs.org/v2/guide/
安装 |
初期选择直接嵌入 <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 --> <script src="https://cdn.jsdelivr.net/npm/vue"></script>
|
||||||||||||||||||||||||||
声明式渲染 |
<div id="app"> {{ message }} </div>
var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
|
||||||||||||||||||||||||||
条件与循环 |
● v-if 参数为真时显示 <div id="app-3"> <p v-if="seen">现在你看到我了</p> </div>
var app3 = new Vue({ el: '#app-3', data: { seen: true } }) ● v-for <div id="app-4"> <ol> <li v-for="todo in todos"> {{ todo.text }} </li> </ol> </div>
var app4 = new Vue({ el: '#app-4', data: { todos: [ { text: '学习 JavaScript' }, { text: '学习 Vue' }, { text: '整个牛项目' } ] } })
|
||||||||||||||||||||||||||
处理用户输入 |
● v-on 绑定事件 例: v-on:click <div id="app-5"> {{message}} <button type="button" v-on:click='reserveMsg'>反转文本</button> </div>
var app5 = new Vue({ el: '#app-5', data: { message: 'sample' }, methods: { reserveMsg: function() { console.log(this); let msg = this.message; msg = this.message.split('').reverse().join(''); this.message = msg; } } }); ● v-model 表单输入和应用状态之间的双向绑定 <div id="app-6"> <p>{{ message }}</p> <input v-model="message"> </div>
var app6 = new Vue({ el: '#app-6', data: { message: 'Hello Vue!' } })
|
||||||||||||||||||||||||||
组件化应用构建 |
● 注册组件 Vue.component(组件名, 组件内容) 例 // 定义名为 todo-item 的新组件 Vue.component('todo-item', { template: '<li>这是个待办项</li>' })
<ol> <!-- 创建一个 todo-item 组件的实例 --> <todo-item></todo-item> </ol>
● 设计例 <div id="app"> <app-nav></app-nav> <app-view> <app-sidebar></app-sidebar> <app-content></app-content> </app-view> </div>
|
||||||||||||||||||||||||||
Vue实例 | |||||||||||||||||||||||||||
创建一个vue实例 |
var vm = new Vue({ // 选项 })
|
||||||||||||||||||||||||||
数据与方法 |
所有属性都以 $ 开头
|
||||||||||||||||||||||||||
声明周期钩子 |
● vue实例创建前后的处理
● 可挂载的钩子
|
||||||||||||||||||||||||||
声明周期图 |
|
||||||||||||||||||||||||||
template语法 | |||||||||||||||||||||||||||
插值 |
|
||||||||||||||||||||||||||
指令 |
所有指定以 v- 开始 v-once: 当前节点为根的节点树不会更新插值内容
|
||||||||||||||||||||||||||
缩写 |
● v-bind <!-- 完整语法 --> <a v-bind:href="url"> ... </a> <!-- 缩写 --> <a :href="url"> ... </a> <!-- 动态参数の省略写法 (2.6.0 以后) --> <a :[key]="url"> ... </a>
● v-on <!-- 完整语法 --> <a v-on:click="doSomething"> ... </a> <!-- 缩写 --> <a @click="doSomething"> ... </a> <!-- 动态参数の省略写法 (2.6.0 以后) --> <a @[event]="doSomething"> ... </a>
|
||||||||||||||||||||||||||
计算属性和侦听器 | |||||||||||||||||||||||||||
计算属性 |
|
||||||||||||||||||||||||||
侦听器 |
watch: { 对应属性名: function() { ... } }
|
||||||||||||||||||||||||||
class与style的绑定 | |||||||||||||||||||||||||||
绑定Class |
|
||||||||||||||||||||||||||
绑定内联Style |
|
||||||||||||||||||||||||||
条件渲染 | |||||||||||||||||||||||||||
v-if |
v-if , v-else-if , v-else ● 条件为真时渲染代码块 ● 如果要对多个元素使用条件, 可以包裹到 <template></template> <template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template> ● 可以给元素设置唯一key, 有key的元素不会被混着重复利用 <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email-input"> </template>
|
||||||||||||||||||||||||||
v-show |
条件为false时, 添加 display: none ● 不支持template, v-else, v-else-if |
||||||||||||||||||||||||||
v-if vs v-show |
一般来说, v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。 因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
|
||||||||||||||||||||||||||
v-if与v-for一起使用 |
不要一起使用, 改用计算属性等计算好以后再v-for |
||||||||||||||||||||||||||
列表渲染 | |||||||||||||||||||||||||||
v-for对数组map | 写法:
v-for="item in items" 第二参数支持索引 v-for="(item, index) in items" 例: <ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul>
var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } })
|
||||||||||||||||||||||||||
v-for对对象 |
第二参数支持key名, 第三参数支持索引 v-for="value in object" // 带key名 v-for="(value, name) in object" // 带key名和索引 v-for="(value, name, index) in object"
注: 枚举顺序为 Object.keys() 的顺序, 参考: https://www.cnblogs.com/lancgg/p/10403527.html 例: <table> <tr v-for="(v, k, i) in sampleData"> <td>{{k}}</td> <td>{{i}}</td> <td>{{v}}</td> </tr> </table>
sampleData: { a: 'here is a', b: 'here is b', c: 'here is c' }
|
||||||||||||||||||||||||||
维护状态 |
默认就地更新: 元素被改变了则更新元素而不是改变顺序匹配元素 加上key属性, 是的vue可以追踪 |
||||||||||||||||||||||||||
数组更新检测 |
● 被监视的变更数组的方法
● 对于不变更数组的方法, 把数组设置成相关方法的返回值 Vue只能识别, 只重新渲染需要的 ● 注: Vue不能识别如下变更方法
|
||||||||||||||||||||||||||
对象更新检测注意事项 |
Vue不能检测对象属性的添加或删除, 对现存属性的修改可以感应到 解决方法: Vue.set(object、propertyName、value)
● 合并object, 不要直接使用 Object.assign() , _.extend() 不要这样 Object.assign(vm.userProfile, { age: 27, favoriteColor: 'Vue Green' })
要这样 vm.userProfile = Object.assign({}, vm.userProfile, { age: 27, favoriteColor: 'Vue Green' })
|
||||||||||||||||||||||||||
显示过滤/排序后的结果 |
不变更原数组, 只是表示的话用计算属性 <li v-for="n in evenNumbers">{{ n }}</li>
data: { numbers: [ 1, 2, 3, 4, 5 ] }, computed: { evenNumbers: function () { return this.numbers.filter(function (number) { return number % 2 === 0 }) } }
|
||||||||||||||||||||||||||
在v-for里使用值范围 |
v-for接受整数 <div>
<span v-for="n in 10">{{ n }} </span>
</div>
|
||||||||||||||||||||||||||
template的v-for |
和 v-if 一样, 可以对template使用 v-for <ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
|
||||||||||||||||||||||||||
v-for与v-if | 不要一起用 | ||||||||||||||||||||||||||
组件与v-for | # TODO: finish here | ||||||||||||||||||||||||||
监听事件 | |||||||||||||||||||||||||||
监听事件 |
v-on:事件名 // 简写 @事件名
例 <div id="example-1"> <button v-on:click="counter += 1">Add 1</button> <p>The button above has been clicked {{ counter }} times.</p> </div>
var example1 = new Vue({ el: '#example-1', data: { counter: 0 } })
|
||||||||||||||||||||||||||
事件处理方法 |
可以添加method, 然后事件触发时呼出 呼出方法: @事件名="方法名" // 例 @click="clickHander" 例 <div id="example-2"> <!-- `greet` 是在下面定义的方法名 --> <button v-on:click="greet">Greet</button> </div>
|
||||||||||||||||||||||||||
内联处理器中的方法 |
也可以用式子来呼出方法 <button type="button" name="button" @click="msg('app-12')"> click me </button>
|
||||||||||||||||||||||||||
事件修饰符 |
● 可以不指定值, 只是用装饰符 <!-- 只有修饰符 --> <form v-on:submit.prevent></form> ● 修饰符可以串联 <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> ● 使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。 因此,用 v-on:click.prevent.self 会阻止所有的点击, 而 v-on:click.self.prevent 只会阻止对元素自身的点击。
|
||||||||||||||||||||||||||
按键修饰符 | # TODO: finish here | ||||||||||||||||||||||||||
系统修饰符 | # TODO: finish here | ||||||||||||||||||||||||||
为什么在 HTML 中监听事件? | # TODO: finish here | ||||||||||||||||||||||||||
表单绑定输入 | |||||||||||||||||||||||||||
基础用法 |
可用 v-model 在表单 <input> , <textarea> , <select> 上创建双向数据绑定 ● v-model 会忽略所有表单元素的 value 、 checked 、 selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。 即Vue会忽略html设定的表单值 你应该通过 JavaScript 在组件的 ●
● v-model的本质 <input v-model="searchText">
相当于 <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" > 当用在自定义组件上时, 相当于 <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input>
|
||||||||||||||||||||||||||
值绑定 | v-bind:value="..." | ||||||||||||||||||||||||||
修饰符 |
|
||||||||||||||||||||||||||
在组件上使用v-model | # TODO: finish here | ||||||||||||||||||||||||||
组件基础 | |||||||||||||||||||||||||||
基本示例 |
组件是可复用的 Vue 实例,且带有一个名字 我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用 // 定义一个名为 button-counter 的新组件 Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' }) ● data, computed, methods, watch, 生命周期钩子等 |
||||||||||||||||||||||||||
组件的复用 |
注册的组件可以重复使用 <div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div> ● data: function () { return { count: 0 } }
|
||||||||||||||||||||||||||
组件的组织 |
通常一个应用会以一棵嵌套的组件树的形式来组织 ● Vue.component(组件名, 组件)
|
||||||||||||||||||||||||||
通过Prop向子组件传递数据 |
Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' })
<blog-post title="My journey with Vue"></blog-post> <blog-post title="Blogging with Vue"></blog-post> <blog-post title="Why Vue is so fun"></blog-post>
|
||||||||||||||||||||||||||
单个根元素 |
每个组件必须只有一个根元素 |
||||||||||||||||||||||||||
监听子组件事件 |
抛出事件的方法 $emit(事件名, 参数) 例 <blog-post ... v-on:enlarge-text="postFontSize += 0.1" ></blog-post>
<button v-on:click="$emit('enlarge-text')"> Enlarge text </button>
● 访问事件抛出的值
|
||||||||||||||||||||||||||
在组件上使用v-model |
● v-model的本质 <input v-model="searchText"> 相当于 <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" > 当用在自定义组件上时, 相当于 <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input> 为了让它正常工作,这个组件内的
Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` })
|
||||||||||||||||||||||||||
通过插槽分发内容 |
在需要的地方加入插槽 <slot></slot>
|
||||||||||||||||||||||||||
动态组件 |
<!-- 组件会在 `currentTabComponent` 改变时改变 --> <component v-bind:is="currentTabComponent"></component>
|
||||||||||||||||||||||||||
解析DOM模板时的注意事项 |
有些 HTML 元素,诸如 而有些元素,诸如 |
||||||||||||||||||||||||||