一. vue中的指令
1.1 v-text
v-text主要是用来更新textContent,可以等同于js中的text属性
<span v-text="msg"></span>
这两者等同于
<span>{{msg}}</span>
1.2 v-html
双大括号的方式会将数据解释为纯文本,而非html,为了输出真正的html,可以用
v-html指令,它等同于js中的innerHTML。
<div v-html="rawHtml"></div>
这个div的内容将会替换成属性rawHTML,直接作为HTML进行渲染。
<div v-html="message">{{message}}</div>
export default {
data () {
return {
message: "这里可以包含html标签"
}
}
}
message可以包含html标签,来展示一个页面的内容
特别是,如果后端返回包含了标签的内容,可以转化为html页面的形式展示。
1.3 v-pre
v-pre主要是用来跳过这个元素和它的子元素编译过程。可以用来显示原始的Mustache标签,跳过大量没有指令的节点加快编译。
<div>
<span v-pre>{{message}}</span> //这条语句不进行编译
<span>{{message}}</span>
</div>
最终仅显示第二个div的内容。
1.4 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>
<div>
hello world!
</div>
</div>
1.5 v-once
v-once关联的示例,只会渲染一次。之后的重新渲染,实例及其所有的子节点将被视为静态内容跳过,这可以用于优化更新性能。
<span v-once>This never change : {{msg}}</span> //单个元素
<div v-once> //有子元素
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<my-component v-once:comment="msg"></my-component> //组件
<ul>
<li v-for="i in list">{{i}}</li>
</ul>
上面的例子中,msg,list即使产生改变,也不会重新渲染。
1.6 v-if
v-if可以实现条件渲染,vue会根据表达式的值的真假条件来渲染元素。
<a v-if="ok">yes</a>
如果属性值ok为true,则显示,否则,不会渲染这个元素。
1.7 v-else
v-else是搭配v-if使用的,它必须紧跟在v-if或者v-else-if后面,否则不起作用。
<a v-if="ok">yes</a>
<a v-else>no</a>
1.8 v-else-if
v-else-if充当v-if的else-if块,可以链式的使用多次。可以更加方便的实现switch语句。
<div v-if="type===A">
A
</div>
<div v-if="type===B">
B
</div>
<div v-if="type===C">
C
</div>
<div v-else>
Not A,B,C
</div>
1.9 v-show
也是根据条件展示元素。和
v-if不同的是,如果v-if的值是false,则这个元素会被销毁,不再dom中。但是v-show的元素会始终被渲染并保存在dom中,它只是简单的切换css的display属性。
<h1 v-show="ok">hello world</h1>
注意:
- v-if有更高的切换开销
v-show有更高的初始渲染开销 - 如果要非常频繁的切换,则使用
v-show较好 - 如果在运行时条件不太可能改变,则使用
v-if较好
1.10 v-for
用
v-for指令根据遍历数组来进行渲染
有下面两种遍历形式:
<div v-for="(item,index) in items"></div> //使用in,index是一个可选参数,表示当前项的索引
<div v-for="item of items"></div> //使用of
下面是一个例子,并且在v-for中,拥有对父级作用域属性的完全访问权限:
<ul>
<li v-for="item in items">
{{parent}}-{{item.text}}
</li>
</ul>
<script>
var example = new Vue({
el:"#app",
data:{
parent:"父级作用域"
items:[
{text:"文本1"},
{text:"文本2"}
]
}
})
</script>
会被渲染为:
<ul id="app">
<li>父作用域-文本1</li>
<li>父作用域-文本2</li>
</ul>
注意:当v-for和v-if处于同一个节点时,v-for的优先级比v-if更高,这意味着v-if将运行在每个v-for循环中
1.11 v-bind
v-bind用来动态的绑定一个或者多个特性,没有参数时,可以绑定到一个包含键值对的对象,常用于动态绑定class和style。以及href等。简写为一个冒号【:】
1.11.1 对象语法
//进行类似切换的例子
<div class="app">
//当data里面定义的isActive等于true时,is-active这个类才会被添加起作用
//当data里面定义的hasError等于true时,text-danger这个类才会被添加起作用
<div :class="{'is-active' :isActive , 'text-danger' :hasError }"></div>
</div>
<script>
var app = new Vue({
el : '#app',
data : {
isActive : true,
hasError : false,
}
})
</script>
渲染结果:
//因为hasError:false,所以text-danger不被渲染
<div class="is-active"></div>
1.11.2 数组语法
<div id="app">
//数组语法:errorClass在data对应的类中一定会添加
//is-active是对象语法,根据activeClass对应的取值决定是否添加
<p :class="[{'is-active' : activeClass} , errorClass]">123456</p>
</div>
<script>
var app = new Vue({
el : '#app',
data : {
activeClass : false,
errorClass : 'text-danger'
}
})
</script>
渲染结果:
//因为activeClass:false,所以is-active不被渲染
<p class="text-danger"></p>
1.11.3 直接绑定数据对象
<div>
//在vue实例的data中定义了classObject对象,这个对象里面是所有类名及其值
//当里面的类的值是true时会被渲染
<div :class="classObject">123456</div>
</div>
<script>
var app = new Vue({
el : "#app",
data : {
classObject:{
'is-active' : false,
'text-danger' : true
}
}
})
</script>
渲染结果:
//因为'is-active' : false, 所以is-active不会被渲染
<div class="text-danger"></div>
1.12 v-model
这个指令用于在表单上创建双向数据绑定
v-model会自动忽略所有表单元素的value,checked,selected特性的初始值。因为它选择vue实例数据作为具体的值。
<div id="app">
<input v-model="somebody">
<p> hello {{somebody}}</p>
</div>
<script>
var app = new Vue({
el : "#app",
data : {
somebody:"小黄瓜"
}
})
</script>
这个例子中直接在浏览器input中输入别的名字,下面的p的内容会直接跟着变。这就是双向数据绑定。
v-model修饰符
<1>. lazy
默认情况下,
v-model同步输入框的值和数据,可以通过这个修饰符,转变在change事件同步。
<input v-model.lazy = 'msg'>
<2>.number
自动将用户的输入值转化为数值类型
<input v-model.number = 'msg'>
<3>.trim
自动过滤用户输入的首尾空格
<input v-model.trim='msg'>
1.13 v-on
v-on主要是用来监听dom事件,以便执行一些代码块,表达式可以是一个方法名。简写为:【@】
<div>
<button @click="consolog"></button>
</div>
<script>
var app = new Vue({
el : "#app",
methods : {
consoleLog:function(event){
console.log(1)
}
}
})
</script>
事件修饰符
.stop阻止事件继续传播.prevent事件不再重载页面.capture使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元 素进行处理.self只在event.target是当前元素自身时触发处理函数.once事件将只会触发一次.passive告诉浏览器你不想阻止事件的默认行为
//阻止单击事件继续传播
<a v-on:click.stop="doThis"></a>
//提交事件不再重载页面
<form v-on:submit.prevent="onSubmit"></form>
//修饰符可以串联
<a v-on:click.stop.prevent="doThat"></a>
//只有修饰符
<form v-on="submit.prevent"></form>
//添加事件监听时使用事件捕获模式
//即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
<div v-on:click.capture="doThis"> ... </div>
//只当在event.target是当前元素自身时触发处理函数
//即事件不是从内部元素触发的
<div v-on:click.self="doThat"> ... </div>
//点击事件只会触发一次
<a v-on:click.once="doThis"></a>
//滚动事件的默认行为(即滚动行为)将会立即触发
//而不会等待'onScroll'完成
//这其中包含 'enent.preventDefault()'的情况
<div v-on:scroll.passive="onScroll"> ... </div>
使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生。因此,用v-on:click.prevent.self会阻止所有的点击,而v-on:click.self.prevent只会阻止对元素自身的点击。
二.全局API
2.1 Vue.extend(option)
参数:
{Object} options
使用基础Vue构造器,创建一个“子类”,参数是一个包含组件选项的对象。
可以简单的理解为当在模板中遇到该组件名称作为标签的自定义元素时,会自动调用扩展实例构造器来生产组件实例,并挂载到自定义元素上。
data选项是特例,需要注意,在Vue.extend()中它必须是函数
<div id="mount-point"></div>
//创建构造器
var Profile = Vue.extend({
templete:'<p>{{firstName}}{{lastName}} aka {{alias}}</p>',
data : function(){
return{
firstName : 'Walter',
lastName : 'White',
alias : '小黄瓜',
}
}
})
//创建Profile实例,并挂载到一个元素
new Profile().$mount('#mount-point')
结果如下:
<p>Walter White ake 小黄瓜</p>
2.2 Vue.nextTick([callback , context])
参数:
{Function} [callback]{Object} [context]
在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
因为Vue在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
//改变数据
vm.message = 'change'
//想要立即使用更新后的数据,不可以,因为设置message后的DOM还没有更新
console.log(vm.$el.textContent) //并不会得到'changed'
//这样可以,因为nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
console.log(vm.$el.textContent) //可以得到'change'
})
Vue实例
new Vue({
el: '.app',
data: {
msg: 'Hello Vue.',
msg1: '',
msg2: '',
msg3: ''
},
methods: {
changeMsg() {
this.msg = "Hello world."
this.msg1 = this.$refs.msgDiv.innerHTML
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
})
那么什么时候需要用的到Vue.nextTick()呢?
- 1.你在Vue生命周期的created()钩子函数进行的DOM操作一定要放在
Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。 - 2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进
Vue.nextTick()的回调函数中。
原因是,Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。。为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
2.3.set(target,key,value)
参数:
-
{Object | Array} target -
{string | number} key -
{any} value -
target: 要修改的数据源(可以是对象或者是数组) -
key: 要更改的数据 -
value:重新赋的值
响应式修改 , 在列表中动态新增一条数据
根据push添加:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div class="app">
<p v-for="item in arr">{{item.title}}</p>
<button @click="change">添加</button>
</div>
<script>
let app = new Vue({
el : '.app',
data:{
arr:[
{title : '小黄瓜'},
{title : '小番茄'},
{title : '小橘子'},
{title : '小嗨瓜'},
]
},
methods: {
change(){
this.arr.push({title : '这是push插入的'});
}
},
})
</script>
</body>
</html>
通过数组的变异方法,我们可以动态的控制数据的增减,但是我们却无法做到对某条数据的修改,这时候需要set方法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div class="app">
<p v-for="item in arr" :key="item.id">{{item.title}}</p>
<button @click="change">修改</button>
<button @click="change1">添加</button>
</div>
<script>
let app = new Vue({
el : '.app',
data:{
arr:[
{title : '小黄瓜' , id : '0'},
{title : '小番茄' , id : '1'},
{title : '小橘子' , id : '2'},
{title : '小嗨瓜' , id : '3'},
]
},
methods: {
change(){
this.$set(this.arr,0,{title : '长出来一根刺' , id : '7'})
},
change1(){
let chang = this.arr.length;
Vue.set(this.arr,chang, {title : "第二根刺" , id : chang});
}
},
})
</script>
</body>
</html>
警惕! 当写惯了js之后,有可能想改变数组中某个下标中的数据我直接this.arr[ ]就修改了,如:
change(){
this.arr[0] = {title : "小黄瓜" , id : "7"}
}
查看结果:
这种情况,是Vue文档中明确指出的注意事项,由于 JavaScript 的限制,Vue 不能检测出数据的改变,所以当我们需要动态改变数据的时候,Vue.set()完全可以满足我们的需求。
这里可以看出,Vue.set()不光能修改数据,还能添加数据,弥补了Vue数组变异方法的不足
Tip:Vue.set()在methods中也可以写成this.$set()
2.4 Vue.delete(target , key)
参数:
{Object | Array} target{string | number} key/index
删除对象的属性,如果对象是响应式的,确保删除能触发更新视图。这个方法主要用于避开vue不能检测到属性被删除的限制,但是很少用。
data : {
nameliat : {
id : 1,
name : '小黄瓜',
}
}
//删除name
delete this.namelist.name; //js方法
Vue.delete(this.namelist, 'name'); //vue方法
2.5 Vue.directive(id , [ definition])
参数:
{string} id{Function | Object} [definition]
注册或获取全局指令
//注册一个全局自定义指令
Vue.directive('focus' , {
//当被绑定的元素插入到DOM中时。。
inserted : function(el){
//聚焦元素
el.focus()
}
})
注册局部组件,组件接受一个directives 选项:
directives : {
focus : {
//指令的定义
inserted : function(el){
el.focus()
}
}
}
可以在模板的任意元素上使用新的v-focus属性,如下 :
<input v-focus>
自定义指令的生命周期
自定义指令有五个生命周期(也叫钩子函数),分别是
bind,inserted,update,componentUpdated,unbind
-
bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
-
inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。
-
update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
-
componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
-
unbind:只调用一次,指令与元素解绑时调用。
2.6 Vue.filter( id, [definition] )
参数:
{string} id{Function} [definition]
注册或获取全局过滤器。
过滤器可在new Vue实例前注册全局的,也可以在组件上写局部
//全局过滤器
Vue.filter('Father', function (value) {
return value
})
//组件中的局部过滤器
filters:{
componentFather:function(value){
return value
}
},
注意:全局注册时是filter,没有s。而组件过滤器是filters,是有s的,虽然你写的时候没有s不报错,但是过滤器是没有效果.
2.7 Vue.component( id, [definition] )
参数:
-
{string} id -
{Function | Object} [definition] -
第一个参数是自定义元素名称,也就是将来在别的组件中使用这个组件的标签名称。
-
第二个参数是将要注册的Vue组件。
//全局
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="box">
<test></test>
</div>
<script type="text/javascript">
//注册
Vue.component('test', {
template: '<div @click="change">{{msg}}</div>',
data:function(){
return {msg:'我的组件'}
},
methods:{
change:function(){
//todo
console.log(this);
}
}
});
//创建根实例
var vm = new Vue({
el:'#box',
});
</script>
</body>
</html>
//局部注册
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="box">
<test></test>
</div>
<script type="text/javascript">
///定义组件
var testTemplate = {
template: '<div @click="change">{{msg}}</div>',
data:function(){
return {msg:'我的局部组件'}
},
methods:{
change:function(){
console.log(this);
}
}
};
//创建根实例
var vm = new Vue({
el:'#box',
components:{
'test': testTemplate
}
});
</script>
</body>
</html>
2.8 Vue.use( plugin )
参数:
{Object | Function} plugin
安装 Vue.js 插件。如果插件是一个对象,必须提供
install方法。如果插件是一个函数,它会被作为install方法。install 方法调用时,会将 Vue 作为参数传入。
该方法需要在调用 new Vue() 之前被调用。
当 install 方法被同一个插件多次调用,插件将只会被安装一次。
通过全局方法 Vue.use() 使用插件。它需要在你调用 new Vue() 启动应用之前完成:
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...组件选项
})
也可以传入一个可选的选项对象:
Vue.use(MyPlugin, { someOption: true })
Vue.use 会自动阻止多次注册相同插件,届时即使多次调用也只会注册一次该插件。
Vue.js 官方提供的一些插件 (例如 vue-router) 在检测到 Vue 是可访问的全局变量时会自动调用 Vue.use()。然而在像 CommonJS 这样的模块环境中,你应该始终显式地调用 Vue.use():
// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)
2.9 Vue.mixin( mixin )
参数:
{Object} mixin
全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。
基础示例:
//首先定义一个混入对象
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello 小黄瓜')
}
}
}
// 定义一个使用混入对象的组件
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // "hello 小黄瓜"
选项合并 :
//当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。
//数据对象在内部会进行递归合并,并在发生冲突时以组件数据优先。
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// { message: "goodbye", foo: "abc", bar: "def" }
}
})
同名钩子函数将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('组件钩子被调用')
}
})
// "混入对象的钩子被调用"
// "组件钩子被调用"
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。两个对象键名冲突时,取组件对象的键值对。
var mixin = {
methods: {
foo: function () {
console.log('Foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var exm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
exm.foo() // "Foo"
exm.bar() // "bar"
exm.conflicting() // "from self"
混入也可以进行全局注册。
// 为自定义的选项 'myCompontent' 注入一个处理器。
Vue.mixin({
created: function () {
var myCompontent = this.$options.myCompontent
if (myCompontent) {
console.log(myCompontent)
}
}
})
new Vue({
myCompontent: 'hello!'
})
// "hello!"
注意: 一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。
2.10 Vue.compile( template )
参数:
{string} template
在
render函数中编译模板字符串。只在独立构建时有效
var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
data: {
msg: 'hello 小黄瓜'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
2.11 Vue.observable( object )
2.6.0新增
参数:
{Object} object
让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。
返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新。也可以作为最小化的跨组件状态存储器
const state = Vue.observable({ count: 0 })
const Demo = {
render(h) {
return h('button', {
on: { click: () => { state.count++ }}
}, `count is: ${state.count}`)
}
}
2.12 Vue.version
提供字符串形式的 Vue 安装版本号。
var version = Number(Vue.version.split('.')[0])
if (version === 2) {
// Vue v2.x.x
} else if (version === 1) {
// Vue v1.x.x
} else {
// Unsupported versions of Vue
}
本文参考VUE官方文档