♕ 实例 property
1、vm.$data
- 类型:
Object - 详细: Vue实例观察的数据对象
2、vm.$props
- 类型:
Object - 详细: 当前组件接收到的props对象
3、vm.$el
- 类型:
Element - 只读
- 详细: Vue 实例使用的根 DOM 元素
4、vm.$options
- 类型:
Object - 只读
- 详细: 用于当前 Vue 实例的初始化选项。需要在选项中包含自定义 property 时会有用处:
♕ 实例方法 / 数据
1、vm.$watch
-
参数
{string | Function} expOrFn{Function | Object} callback{Object} [options]{boolean} deep{boolean} immediate
-
用法
- 观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。
export default { data() { return { count: 1 } }, created() { this.$watch('count', function(){ console.log('count 新值:'+newVal) }) } }- 和
watch作用一样,但这种方式使定义数据观察更灵活,而且$watch会返回一个取消观察函数,用来停止触发回调:
let watchFn = this.$watch('count', function(){ console.log('count 新值:'+newVal) }) this.count = 2 // log: count 新值:2 watchFn() // 调用之后取消观察 this.count = 3 // 什么都没有发生...- $watch 第三个参数接收一个配置选项:
this.$watch('count', function(){ console.log('count 新值:'+newVal) }, { immediate: true // 立即执行watch })// 为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。 this.$watch('count', function(){ console.log('count 新值:'+newVal) }, { deep: true })注意在带有 immediate 选项时,你不能在第一次回调时取消侦听给定的 property。
// 这会导致报错 var unwatch = vm.$watch( 'value', function () { doSomething() unwatch() }, { immediate: true } )
♕ 模板语法
1、插值
-
文本:大括号的形式
{{ }}<span>{{ msg }}</span> -
原始HTML:使用
v-html指令<span v-html="rawHtml"></span> -
使用js表达式:在模板中,对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{ ok ? 'YES' : 'NO' }} {{ message.split('').reverse().join('') }} <div v-bind:id="'list-' + id"></div>注意:每个绑定都只能包含单个表达式
2、指令
指令是带有
v-前缀的特殊 attribute
① v-text
- 插入数据:
string - 示例
<div v-text="msg"></div>
<!-- 和下面的一样 -->
<div>{{msg}}</div>
② v-html
- 插入数据:
string - 示例
<div v-html="html"></div>
注意事项:在单文件组件里,scoped的样式不会应用在 v-html 内部,因为那部分 HTML 没有被 Vue 的模板编译器处理。 如果你希望针对v-html的内容设置带作用域的 CSS,你可以替换为CSS Modules或用一个额外的全局<style>元素 手动设置类似 BEM 的作用域策略。
③ v-show
- 插入数据:
any
<div v-html="html"></div>
- 用法
带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。
设置为 0、-0、null、""、false、undefined 或 NaN,则该对象设置为 false。否则设置为 true(即使 value 参数是字符串 "false")。
- 实例
<div v-show="ok">Hello!</div>
注意事项:v-show 不支持<template>元素,也不支持v-else。
④ v-if
- 插入数据:
any - 用法
在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 <template>,将提出它的内容作为条件块。
- 示例
<div v-if="ok">Hello!</div>
注意事项:
在2.x中:当在同一元素上使用v-if和v-for时,v-for将优先使用;
在3.x中,v-if优先级始终高于v-for。
⑤ v-else
- 插入数据:不需要表达式
- 限制:前一兄弟元素必须有 v-if 或 v-else-if。
- 示例
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
⑥ v-else-if
- 插入数据:
any - 限制:前一兄弟元素必须有 v-if 或 v-else-if。
- 示例
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else>
Not A/B/C
</div>
⑦ v-for
- 插入数据:
Array | Object | number | string | Iterable (2.6 新增) - 用法
v-for 的默认行为会尝试原地修改元素而不是移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示
另外也可以为数组索引指定别名 (或者用于对象的键):
- 示例
<!-- string --- item:值,index:索引值 -->
<div v-for="(item, index) in string" :key="index"></div>
<!-- Array --- val:值,key:索引值 -->
<div v-for="(val, key) in array" :key="key"></div>
<!-- Object --- val:值,name:键,index:索引值 -->
<div v-for="(val, name, index) in object" :key="index"></div>
⑧ v-on
- 插入数据:
Function | Inline Statement | Object - 缩写:
@ - 示例
<!-- 方法处理器 -->
<button @click="doThis"></button>
<!-- 动态事件 (2.6.0+) -->
<button @[event]="doThis"></button>
<!-- 内联语句 -->
// 如果使用内联语句,语句可以访问一个 $event property
<button @click="doThat('hello', $event)"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 对象语法 (2.4.0+) -->
// 注意当使用对象语法时,是不支持任何修饰器的。
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
⑨ v-bind
-
插入数据:
any (with argument) | Object (without argument) -
缩写:
: -
修饰符:
-
. prop:该修饰符的作用是防止暴露标签自定义属性,美化HTML结构。没有添加prop的属性是直接暴露在外的。作为一个 DOM property 绑定而不是作为 attribute 绑定。
打开chrome Elements的properties属性面板查看该元素属性可以看到
-
. sync:vue中我们经常会用v-bind(缩写为:)给子组件传入参数。或者我们会给子组件传入一个函数,子组件通过调用传入的函数来改变父组件的状态。
即:父组件改变数据可以改变子组件, 但是子组件的内容改变并不会影响到父组件,可以通过2.3.0新增的sync修饰符来
达到双向绑定的效果🎬 前景:
//父组件给子组件传入一个函数 <MyFooter :ages="age" @setAge="(res)=> age = res"/> //子组件通过调用这个函数来实现修改父组件的状态。 <script> props: { ages: '' }, mounted () { console.log(this.$emit('setAge',1234567)); } </script>这时子组件触发了父组件的修改函数使父组件的age修改成了1234567,这种情况比较常见并且写法比较复杂。
⏳ 优化:
于是我们引出今天的主角
.sync这里注意我们的事件名称被换成了
update:age;update:是被固定的也就是vue为我们约定好的名称部分;age是我们要修改的状态的名称,是我们手动配置的,与传入的状态名字对应起来//父组件将age传给子组件并使用.sync修饰符。 <MyFooter :ages.sync="age"/> //子组件触发事件 <script> props: { ages: '' }, mounted () { console.log(this.$emit('update:ages',1234567)); } </script>注意:带有 .sync 修饰符的 v-bind 不能和表达式一起使用 (例如 v-bind:title.sync=”doc.title + ‘!’” 是无效的)。
👉 取而代之的是,你只能提供你想要绑定的 property 名,类似 v-model。-
.camel :(2.1.0+) 将 kebab-case attribute 名转换为 camelCase。(从 2.1.0 开始支持)
待研究。。。
-
-
示例
<!-- 缩写 -->
<img :src="imageSrc">
<!-- 动态 attribute 名缩写 (2.6.0+) -->
<button :[key]="value"></button>
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName">
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 通过 prop 修饰符绑定 DOM attribute -->
<div v-bind:text-content.prop="text"></div>
<!-- prop 绑定。“prop”必须在 my-component 中声明。
父传子数值-->
<my-component :prop="someThing"></my-component>
<!-- 通过 $props 将父组件的 props 一起传给子组件 -->
<child-component v-bind="$props"></child-component>
⑩ v-model
-
插入数据:随表单控件类型不同而不同。
-
限制:
<input><select><textarea>- components
-
用法:
-
基本用法
你可以用 v-model 指令在表单
<input>、<textarea> 及 <select>元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:
-
input 和 textarea 元素使用
valueproperty 和input事件; -
checkbox 和 radio 使用
checkedproperty 和change事件; -
select 字段将
value作为 prop 并将change作为事件。 -
在组件上使用v-model
v-model本质是一个语法糖,v-bind和v-on的整合
-
2.x语法
在2.x中,v-model在组件上使用等效于传递
value值并发出input事件:<!-- 父组件 --> <ChildComponent v-model="pageTitle" /> <!-- 等价于 --> <ChildComponent :value="pageTitle" @input="pageTitle = $event" />
如果我们想将属性名称或事件名称更改为其他名称,则需要向ChildComponent组件添加一个选项:<!-- 父组件 --> <ChildComponent v-model="pageTitle" /> <!-- 等价于 --> <ChildComponent :title="pageTitle" @change="pageTitle = $event" /><!-- 子组件 --> export default { model: { prop: 'title', event: 'change' }, props: { title: { type: String, default: 'Default title' } } } -
3.x语法
在3.x v-model在组件上使用等效于传递
modelValue值并发出update:modelValue事件:<ChildComponent v-model="pageTitle" /> <!-- 等价于: --> <ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event"/>
如果我们想改属性名称<ChildComponent v-model:title="pageTitle" /> <!-- 等价于: --> <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
这也可以作为.sync修饰符的替代,并允许我们v-model在自定义组件上使用多个。<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> <!-- 等价于: --> <ChildComponent :title="pageTitle" @update:title="pageTitle = $event" :content="pageContent" @update:content="pageContent = $event" /> -
-
修饰符:
-
.lazy : 取代
input监听change事件原本监听input事件
<input v-model="value"/> //等同于 <input :value="value" @input="value=$event.target.value"/>使用.lazy修饰符后监听change事件:
<input v-model.lazy="value"/> //等同于 <input :value="value" @change="value=$event.target.value"/> -
.number : 输入字符串转为有效的数字,这通常很有用,因为即使在
type="number"时,HTML 输入元素的值也总会返回字符串,它主要是用来限制用户输入的时候只能是数字 -
.trim : 输入首尾空格过滤
-
-
示例
<input v-model="value"></input>
⑪ v-slot
- 插入数据:
- 缩写:
#
待研究更新。。。
⑫ v-pre
- 不需要表达式
- 用法: 跳过这个元素和它的子元素的编译过程。可以用来显示原始
Mustache标签。跳过大量没有指令的节点会加快编译。 - 示例:
<div id="app">
{{ str }}
<span v-pre>{{ str }}</span>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
msg: '天气真好!'
}
})
</script>
编译结果:
⑬ v-cloak
- 不需要表达式
- 用法: 这个指令保持在元素上直到关联实例结束编译。
- 示例:
<div id="app" v-cloak>
<div>
{{message}}
</div>
</div>
<script type="text/javascript">
new Vue({
el:'#app',
data:{
message:'hello world'
}
})
</script>
在页面加载时会闪烁,先显示
<div>
{{message}}
</div>
然后才会编译为:
<div>
hello world!
</div>
⑭ v-once
- 不需要表达式
- 用法:只渲染
元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。 - 示例
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 组件 -->
<my-component v-once :comment="msg"></my-component>
<!-- `v-for` 指令-->
<ul>
<li v-for="i in list" v-once>{{i}}</li>
</ul>
3、特殊attribute
Ⅰ. key
-
语法:
number | string | boolean (2.4.2 新增) | symbol (2.5.12 新增) -
用法:有相同父元素的子元素必须有独特的
key。重复的 key 会造成渲染错误。主要是为了vue精准的追踪到每一个元素,高效的更新虚拟DOM。
最常见的用例是结合
v-for:
<ul>
<li v-for="item in items" :key="item.id">...</li>
</ul>
它也可以用于强制替换元素/组件而不是重复使用它。
当 text 发生改变时, 没有key的情况下diff算法可以对节点就地复用<span>会被修改。
有key的情况下<span>会被替换。
<transition>
<span :key="text">{{ text }}</span>
</transition>
vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们。否则vue只会替换其内部属性而不会触发过渡效果。
<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>
Ⅱ. ref
-
语法:
string -
用法:
- ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。
<!-- `vm.$refs.p` 在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; --> <p ref="p">hello</p> <!-- `vm.$refs.child` 在子组件上,引用就指向组件实例 --> <child-component ref="child"></child-component>-
当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组。
这里之前遇到一个问题:使用this.$refs.xx在mounted中获取DOM元素为undefined)
* 原因:在 DOM 结构中的某个 DOM 节点使用了 `v-if`、`v-show` 或者 `v-for` `(即根据获取到的后台数据来动态操作 DOM,即响应式)`,那么这些 DOM 在 mounted 阶段他们根本不存在。动态加载回来的数据是不会在这个阶段更新到 DOM 中的。 * 解决: ① 在`updated` 函数中获取:updated 阶段是完成了数据更新到 DOM 的阶段 ② 使用`$nextTick`:$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM。
Ⅲ. is
- 语法:
string | Object (组件的选项对象) - 作用:
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>里面嵌套的写法是HTML语法的固定写法,里面添加自己写的组件,html在渲染dom时,<my-component>并不是有效的dom,自定义组件<my-component>会被作为无效的内容提升到外部,并导致最终渲染结果出错。
<ul>
<my-component></my-component>
</ul>
于是就诞生了is解决html模板的限制
<ul>
<li is='my-component'></li>
</ul>
- 使用:
- 动态切换不同组件
<div id="app"> <button @click="changeComponent('component1')">A</button> <button @click="changeComponent('component2')">B</button> <!-- 通过is特性,可以动态切换当前组件 --> <div :is="currentView"></div> <!-- v-bind:动态绑定属性 --> </div> //引入组件 <script> import component1 from '../....'; import component2 from '../....'; export default { data(){ return { //当前组件 currentView:'component1' } }, components:{ component1, component2 } methods:{ changeComponent(component){ //点击按钮,动态切换不同的组件 this.currentView=component; } } } </script>- 解析DOM模板 : 解除限制元素
<!-- 这个自定义组件<my-component>会被作为无效的内容提升到外部,并导致最终渲染结果出错。 --> <table> <my-component></my-component> </table> <!--增加is特性来扩展,从而达到可以在这些受限制的html元素中使用 --> <table> <tr is="my-component"></tr> </table>
3、内置组件
Ⅰ. component
- Props:
is- string | ComponentDefinition | ComponentConstructor`inline-template- boolean
- 用法: 渲染一个“元组件”为动态组件。依
is的值,来决定哪个组件被渲染。
<!-- 动态组件由 vm 实例的 `componentId` property 控制 -->
<component :is="componentId"></component>
<!-- 也能够渲染注册过的组件或 prop 传入的组件 -->
<component :is="$options.components.child"></component>
待续。。。