vue基本使用(1)
Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
最简单的结构
导入Vue文件,可以自己下载一个Vue.js文件,然后将其导入页面即可。这种方式是直接在页面中使用Vue
<script src="./lib/Vue.js">script>
导入该包之后,在该环境中存在一个Vue的对象可以供我们操作,通过实例化Vue对象,通过 el 属性指定该Vue对象控制的区域,通过 data 来保存一些数据,通过 methods 来定义一些操作,比如一些点击事件的事件函数。
<script src="./lib/Vue.js">script> <div id=app1 v-on:click="clickToGetinfo"> {{ msg }} div> <div id=app2> {{ msg }} div> <script> var vm = new Vue({ el:"#app1", data:{ msg:"abc" }, methods:{ clickToGetinfo: function(){}, } }) script>
上面使用插值表达式的方式,将msg对应的值 abc 渲染到 页面中,但是能够被渲染出abc 的只有 id=app1中的msg表达式,因为实例 vm 这个 Vue对象的el 属性指定了该Vue对象啊只会服务于app 对应的这个标签。所以app2 这个标签 中的 {{ msg }} 只会被当作一个字符串按照原本的形式的输出,而不是作为一个Vue对象中的变量进行渲染。
data 中定义了msg变量,这个msg 变量就是页面中 {{ msg }} 数据的由来,通常需要操作的数据都可以定义到 data 结构体,这样也会方便我们使用。
methods 中 可以定义一个个函数,key为函数名,是这个函数对象引用,等同于一个变量,上面得代码中,通过v-on指令,将这个函数绑定为一个点击事件的处理函数,v-on:click:="a" 指定一个函数对象,用于处理这个click 的事件,当我们通过点击触发这个事件时,将会执行这个处理函数,也就是调用变量a 引用的函数,也就是执行 a() 。所以这里需要一个函数对象。当然可以直接指定函数。 ,也可以是其他的表达式,只要最后的是一个函数对象即可。
插值语法
可以在页面中的增加插值的位置,该位置的值随着变量改变,语法规则是使用 {{ msg }} 双大括号,内部是一个表达式,此处会将msg这个变量的值渲染出来,而不是直接输出啊这个表达式的字符串。
指令
基本指令介绍
官网api:https://cn.vuejs.org/v2/api/#v-html
- v-text:渲染指定表达式的值,按照原字符串的形式进行渲染 ""
- v-html:渲染指定的表达式的值,这个值会按照html 的语法进行渲染,而不是直接直接输出字符串。
- v-pre:默认标签中{{ msg }} 会被作为一个表达式解析,在标签中定义该属性后,不会解析这个表达式,而是直接输出 {{ msg }} 这个字符串。
- v-cloak:某些情况下,标签会先渲染,然后在替换内部的变量的内容,给标签指定该属性,只有在变量渲染后才会展示到到页面中。
- v-once:如果标签中使用了data 中的数据,该数据改变时该值会自动重新渲染,指定该v-once属性之后,这个标签只会渲染一次,即使data数据改变也不会重新渲染这个标签。
<span v-text="msg">span> <span>{{msg}}span> <span v-html="msg">span> <span v-pre>{{ 相当于一个原始的标签,即使使用了了插值表达式 }}span> <div v-cloak> {{ message }} div> // 只会显示message 指定的结果 <span v-once >这个msg 只会被渲染一次,被渲染后,即使msg的内容发生了改变,也不会重新更新内容: {{msg}}span>
- v-if:if 后对应的值为 true 时候,才会在页面中创建该标签。
- v-else:前面一定是带有 if 或者 else-if 指令的标签,当以上的条件都不满足时候,将会渲染这个标签。
- v-else-if:前面一定有 if ,else-if 的 值为 true 时,才会渲染该标签。
- v-show:指定渲染的条件,如果条件为true,会在页面中的显示,否则会给改标签添加 css 中的 dispaly,隐藏这个标签。
v-if 和 v-show 的区别是,if 是根据条件选择性的创建满足条件的标签,而不满足条件的标签是不会被创建的。而 v-show 的标签都会被创建,只是将不满足条件的标签使用了display属性而无法展示出来。
因此:当需要根据条件渲染标签时候,使用 if 反复的创建会消耗cpu的性能,使用show 会将所有组件全部渲染而消耗一部分内存,根据业务实际情况考虑即可。
<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>
- v-for:循环展示的多个标签,为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一
key
// 遍历数字 <p v-for="count in 10" :key="count"> {{count}} p> // 遍历1-10,count从1 开始,会出现10个p标签 // 遍历数组 <p v-for="(val, index) in items" :key="val"> 值为{{val}},{{index}} 为index p> <p v-for="(item, index) in items" :key="item.id"> 值为{{item.attr}},{{index}} 为index p> // 遍历对象 <p v-for="(val, key, index) in object" :key="key"> 值为 {{val}},{{key}}, {{index}} 为index p> // v-for 可以和if 共同使用, 并且for 的优先级比if 更高,也就是先遍历 数组,其中满足 if 条件的项才会被渲染。 <li v-for="todo in todos" v-if="!todo.isComplete"> {{ todo }} li> // 当在组件上使用 v-for 时,因为组件有自己的作用域,所以在组件标签使用的变量,需要使用v-bind绑定,同时还要再组件 // 内部定义 props数组才能接收对应的变量值。 <ul> <li is="todo-item" // is=todo-item 指定这个li 其实是一个> 组件 v-for="(todo, index) in todos" v-bind:key="todo.id" // key 没有再 props 中定义,所以内部无法获取到这个值 v-bind:title="todo.title" // 这个title变量的值要在组件内部使用,而组件内部props 中定义了title v-on:remove="todos.splice(index, 1)" >li> ul> <script> // 组件对象 Vue.component('todo-item', { template: '\ \ {{ title }}\ \ \ ', props: ['title'] // 内部使用了外部的 title 变量,需要使用props 定义来自外部 }) var vm = new Vue({ el: '#todo-list-example', data: { todos: [ { id: 1, title: 'Do the dishes',}, { id: 2, title: 'Take out the trash',}, { id: 3, title: 'Mow the lawn'} ], }, )} script>
- v-bind:使用该指令后,该指令对应的属性在为其指定值时,可以使用Vue对象中变量来指定,也可以是一个表达式 Vue会将指定的中作为表达式解析得到结果。同时无法直接在属性上使用 插值表达式进行赋值,就需要v-bind 进行属性绑定。bind的对象是Vue对象,指定的任何变量都是这个Vue对象的上的属性。
<img v-bind:src="imageSrc"> <img :src="imageSrc"> <img :src="'/path/to/images/' + fileName"> <div v-bind="{ id: someProp, 'other-attr': otherProp }">div> <div v-bind:text-content.prop="text">div> <my-component :prop="someThing">my-component> <child-component v-bind="$props">child-component> // $props 表示父组件的 this.$props 属性值 <script> var vm = Vue({ data: { imageSrc:"", otherProp:"" fileName:"", text:"" someProp: "",someThing }, }) script>
- v-on:为一个标签绑定事件监听函数,需要使用v-on 指令,指定事件的类型和处理函数即可
。 - v-model:实现数据的双向绑定,v-model关联的变量,标签中的值 和 data 中的值是双向绑定的,一方会随着另一方进行改变。通常用来获取页面中输入框内部用户输入的数据。
class 和 style 绑定
指定标签的class 和 style 内联样式也是可以通过v-bind 绑定Vue对象中的数据,从而使用Vue中的属性动态赋值。
class 语法
1. 最原始的方式,未使用 v-bind <p class="class1 class2 class3"> 类名为 class1,class2, class3 2. 数组的方式 <p :class="[c1, c2, c3]"> // c1, c2, c3 是变量名, 他们对应了真实的类名的字符串 "class1" "class2" "class3" <p :class="[{c1:true}, c2, {c3:flag}]"> // 某些类名根据条件判断使用 <p :class="[flag? c1:"" , c2, c3]"> data:{ c1: "class1", c2: "class2", c3: "class3", flag:true } 3. 使用对象的语法 <p :class="{class1:flag1, class2:flag2, class3:flag}"> // key就是类名,不会作为变量编译,即使没有加 引号,valuea才会当作变量
// Vue对象中data 的值 data:{ flag1:true, flag2:true, flag3:true }
style
style 内联样式的指定方式是在对应的 样式名 指定对应的值即可,样式的值可以使用变量或者是表达式来指定。
这是原始的样子 <div style="{ color: 'red', fontSize:'20px'}">div> 1. 对象的指定方式:对象的指定方式就是每个样式的值可以使用变量或者表达式替代 <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }">div> // value 是变量或者表达式 data: { activeColor: 'red', fontSize: 30 } // 也可以这样 <div v-bind:style="styleObject">div> // 变量指定为一个对象,直接将对象全部替换过来 data: { styleObject: { color: 'red', fontSize: '13px' } } 2. 数组的指定方式:数组主要是解决多个样式对象的合并 <div v-bind:style="[baseStyles, overridingStyles]">div> data: { baseStyles:{ color: 'red', fontSize: '13px' }, overridingStyles:{ width:"500px", height: "600px" } }
v-on 事件监听
通过对标签绑定事件,当事件触发,将会执行对应的事件函数。
事件修饰符
事件修饰符是进一步指定事件的触发状态,常用的有
.stop- 调用event.stopPropagation()。事件触发该标签后不会向外继续冒泡触发外部标签的事件。.prevent- 调用event.preventDefault()。阻止默认的事件行为,只会调用我们指定的事件处理函数。.capture- 添加事件侦听器时使用 capture 模式,开启在捕获过程的事件监听,默认只会在冒泡过程监听。.self- 只当事件是从侦听器绑定的元素本身触发时才触发回调函数。.left- (2.2.0) 只当点击鼠标左键时触发。.right- (2.2.0) 只当点击鼠标右键时触发。.middle- (2.2.0) 只当点击鼠标中键时触发
.{keyCode | keyAlias}- 只当事件是从特定键触发时才触发回调,也就是绑定指定按键去触发事件。.native- 监听组件根元素的原生事件。.once- 该标签只触发一次回调事件。.passive- (2.3.0) 以{ passive: true }模式添加侦听器
多个标签嵌套使用时候,当触发内部标签,此时事件有一个传递的过程,分为捕获和冒泡,捕获过程是事件由外部标签向内部传递的过程,而内部元素事件向外部传递为冒泡过程。
语法
1. 指定事件类型,绑定一个处理函数 <button v-on:click="doThis"> button> // doThis 是一个变量 <button @click="doThis"> button> // 缩写 <button v-on:click="doThat('hello', $event)"> button> // 内联调用,可以方便传参 2. 使用修饰符 <button @click.stop="doThis">button> <button @click.prevent="doThis">button> <button @click.stop.prevent="doThis">button> <input @keyup.enter="onEnter"> <input @keyup.13="onEnter"> 3. 使用对象语法监听多个事件 <button v-on="{ mousedown: doThis, mouseup: doThat }">button> var vm = Vue({ methods:{ // 定义事件处理函数 doThis(){}, doThat(params1, params2){}, onEnter(){} } })
自定义按键修饰符
Vue中提供的按键修饰符有
.enter.tab.delete(捕获 “删除” 和 “退格” 键).esc.space.up.down.left.right.ctrl.alt.shift.meta
我们也可以自己定义系统没有提供的按键,上述的.enter 修饰符 来指代 enter 键的事件,只是为enter 键的码值指定了一个名字,然后绑定到Vue对象的属性上,我们也可以自己将一个码值绑定到Vue上,就可以使用该修饰符号了,例如 F2 的键盘码值是 113,我们为其创建一个修饰符名称 f2,绑定到Vue上
// 1.0版本中设置的方式,Vue.direative("on").keyCodes.f2 = 113 Vue.config.keyCodes.f2 = 113 // 定义了 113 这个码值的变量为 f2 这样可以使用键值修饰修饰符 f2 <input @keyup.f2="onEnter"> // 这样就可以使用f2 这个修饰符号为 input 标签定义一个F2 按键对应按键抬起事件
v-model 双向数据绑定
双向数据绑定是指 你可以通过 改变data 中的数据来改变 标签中的显示,也可以更改标签中的数据使得data中的数据同步修改。这是一个双向绑定的过程,这非常便利的使得我们可以时刻获取输入框的数据,一旦输入框内容改变,Vue中data的数据是同步改变的。
原理
v-model其实是一个语法糖,它的背后本质上是包含两个操作:
- 1.v-bind绑定一个value属性
- 2.v-on指令给当前元素绑定input事件,每次输入完成,获取input中的value,更新data中的 value
redio的使用
选中一个redio 时,会使用被选中的项 的 value 属性的值,赋值给 v-model指定的变量,从而改变data中的 变量值。
<div id="app"> <input type="radio" id="man" value="男" v-model="sex">男 <input type="radio" id="woman" value="女" v-model="sex">女 div> <script src="../js/vue.js">script> <script> const app = new Vue({ el: '#app', data: { sex: '男' } }) script>
checkbox的使用
单个勾选框:选中isagree 被指定为true,未选中指定为false
<label for="agree"> <input type="checkbox" id="agree" v-model="isagree">同意协议 <h1>你的选择是:{{isagree}}h1> <script src="../js/vue.js">script> <script> const app = new Vue({ el: '#app', data: { isagree: false } }) script>
多个勾选框:被选中项的value,在data中使用一个数组保存。
<div id="app"> <input type="checkbox" value="red" v-model="color">红 <input type="checkbox" value="yellow" v-model="color">黄 <input type="checkbox" value="green" v-model="color">绿 <input type="checkbox" value="blue" v-model="color">蓝 div> <script src="../js/vue.js">script> <script> var app = new Vue({ el: '#app', data: { color: ["red", "blue"] // 储存被选中的内容 } }) script> body>
v-model 的修饰符
.lazy修饰符:
- v-model默认是在input事件中同步输入框的数据的, 一旦有数据发生改变对应的data中的数据就会自动发生改变。
- lazy修饰符可以让数据在 input标签 失去焦点或者回车时才会更新,而不是实时更新,这样更节约性能。
number修饰符:
- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
- number修饰符可以让在输入框中输入的内容自动转成数字类型
trim修饰符:
- 如果输入的内容首尾有很多空格,使用 trim修饰符可以自动去除内容左右两边的空格。
自定义指令
当标签使用我们自定义的指令后,这个指令会获取这个标签对象,并在这个标签从生成到插入节点再到销毁的过程中绑定一些执行函数,去执行一些操作。这也是自定义指令的常用方式,例如我们可以定义一个指令 v-focus,这个指令的作用为,被该指令指定的标签,在页面完全加载完成后会获取到焦点。
自定义指令原理
自定义指令提供了几个生命周期函数,标签执行一下操作的过程中会触发这些操作函数来操作标签,从而实现我们自定义指令期望的功能
// 全局定义一个指令,所有Vue对均可使用 Vue.direactive("focus", {} ) - 参数1:指令名字, 定义时不需要添加v-前缀,调用时必须添加前缀 - 参数2:一个对象,对象中有多个函数,这些函数在标签生命周期的特定时刻。 { bind:function(el){}, // 指令绑定到DOM上时触发,bind不是插入到dom中,只触发一次, 参数 el 为被绑定的dom元素对象 inserted: function(el){}, // 当被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 updated: function(el){}, // vNode 被更新的时候执行,可以执行多次。 componentUpdated: function(el){}, //指令所在组件的 VNode 及其子 VNode 全部更新后调用。 unbind:function(el){}, //只调用一次,指令与元素解绑时调用。 } // 局部定义 var vm = New Vue({ el:, methods:{}, data:{}, directive:{ focus:{ inserted:function(el){}, bind:function(el){} } }, })
指令钩子函数的参数
指令通常有两种使用方式,传值和不传值,例如下面的两种自定义指令用法
<input v-focus v-color="'red'">
每个钩子函数都可以定义形参来接收参数值,我们可以在 钩子函数中使用4个形参去接收被注入钩子函数的四个参数。被注入的四个参数值分别为以下的数据。
el:指令所绑定的元素,可以用来直接操作 DOM 。
binding:一个对象,包含以下 property:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
使用参数
以一个钩子函数为例,我们接收这个四个参数,这样在这个钩子函数就可以使用这个四个参数值。根据上述四个参数值的实际意义,我们可以获取到指定的内容。
var vm = new Vue({ el: directive:{ color:{ bind: function(el, binding, vnode, oldVnode){ console.log(el) console.log(binding) console.log(vnode) console.log(oldVnode) } } } })
通常情况下,我们只需要前两个参数即可获得基本的数据,第一参数为该标签的dom对象,第二次参数为一个结构体,内部包含了标签中传入的值,以及原始表达式,以及其他参数信息。我们想要获取v-color上的 'red',直接从第二个参数获取即可
var vm = new Vue({ el: directive:{ color:{ bind: function(el, binding, vnode, oldVnode){ console.log(binding.value) // 获取 v-color="'red'" 中的 'red' console.log(binding.arg) // 获取 v-color:foo 中的参数 "foo" } } } })
如果这个指令的钩子函数只有 bind 和 update方法,可以直接简写方法函数,不需要指定bind这个操作的名字。
特殊属性
我们在一个标签中可以定义几个特殊的属性。例如
<p key="k1" ref="name1" is="my-component"> item1 p> <p key="k2" ref="name2"> item2 p> <p key="k3" ref="name3"> item3 p>
key
key 这个特殊的属性主要是用来 服务于 Vue 的虚拟 DOM 算法,key 是虚拟的dom节点的唯一标识,在Vue中,为了最大的节约资源,提高性能从而提高响应速度,Vue 会使用一种 "最大限度减少动态元素" 并尽可能的尝试 "就地修改和复用相同类型元素" 的算法。没有key 对这个元素进行唯一标识,在渲染一个相同类型的元素时,将会复用这个元素,这样可以避免新创建一个 vnode 对象,节约性能,但是在某些情况下复用组件可能出现问题,造成渲染错误。
举例说明:以下会根据 flag 的 真假值选择渲染 login 或者 reg 中的其中一个标签
<input v-if="flag" value="" id='login'> <input v-else value="" id='reg'>
一开始,我们选择 login组件,并在输入框中输入内容,然后通过改变flag 为 false 切换到 reg 这个 输入框中,而此时我们刚才输入的内容不会消失,而是保持原来的内容,这就是Vue复用组件的例子。当需要渲染一个input 时候,Vue并没有立刻创建一个新的标签,而是发现有一个闲置的input 没有被使用,所以就用他复用,复用前对某些必要的值进行了修改,但没有将其全部重置,所以可以保留了部分原来的内容,从而造成渲染错误。
通过 添加key 属性来对标签唯一标识,就不会出现类似的情况,当我们从 login 切换到 reg 时候,由于两个input 的key值不同,所以Vue不会复用这个标签。
key 属性在 v-for 指令中常常使用,为了使其每一项都有自己的唯一标识,从而避免标签复用而产生错误。如果是在组件中,那么所有的 v-for 都必须加上 key属性,每项使用一个唯一的值来标识自己。
因此,有相同父元素的子元素必须有独特的 key。重复的 key 或者未指定 key 都可能会造成渲染错误。
ref
ref 属性的作用是为了 让Vue对象更好的获取这个对应的标签,从而对该标签进行操作。获取这个对象只需要访问vue实例对象的 $refs 属性,内部记录了 所有被赋予 ref 属性的标签。
示例,在vue 中获取 标签对象
<p key="k1" ref="name1" is="my-component"> item1 p> <p key="k2" ref="name2"> item2 p> <p key="k3" ref="name3"> item3 p> <script> var vm = Vue({ el:"", methods:{ getref(){ console.log(this.$refs) // 输出一个对象key为每个ref属性的值,value 为每一个标签对象 } } }) script>
如果我们需要方便的获取某一个标签,添加一个ref属性,并指定一个名字即可。
is
is 属性是为了实现动态组件。如果需要在页面中使用组件,就需要使用这个组件命的标签,例如有一个组件名为 my-comp,则需要这样使用。
<div class="contain"> <my-comp> my-comp> div>
如果使用 is 属性,就可以随意指定标签,然后在标签中添加 is = my-comp 的属性,这样这个标签会被渲染成is 指定的组件。
<div class="contain"> <div is="'my-comp'"> div> ///该div 会被渲染为 my-comp标签 div>
过滤器 filter
使用过滤器
过滤器就是一个函数,将某个变量进行处理后,输出 return 指定的值。
在插值表达式中使用过滤器的语法为 {{ name | filter_name}} , 也可以连续使用多个过滤器 {{ name | substring("hello") | filter2() }} ,过滤器 也可以直接传参,但是过滤器的第一个形参接收的值始终是被过滤的元素本身,传入的参数只能从第二个参数开始计算。
定义过滤器
过滤器就是一个函数,用来对一个值进行指定的操作,定义一个过滤器可以有两种定义的方式,全局定义和局部定义、
全局定义即定义后,该页面中所有的Vue中对象都可以访问这个过滤器,然后给自己的变量使用。
局部定义的过滤器,只有在该Vue对象可以访问到,也就只有自己可以使用
<p> {{ data | filter_name1 }} p> // 不带参数 <p> {{ data | filter_name2("k-on-")}} p> // 带参数 <script> // 全局定义的过滤器,直接咋Vue类上定义,而不是在某个new出来的实例对象中,全局所有的Vue对象都可以使用 Vue.filter("filter_name1", (data) => { return ture } ) // data管道符传入的数据, 上面的name,返回值为结果 // 私有的过滤器,在 Vue 对象内部定义。 var vm = new Vue({ el:"#app", data:{}, methods:{ fun_name:() => {}, }, filters:{ filter_name1: (data)=>{ return "k-on-" + data }, filter_name2: (data, prefix){ // 带参数的过滤器,第一形参是被过滤对象,我们传入的参数从第二个位置开始接收 return prefix + data } } }) script>
如果私有过滤器和全局的过滤器名字重复,vue对象在使用过滤器时,会首先查看自己有没有该过滤器,如果有,则优先使用自己的过滤器。