第一节(指令)
入门案例
<div id="app">{{msg}}</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"Hello Vue!"
}
});
</script>
if else else-if
<div id="app">
<p v-if="isShow=='if'">{{msg}}</p>
<p v-else-if="isShow=='elseif'">{{msg1}}</p>
<p v-else>其他情况</p>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"Hello Vue!",
msg1:"Hello Vue2!",
isShow:'eleif'
}
});
</script>
v-show
<div id="app">
<p v-show="isShow">{{msg}}</p>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"Hello Vue!",
isShow:false
}
});
</script>
v-show只是显示和隐藏,修改的是css属性,v-if是完全没有加载,减少请求,减轻服务器压力
v-for指令
v-for指令放在需要循环的标签上面,此时是li标签
<div id="app">
<ul>
<li v-for="(item,index) in newItems">{{item}}</li>
</ul>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
items:[11,1,56,3,98,27]
},
computed:{
newItems:function(){
return this.items.sort();
}
}
});
</script>
computed是vue提供的在数据输出之前需要进行的计算的方法,特别注意data里面的变量名(items)和computed里面的变量名不能相同(newItems),而且最后v-for指令使用的是newItems。
v-text和v-html
{{msg}}这种模式在网页加载缓慢和程序出错时候,会在html上面显示{{msg}},体验不好。v-text是绑定数据,可以避免在msg数据请求未成功和代码异常的时候出现{{msg}}这样的错乱数据,会直接不现实对应的标签。v-html是插入html,注意避免xss攻击。
<div id="app">
<p v-text="msg"></p>
<p v-html="msg1"></p>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"<h1>测试</h1>",
msg1:"<h1>测试1</h1>"
},
});
</script>
v-on指令
场景是绑定点击,键盘等事件
<div id="app">
<p>{{msg}}</p>
<input type="text" v-model="msg" v-on:keyup.enter="jiafen">
<button v-on:click="jiafen">加分</button>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:1,
},
methods:{
jiafen:function(){
this.msg=parseInt(this.msg)+parseInt(this.msg);
}
}
});
</script>
v-model 双向数据绑定
基本案例
<div id="app">
<p>{{msg}}</p>
<input type="text" v-model="msg"><br>
<input type="text" v-model.lazy="msg"><br>
<input type="text" v-model.number="msg"><br>
<input type="text" v-model.trim="msg"><br>
</div>
说明:lazy,懒加载,在鼠标移出输入框时候才同步;number,只允许输入数字,会自动去除从第一处不是数字的部分往后的部分,但是注意,如果最开始就输入不是数字,则无效,效果等同于v-model;trim,去除前后空格。
多选绑定一个值
<div id="app">
<p>多选绑定一个值</p>
<input type="checkbox" id="one" v-model="msg"><label for="one">{{msg}}</label>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:true
}
});
</script>
type="checkbox"是多选,下面的msg可以是任何值,在后续切换中会自动转换为true和false,但是为了好理解,建议使用true和false。
单选绑定一个值
<div id="app">
<p>单选绑定一个值</p>
<input type="radio" id="one" v-model="msg" value="男"><label for="one">男</label>
<input type="radio" id="two" v-model="msg" value="女"><label for="two">女</label>
<br>
<p>{{msg}}</p>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"男"
}
});
</script>
注意:下面的msg的内容必须和上面的value的某个内容对应,否则没有默认显示
多选绑定多个值
<div id="app">
<p>多选绑定多个值</p>
<input type="checkbox" id="one" v-model="msg" value="男"><label for="one">男</label>
<input type="checkbox" id="two" v-model="msg" value="女"><label for="two">女</label>
<input type="checkbox" id="three" v-model="msg" value="不明确"><label for="three">不明确</label>
<br>
<p>{{msg}}</p>
</div>
<script>
var app=new Vue({
el:"#app",
data:{
msg:[]
}
});
</script>
说明:注意msg必须是数组,否则会被当成布尔值处理,及要么全选要么全不选
v-bind
bind绑定的是标签的属性
<body>
<div id="app">
<!-- 三元运算符显示不同的图片 -->
<img v-bind:src="isOk?pathA:pathB" width="200px" height="300px" >
<!-- 绑定路径 -->
<a :href="path">百度</a>
<!-- 内部绑定style -->
<p :style="{color:'red'}">{{isOk}}</p>
<!-- 绑定外部style,注意此处是class -->
<p :class="[styleA,styleB]">{{isOk}}</p>
<!-- 绑定已经写好的style对象,同理:style也可以对应[]绑定多个 -->
<p :style="styleObj">{{isOk}}</p>
</div>
</body>
</html>
<style>
.styleA{
color: green
}
.styleB{
font-size: 20px
}
</style>
<script>
var app=new Vue({
el:"#app",
data:{
isOk:false,
pathA:"./img/1.jpg",
pathB:"./img/2.jpg",
path:"http://www.baidu.com",
styleA:"styleA",
styleB:"styleB",
styleObj:{
color:'pink',
fontSize:'30px'
}
}
});
</script>
说明:v-bind 简略写法:,注意html中的:class和:style
其他指令
v-pre:原样输出
v-cloak:渲染完成后才显示,避免错乱数据和v-text的区别是,text在vue对象没有的时候,及代码有重大错误时候,啥也不显示,但是v-cloak还会原样输出。
v-once:只在第一次渲染时候进行渲染,例如双向数据绑定时候,只想让某一处显示第一次渲染的值。
第二节(全局API)
在构造器外面利用vue提供的api构建新的功能,就叫做全局API
Vue.directive(自定义指令)
自定义指令有五个生命周期: bind:"被绑定"只执行一次,inserted:"绑定到节点",update:"组件更新",componentUpdated:"组件更新完毕",unbind:"解绑".
<body>
<div id="app">
<p v-jspang="color">{{msg}}</p>
</div>
</body>
</html>
<script>
Vue.directive("jspang",function(el,bindding){
el.style="color:"+bindding.value;
});
var app=new Vue({
el:"#app",
data:{
msg:"测试",
color:"green"
}
});
</script>
> 说明:利用directive自定义指令是在构造器外面,且自定义指令名称是不加v-的,此处直接是jspang,但是上面使用是v-jspang,注意自定义指令名称不要出现大小写间隔(例如jsPang),会无法识别然后报错。另外,传入的参数el指的就是<p v-jspang="color">{{msg}}</p>这个dom对象,bindding指的是v-jspang="color",bindding.value就是获取的值color,bindding.name就是jspang,可以打印看看bindding其他属性。而v-jspang="color"中的color就对应app对象中的green,从而产生效果。
Vue.extend(构造器延伸)
<body>
<div id="app">
<author></author>
<div id="author"></div>
</div>
</body>
</html>
<script>
var author=Vue.extend({
template:"<a :href='authorUrl'>{{msg}}</a>",
data:function(){
return {
authorUrl:"http://www.baidu.com",
msg:"点击到百度"
}
}
});
new author().$mount("author");
new author().$mount("#author");
</script>
说明:构造器延伸一般和组件一起使用,此处只是基本展示。Vue.extend内部和vue的正常构造器一样是一个对象,对象内部是模板template,注意此时data是一个函数,然后return一个{},内部按照正常构造器的data书写即可。最后一定要挂载,不挂载无效。new author().$mount("author");可以是标签,id和类的挂载形式。
Vue.set(全局操作)
js中数组中数据的更新(包括变更,数组长度变化等),dom无法监听,所以提供set方法进行数组相关操作.
基本案例
<body>
<div id="app">
{{num}}
</div>
<p><button onclick="add()">添加</button></p>
</body>
</html>
<script>
function add(){
//方式一
// Vue.set(objData,"num",++objData.num)
//方式二
// objData.num++;
//方式三
// app.num++;
}
var objData={
num:1
}
var app=new Vue({
el:"#app",
data:objData
});
</script>
说明:三种方式都可以更改数据更新dom。
数组更新案例
<body>
<div id="app">
<ul>
<li v-for="(item ,index) in nums">{{index}}--{{item}}</li>
</ul>
</div>
<p><button onclick="add()">添加</button></p>
</body>
</html>
<script>
function add(){
// app.nums[0]="测试"; 无效
//有效
Vue.set(objData.nums,1,++objData.nums[1])
}
var objData={
nums:[1,2,3,4]
}
var app=new Vue({
el:"#app",
data:objData
});
</script>
说明: 此时直接app.nums[0]="测试";是无效的,因为js不会监听到数组变化从而也就不会引起dom更新,但是如果在修改之前修改一下其他变量(非数组的),就会引起dom更新,从而数组变化也会有效。注意:Vue.set操作普通数据和数组数据参数有区别.Vue.set(objData.nums,1,++objData.nums[1])其中1是数组索引,和Vue.set(objData,"num",++objData.num);
三种创建模板的形式
<body>
<div id="app">
</div>
<!-- tempalte标签模板,可以在app之外 -->
<template id="tl1">
<p><a href="http://www.baidu.com">百度</a></p>
</template>
<script type="x-template" id="tl2" >
<p><a href="http://www.baidu.com">百度</a></p>
</script>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
template:"#tl2" //template标签模板,通过id设置
// 选项模板
// template:`
// <p><a href="http://www.baidu.com">百度</a></p>
// `
})
</script>
说明:script标签模板,必须添加type="x-template" ,最后都是靠给app构造器里面的template属性设置id,class等设置模板。
组件
自定义指令针对的是属性,而组件功能更强大,而模板是组件的一部分。
局部组件和全局组件
<body>
<div id="app">
<jspang></jspang>
<jspang1></jspang1>
</div>
</body>
</html>
<script>
// 这是全局组件,虽然是全局的,但是也要放在注册过构造器的
//标签里面使用
Vue.component("jspang",{
template:`<p>{{msg}}</p>`,
data:function(){
return{
msg:"测试"
}
}
});
var app=new Vue({
el:"#app",
components:{
//“jspang1”是组件名称必须是字符串类型,这是局部组件,只能在该构造器
//对应的标签内部使用
"jspang1":{
template:`<p style="color:green">{{msg}}</p>`,
data:function(){
return {
msg:"呵呵呵"
}
}
}
}
})
</script>
props传参基本案例
<body>
<div id="app">
<zengqiang info="xinyang"></zengqiang>
</div>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"数据来源"
},
components:{
"zengqiang":{
template:`<p style="color:red">来自--{{info}}</p>`,
props:['info']
}
}
})
</script>
说明:模板中的{{info}}来源是props,注意props的值是数组,因为属性可能有多个,而props中的info对应的就是zengqiang标签中的info属性的值
props传参演化案例
<body>
<div id="app">
<zengqiang v-bind:info="msg"></zengqiang>
</div>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
data:{
msg:"xinyang"
},
components:{
"zengqiang":{
template:`<p style="color:red">来自--{{info}}</p>`,
props:['info']
}
}
})
</script>
说明: v-bind是绑定属性的,数据来源是data,后续关联关系等同于上个案例
父子组件
重要案例:
<body>
<div id="app">
<zengqiang v-bind:info="msg"></zengqiang>
</div>
</body>
</html>
<script>
var zengqiangerzi={
template:`
<p style="color:red">来自儿子--{{info1}}</p>
`,
props:['info1']
};
var zengqiang={
template:`
<div>
<p style="color:red">来自--{{info}}</p>
<zengqiangerzi v-bind:info1="msg1"></zengqiangerzi>
</div>
`,
data:function(){
return{
msg1:"henan"
}
},
props:['info'],
components:{
"zengqiangerzi":zengqiangerzi,
}
};
var app=new Vue({
el:"#app",
data:{
msg:"xinyang"
},
components:{
"zengqiang":zengqiang,
}
})
</script>
说明:dom是从上往下加载,所以子组件要定义在父组件上面,否则会报错。
component标签
动态绑定组件,根据数据不同绑定不同的组件
基本案例
<body>
<div id="app">
<component v-bind:is="who"></component>
</div>
</body>
</html>
<script>
var c1={
template:`<p style="color:red">测试</p>`
}
var c2={
template:`<p style="color:black">测试</p>`
}
var c3={
template:`<p style="color:pink">测试</p>`
}
var app=new Vue({
el:"#app",
data:{
msg:"xinyang",
who:"c2"
},
components:{
"c1":c1,
"c2":c2,
"c3":c3
}
})
</script>
说明:component一般和v-bind:is配合使用,对应值是构造器里面的data的数据,注意:components内部的key和value一定是key是字符串,不要弄反了。
第三节(构造器选项)
propsDataOption
<body>
<div id="app">
<div id="hehe"></div>
</div>
</body>
</html>
<script>
var header_a=Vue.extend({
template:`<p>{{msg}}--{{info}}</p>`,
data:function(){
return {
msg:"测试信息"
}
},
props:["info"]
});
new header_a({propsData:{info:"参数信息"}}).$mount("#hehe");
</script>
说明:传参时候,必须用{}包裹propsData,而且还要在扩展里面添加props:["info"],而且数组里面的元素要是字符串
computedOption
在渲染信息之前,进行的相关计算
<body>
<div id="app">
{{info}}
<br>
<ul>
<li v-for="li in newlis">{{li.title}}---{{li.age}}</li>
</ul>
</div>
</body>
</html>
<script>
var lis=[
{title:"曾强",age:20},
{title:"皇冠",age:21},
{title:"鹏飞",age:22},
{title:"鱼尾",age:23}
]
var app=new Vue({
el:"#app",
data:{
info:100,
lis:lis
},
computed:{
newinfo:function(){
return this.info=this.info+"美元";
},
newlis:function(){
return this.lis.reverse();
}
}
})
</script>
MethodsOption
<body>
<div id="app">
{{info}}
<br>
<button @click="add(2,$event)">添加</button>
<br>
<btn @click.native="add(3)"></btn>
</div>
<!-- 外部调用构造器的方法 -->
<button onclick="app.add(10)">添加</button>
</body>
</html>
<script>
var btn={
template:`<button>添加组件</button>`
}
var app=new Vue({
el:"#app",
data:{
info:1
},
components:{
"btn":btn
},
methods:{
add:function(num){
this.info=this.info+num;
}
}
})
</script>
说明:切记 components中key是字符串,如果在组件中使用构造器中的方法,需要添加native,构造器对应标签的外部使用构造器方法需要加上构造器对象的变量名称。另外$event包含点击事件相关信息,比如点击位置等,一般用于精确控制,普通场景不需要。
watchOption
用于监测某个数据,从而动态更新根据这个数据而变化的数据的内容
<body>
<div id="app">
{{msg}}--{{num}}
<br>
<button @click="add">加温</button><br>
<button @click="delet">减温</button><br>
</div>
</body>
</html>
<script>
var lis=["冷","普通","热"];
var app=new Vue({
el:"#app",
data:{
num:0,
msg:lis[0]
},
methods:{
add:function(){
this.num++;
},
delet:function(){
this.num--;
}
},
watch:{
num:function(newValue,oldValue){
if(newValue>=10){
this.msg=lis[0];
}else if(newValue>5&&newValue<10){
this.msg=lis[1];
}else{
this.msg=lis[2];
}
}
}
})
</script>
mixinsOption
混入 在构造器稳定的情况下,加入一些临时需求时候使用
<body>
<div id="app">
{{num}}
<br>
<button @click="add">加温</button><br>
</div>
</body>
</html>
<script>
Vue.mixin({
updated:function(){
console.log("全局混入");
}
});
var addLog={
updated:function(){
console.log("内部混入");
}
}
var app=new Vue({
el:"#app",
data:{
num:0,
},
methods:{
add:function(){
this.num++;
}
},
mixins:[addLog],
updated:function(){
console.log("内部生命周期");
}
})
</script>
输出:
全局混入
内部混入
内部生命周期
说明:混入分为内部混入和全局混入,先执行全局混入对应的生命周期,然后才是内部混入的生命周期,最后才是构造器内部的生命周期函数。注意mixins(混入选项)是数组,可以是多个,后面的扩展选项只能是一个,要区分开。
extendsOption
<body>
<div id="app">
{{num}}
<br>
<button @click="add">加温</button><br>
</div>
</body>
</html>
<script>
var extendObj={
updated:function(){
console.log("扩展生命周期");
},
add:function(){
console.log("扩展方法")
this.num++;
}
}
var app=new Vue({
el:"#app",
data:{
num:0,
},
methods:{
add:function(){
console.log("原生方法");
this.num++;
}
},
extends:extendObj,
updated:function(){
console.log("内部生命周期");
}
})
</script>
输出:
原生方法
扩展生命周期
内部生命周期
说明:注意扩展只是一个对象,不是数组,extends:extendObj,另外,当扩展和原生方法同名的时候,只执行原生方法,例如此时的add方法,另外扩展的生命周期执行先于内部生命周期。
替换插入符号
在一些例如织梦系统里面可能是Vue自带的{{}}插入符号冲突,可以通过delimiters自定义插入符号.
<body>
<div id="app">
${num}
</div>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
data:{
num:0,
},
delimiters:["${","}"]
})
</script>
说明:此时只能通过${}来插入数据,之前的{{}}无效了.
第四节(实例和内置组件)
实例,就是在构造器外面可以调用构造器内部的方法,给其他框架提供一个和vue一起使用的接口
rumen
<body>
<div id="app">
{{num}}
<br>
<button @click="add">增加</button>
</div>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
data:{
num:0,
},
methods:{
add:function(){
this.num++;
}
},
mounted:function(){
$("#app").html("Hello Jquery!");
}
});
app.add();
</script>
说明:jquery只有在mounted和updated之中才能使用,因为一个是dom挂载一个是dom更新。另外可以通过构造器名称.方法名直接在外部调用构造器内部的方法。
exampleMethod
<body>
<div id="app">
{{num}}
</div>
<button onclick="add()">增加</button>
<button onclick="des()">销毁</button>
<button onclick="tick()">更改数据</button>
<button onclick="upda()">重新加载数据</button>
</body>
</html>
<script>
var info = Vue.extend({
template: `<p>{{msg}}</p>`,
data: function () {
return {
msg: 1
}
},
mounted:function(){
//在挂载时候执行
console.log("被挂载");
},
updated:function(){
console.log("被更新");
},
destroyed:function(){
console.log("被销毁")
},
});
var vm = new info().$mount("#app");
//会执行updated
function add() {
vm.msg++;
}
//会执行destroyed
function des() {
vm.$destroy();
}
//重新加载数据,还是会调用updated钩子函数
function upda(){
vm.$forceUpdate();
}
//updated和内部的nextTick的回调都执行
function tick(){
vm.msg=10;
vm.$nextTick(function(){
console.log("msg更新完毕之后调用");
})
}
</script>
exampleEvent(实例事件)
在实例外部创建一个构造器的事件,好处是可以在外部调用构造器的数据和方法等。
基本案例:
<body>
<div id="app">
{{num}}
<br>
</div>
<button onclick="addc()">加</button>
<button onclick="offc()">关闭事件</button>
<button onclick="oncec()">加一次</button>
</body>
</html>
<script>
var app=new Vue({
el:"#app",
data:{
num:1
}
});
app.$once("once",function(){
console.log("只执行一次");
this.num++;
});
app.$on("add",function(){
this.num++;
})
function addc(){
app.$emit("add");
}
function offc(){
app.$off("add");
}
function oncec(){
app.$emit("once");
}
</script>
说明:button的点击事件按照js正常写法,构造器对象通过on绑定方法名,通过once绑定只执行一次的方法,但是button是我无法直接调用构造器的方法的,通过emit触发。关闭事件的时候,不使用on,而是直接off传入对应的方法名即可。
slot
slot是标签内容扩展,使用slot可以在自定义组件传递给组件内容,组件接受内容并输出。
<body>
<div id="app">
<zengqiang><span slot="info">{{info}}</span></zengqiang>
</div>
</body>
<template id="tm">
<div>
<a><slot name="info"></slot></a>
</div>
</template>
</html>
<script>
var el={
template:"#tm"
}
var app=new Vue({
el:"#app",
data:{
info:"数据信息"
},
components:{
"zengqiang":el
}
});
</script>
说明:组件传递数据的流程:首先,定义组件的地方,使用通过<slot>标签的name属性,关联构造器里面的data中的info,在使用组件的时候,<zengqiang>中通过slot属性关联<slot>标签中的name属性,从而渲染数据。注意,这种定义组件方式,<template>内部 第一层要加一个div,否则报错。