Vue.js是一个基于MVVM思想的前端框架和angular类似
首先要引用它的js文件
和js一样直接下载源文件引用就可以
但是这次用一个别的方式
通过BootCDN加速服务引用
官网:http://www.bootcdn.cn/
这个网站里有很多前端
里面有很多前端的插件,点进去后有链接,把链接直接复制过去就可以使用,这样就不需要下载为本地文件了,为项目节省的空间,但是使用时必须联网
(简单说其实就是cdn开了一个服务器帮你存储这些文件,你通过网络访问它的服务器)
下面进入正题
Vue.js的核心是一个简洁的模板语法
写模板时需要一个容器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://cdn.bootcss.com/vue/2.5.9/vue.js"></script> </head> <body> <!--↓h1就是一个容器,{{bug}}为占位符--> <h1 id="Id">{{bug}}</h1> </body> </html> <script> //↓Vue对象 var app = new Vue({ el:"#Id", //要操作的容器 data:{ bug:"值" //为容器中的占位符赋真实的值 } }); </script>
这样在运行网页时,{{bug}}就会替换为值
{{}}中不止可以放属性名称,还可以放一些简单的运算符(一行就可以结束,且得出结果的,如三目运算符)
<div>{{100/2*8}}</div> <div>{{sex==1?"男":"女"}}</div>
除了给标签复制,我们还能为标签添加属性
<div id="d" v-bind:href="msg">aaaaaa</div> <script> var app = new Vue( { el:"#d", data:{ msg:"链接" } }); </script>
除了href.其他属性也可以通过v-bind绑定,如class,name等
v-bind可以省略,简写为
<div id="d" :href="msg">aaaaaa</div>
如果要绑定事件用 v-on
<div id="d" :href="msg"> <div v-on:click="fangfa">点击事件</div> </div> <script> var app = new Vue( { el:"#d", data:{ msg:"链接" },methods:{ fangfa:function(){ alert("点击了"); } } });
这里我们在Vue对象里加了一个methods,是用来创建方法的
v-on也是有简写方法
<div @click="fangfa">点击事件</div>
插一个有趣的小功能,文字反转
<div id="d" :href="msg"> <div>{{msg}}</div> <button @click="fangfa">反转</button> </div> <script> var app = new Vue( { el:"#d", data:{ msg:"balabaaanalsdakdjakkasnckasncasncjksksnkdsnkfsk" }, methods:{ fangfa:function(){ this.msg = this.msg.split('').reverse().join('') } } }); </script>
reverse() 把数组中元素的顺序颠倒
到这里为止,我们之前的操作都是数据绑定到页面的单向绑定,那么我们怎么才能让页面也绑定到数据,实现双向绑定呢?
在页面的标签上添加v-model属性
<div id="d" :href="msg"> <div>{{msg}}</div> <input type="text" v-model="msg"> <button @click="fangfa">反转</button> </div> <script> var app = new Vue( { el:"#d", data:{ msg:"balabaaanalsdakdjakkasnckasncasncjksksnkdsnkfsk" }, methods:{ fangfa:function(){ this.msg = this.msg.split('').reverse().join('') } } }); </script>
这样文本框就和msg进行了绑定,文本框的值改变msg的值也会随之改变
之前我们有说过{{}}可以放简单的运算,但是也只是简单的,如果我们需要进行复杂的计算时,就要用到计算属性 computed
<div id="d" :href="msg"> <div>{{jisuan}}</div> </div> <script> var app = new Vue( { el:"#d", computed:{ jisuan:function(){ if(1+1<3){ return "小于" }else{ return "大于" } } } }); </script>
在computed中可以声明方法,然后在方法总进行操作,最终把结果返回出来
在{{}}写上方法的名称,就会调用这个方法,然后把返回值作为实际的值显示
计算属性中是可以写get和set的
computed:{
jisuan:{
get:function(){
},
set:function(){
}
}
}
虽然大部分情况使用计算属性就很合适,但是有时也会需要一个监听器 watch
<input type="text" v-model="zhanghao"> <div>{{answer}}</div> <script> var app = new Vue( { el:"#d", data:{ zhanghao:"", answer:"" }, watch:{ //监视zhanghao属性,如果zhanghao发生改变就会调用此方法 zhanghao:function(){ if(this.zhanghao.length<6){ this.answer = "账号必须大于6位" }else{ this.answer = "OK" } } } }); </script>
判断和循环
v-if和v-for的作用就不解释了,直接看语法吧
<div v-if="true">显示</div> <!-- if为false,继续判断else if --> <div v-if="false">不显示</div> <!-- else if为true 显示这个标签 --> <div v-else-if="true">不显示2</div> <!-- else if只会进一个,所以这个为true也不会显示 --> <div v-else-if="true">不显示3</div> <!-- 如果上边都不进就会显示这个 --> <div v-else>else</div>
<div v-for="(item,index) in arr"> <div>{{item}}</div> </div> <script> var app = new Vue( { el:"#d", data:{ arr:[1,2,3,4,5] } }); </script>
item是值,index是下标,arr是要循环的数组
自定义指令
我们之前使用了很多vue自身的指令如 v-bing,v-model等等
那么如果我们要自己定义个指令呢
比如
<div v-show="">输出</div>
vue中是没有v-show这个指令的,我们需要通过Vue.directive来创建自定义的指令
Vue.directive是一个全局API
全局API并不在构造器里,而是先声明全局变量或者直接在Vue上定义一些新功能,说的简单些就是,在构造器外部用Vue提供给我们的API函数来定义新的功能。
下面讲解Vue.directive的使用
<div id="vue"> <div v-show="info">输出</div> </div> <script> Vue.directive('show',function(el,binding,vnode){ console.info(el); console.info(binding); console.info(vnode); }); var app = new Vue({ el:"#vue", data:{ info:10 } }) </script>
这样我们就完成了自定义一个v-show指令,注意定义时不需要加v-,但是使用时别忘了加上v-
我们输出了方法中的三个参数,接下来我们来看一下这三个参数都是什么作用
第一个参数 : el
一看就懂,el这个参数就是代表当前使用这个指令的标签,你可以通过这个参数对这个标签做一些操作,比如获取内容,改变样式等
第二个参数 : binding
这个参数存放的是这个指令的一些属性,如指令的名字,传给指令的值等
我们可以把传给指令的值加入到操作中,然后就可以达到传不同的值出现不同结果的效果
小例子:点击字体变大
<div id="vue"> <div v-show="size">字体</div> <button @click="change">变大</button> </div> <script> Vue.directive('show',function(el,binding,vnode){ el.style='font-size:'+binding.value+'px'; }); var app = new Vue({ el:"#vue", data:{ size:20 }, methods:{ change:function(){ this.size++; } } }) </script>
第三个参数 : vnode
一样是当前使用这个指令的标签,但是和el不同的是,它是虚拟节点,el是实际的标签,用js去操作页面上的标签做出更改,比较耗费性能,而vnode则是标签的抽象,是一个js对象,操作js对象性能就会大大提升
它的属性和标签的属性是对应的,当属性改变时,页面也会相应改变 (然而我其实并不是很懂这东西怎么用)
/*当前节点的标签名*/
this.tag = tag
/*当前节点对应的对象,包含了具体的一些数据信息,是一个VNodeData类型,可以参考VNodeData类型中的数据信息*/
this.data = data
/*当前节点的子节点,是一个数组*/
this.children = children
/*当前节点的文本*/
this.text = text
/*当前虚拟节点对应的真实dom节点*/
this.elm = elm
/*当前节点的名字空间*/
this.ns = undefined
/*编译作用域*/
this.context = context
/*函数化组件作用域*/
this.functionalContext = undefined
/*节点的key属性,被当作节点的标志,用以优化*/
this.key = data && data.key
/*组件的option选项*/
this.componentOptions = componentOptions
/*当前节点对应的组件的实例*/
this.componentInstance = undefined
/*当前节点的父节点*/
this.parent = undefined
/*简而言之就是是否为原生HTML或只是普通文本,innerHTML的时候为true,textContent的时候为false*/
this.raw = false
/*静态节点标志*/
this.isStatic = false
/*是否作为跟节点插入*/
this.isRootInsert = true
/*是否为注释节点*/
this.isComment = false
/*是否为克隆节点*/
this.isCloned = false
/*是否有v-once指令*/
this.isOnce = false
自定义指令有五个生命周期(也叫钩子函数),分别是 bind,inserted,update,componentUpdated,unbind
- bind:只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
- inserted:被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。
- update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
- componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
- unbind:只调用一次,指令与元素解绑时调用。
Vue.directive('show',{
bind:function(){//被绑定时
console.log('1 - bind');
},
inserted:function(){//绑定到节点后
console.log('2 - inserted');
},
update:function(){//组件更新时
console.log('3 - update');
},
componentUpdated:function(){//组件更新完成后
console.log('4 - componentUpdated');
},
unbind:function(){//解绑
console.log('1 - bind');
}
});
Vue.extend构造器
用来把写好的模板挂载到自定义的标签上 (我是真看不出和下面的component有什么区别,但是姑且还是记下来吧)
<link></link> //自定义的标签 var authorExtend = Vue.extend({ //模板的对象 template:'<a :href="link">链接</a>', data:function(){ return{ link:'http://www.baidu.com' } } }); new authorExtend().$mount('link'); //将对象挂载到自定义标签上
也可以挂载到普通的标签上,只要填上标签的id就行
<div id="link"></div> new authorExtend().$mount('#link');
如果不想在创建模板对象时在data中给数据,而是在挂载标签时给
可以使用propsData
propsData三步解决传值:
1、在全局扩展里加入props进行接收。props:[‘a’]
2、传递时用propsData进行传递。propsData:{a:1}
3、用插值的形式写入模板。{{ a }}
<div id="link"></div> <script> var authorExtend = Vue.extend({ template:'<a :href="link">链接</a>', data:function(){ return{ } }, props:['link'] }); new authorExtend({propsData:{link:'http://www.baidu.com'}}).$mount('#link'); </script>
自定义组件
自定义组件其实就是自定义一个标签
<com></com> <script> Vue.component('com',{ template:"<div>这是一个组件</div>" }); </script>
第一个参数是自定义的标签,之后的template是模板
现在com标签就等同于''<div>这是一个组件</div>'',当然你也可以在模板里多写点标签,这样一大段标签就变成了一个标签,省了很多事
但是这样写的话,值岂不是都是固定的,这样肯定是不行的,我们要进行一些改进
<com v-for="(item,index) in arr" :items="item"></com> <script> Vue.component('com',{ props:['items'], template:"<div>{{items}}</div>" }); var app = new Vue( { el:"#d", data:{ arr:[1,2,3,4,5] } } </script>
props类似于自定义属性,然后在模板使用这个自定义的属性,并在标签上通过v-bind把自定义属性绑定上去,再给自定义属性赋值
这样模板的值就是动态的了
如果自定义属性带有 -
我们在写属性时经常会加入’-‘来进行分词,比如:<panda from-here=”China”></panda>,那这时我们在props里如果写成props:[‘form-here’]是错误的,我们必须用小驼峰式写法props:[‘formHere’]。
局部注册组件
<div id="vue"> <lianjie :src="a"></lianjie> </div> <script> var app = new Vue({ el:"#vue", data:{ a:'http://www.baidu.com' }, components:{ "lianjie":{ template:'<a :href="src">{{src}}</a>', props:['src'] } } }) </script>
可以看出,其实局部注册就是在Vue对象中注册自定义组件,但是要注意局部注册用的components,而上面是component,要多一个s
这样把所有属性全部都写在Vue对象里,如果组件多了会感觉很乱,我们可以把它们的属性设置提出去
var lianjie = { template:'<a :href="src">{{src}}</a>', props:['src'] }; var app = new Vue({ el:"#vue", data:{ a:'http://www.baidu.com' }, components:{ "lianjie":lianjie } })
组件之间是可以相互嵌套的
<script> var son = { template:'<div>子项</div>' } var lianjie = { template:'<a :href="src">{{src}} <son></son> </a>', props:['src'], components:{ "son":son } }; var app = new Vue({ el:"#vue", data:{ a:'http://www.baidu.com' }, components:{ "lianjie":lianjie } }) </script>
注意模板只能有一个根标签
Component标签
Component标签是用来动态绑定组件的
小例子:点击切换组件
<div id="vue"> <component :is="who"></component> <button @click="change">切换组件</button> </div> <script> var tempA={ template:'<div>模板A</div>' } var tempB={ template:'<div>模板B</div>' } var tempC={ template:'<div>模板C</div>' } var app = new Vue({ el:"#vue", data:{ who:'tempA' }, components:{ "tempA":tempA, "tempB":tempB, "tempC":tempC }, methods:{ change:function(){ if(this.who=='tempA'){ this.who='tempB'; }else if(this.who=='tempB'){ this.who='tempC'; }else{ this.who='tempA'; } } } }) </script>