1.表单修饰符
- .lazy(限制实时传入服务器) 失去焦点之后才能更新
- .number(限制输入的为数字)
- .trim(去掉首尾字符是空格)
<body>
<div id="box">
<input type="text" v-model.lazy='mytext'>
{{mytext}}
<!-- <input type="text" v-model.number='mynumber'> -->
<input type="number" v-model='mynumber'>
{{mynumber}}
<input type="text" v-model.trim='myusername'>
|{{myusername}}|
</div>
<script>
new Vue({
el:"#box",
data:{
mytext:'',
mynumber:0,
myusername:''
}
})
</script>
</body>
2.axios与fetch实现数据请求
(1)fetch
why:
XMLHttpRequest是一个设计粗糙的API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好。
兼容性不好
polyfill:
https://github.com/camsong/fetch-ie8
<body>
<div id="box">
<button @click='handleClick()'>获取影片信息</button>
<ul>
<li v-for='data in dataList'>
<h3>{{data.name}}</h3>
<img :src="data.poster" alt="">
</li>
</ul>
</div>
<script>
new Vue({
el:"#box",
data:{
dataList:[]
},
methods:{
handleClick(){
fetch('./json/test.json').then(res=>res.json()).then(res=>{
console.log(res.data.films)
this.dataList=res.data.films
})
}
}
})
</script>
</body>
注意:fetch请求默认是不带cookie的,需要设置fetch(url,{credentials:‘include’})
(2) axios(第三方库)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="../js/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box">
<button @click='handleClick()'>正在热映</button>
<ul>
<li v-for='data in dataList'>
<h3>{{data.name}}</h3>
<img :src="data.poster" alt="">
</li>
</ul>
</div>
<script>
new Vue({
el:"#box",
data:{
dataList:[]
},
methods:{
handleClick(){
axios.get('./json/test.json').then(res=>{
console.log(res.data.data.films) //axios 自动包装data属性 res.data
this.dataList=res.data.data.films
}).catch(err=>{
console.log(err)
})
}
}
})
</script>
</body>
</html>
3.计算属性
- 计算属性,定义在computed里面,定义起来像函数一样,使用起来像属性一样
- 计算属性要比普通方法的性能要高
- 多次调用时,方法都会重新执行一遍,计算属性只计算一遍,会缓存,使用缓存
<body>
<div id="box">
<!-- {{myname.substring(0,1).toUpperCase() + myname.substring(1)}} -->
<p>计算属性:{{getMyName}}</p>
<p>普通方法:{{getMyNameMethod()}}</p>
<br>
<div>
<p>计算属性:{{getMyName}}</p>
<p>普通方法:{{getMyNameMethod()}}</p>
</div>
</div>
<script>
new Vue({
el:"#box",
data:{
myname:'xiaoming'
},
methods:{
getMyNameMethod(){
console.log("getMyNameMethod-方法调用")
return this.myname.substring(0,1).toUpperCase() + this.myname.substring(1)
}
},
computed:{
getMyName(){
console.log("getMyName-计算属性调用")
return this.myname.substring(0,1).toUpperCase() + this.myname.substring(1)
} //依赖的状态改变了,计算属性会重新计算一遍
}
})
</script>
</body>
计算属性模糊查询
<body>
<div id="box">
<input type="text" v-model="mytext">
<ul>
<li v-for='data in getMyDataList'>
{{data}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
mytext:"",
dataList:['aaa','abb','bbb','ccc','cdd','ddd','dee'],
},
computed:{
getMyDataList(){
return this.dataList.filter(item=>item.indexOf(this.mytext)>-1)
}
}
})
</script>
</body>
4.虚拟dom与diff算法
- 同层级对比
- 同key值对比
- 同组件对比
5.组件化开发
扩展HTML元素,封装可重用的代码
- 全局定义组件(作用域隔离),不能访问new Vue里面的方法和属性
- 在哪个组件的模板之中,就是谁的孩子
- navbar是根组件的孩子,child是navbar的孩子
sidebar是根组件的孩子,child是sidebar的孩子 - 全局定义的孩子,谁都可以访问
<body>
<div id="box">
<navbar></navbar>
<sidebar></sidebar>
</div>
<script>
Vue.component('navbar',{
template:`
<div>
<button @click="handleback()">返回</button>
navbar
<button>主页</button>
<child></child>
<navbarchild></navbarchild>
</div>`,
methods:{
handleback(){
console.log('back');
}
},
// 局部组件定义
components:{
navbarchild:{
template:`<div>navbar-child-只能在navbar组件中使用</div>`
}
}
})
Vue.component('child',{
template:'<div>child组件-全局定义</div>'
})
Vue.component('sidebar',{
template:`
<div>
sidebar组件
<child></child>
</div>`
})
new Vue({
el:"#box",
})//根组件 root component
</script>
</body>
组件的编写方式与Vue实例的区别
- 自定义组件需要有一个root element,不一定是div标签
- 父子组件的data是无法共享
- 组件可以有data,methods,computed…但是data必须是一个函数
6.组件通信
- 父子组件传值(props down,events up)
- 属性验证
props:{name:Number}
Number,String,Boolean,Array,Object,Function,null(不限制类型) - 事件机制
a.使用$.on(eventName)监听事件
b.使用$emit(eventName)触发事件
-
ref
<innput ref='mytext'> this.$refs.mytext
-
事件总线
var bus=new Vue();
*mounted生命周期种进行监听
(1)父传子
<body>
<div id="box">
<navbar myname='home' :myshow='false'></navbar>
<navbar myname='list' :myshow='true'></navbar>
<navbar :myname='parentname' :myshow='true'></navbar>
</div>
<script>
Vue.component('navbar',{
template:`
<div>
<button>返回</button>
navbar--{{myname}}
<button v-show='myshow'>首页</button>
</div>`,
// props:['myname','myshow'] //接受父组件传来的属性
// 属性验证
props:{
myname:String,
myshow:Boolean
}
})
new Vue({
el:"#box",
data:{
parentname:"父组件的状态"
}
})
</script>
</body>
(2)子传父
<body>
<div id="box">
父组件
<child @myevent='handleEvent($event)'></child>
</div>
<script>
// 子组件
Vue.component('child',{
template:`<div>
child组件
<button @click='payMoney()'>click</button>
</div>`,
data(){
return{
childname:'子组件的状态'
}
},
methods:{
payMoney(){
this.$emit('myevent',this.childname) //分发事件
}
}
})
new Vue({
el:"#box",
methods:{
handleEvent(ev){
console.log("父组件收到钱了",ev)
}
}
})
</script>
</body>
子传父案例
<body>
<div id="box">
<!-- <button @click='isShow=!isShow'>click</button> -->
<navbar @myevent='handleEvent'></navbar>
<sidebar v-show='isShow'></sidebar>
</div>
<script>
Vue.component('navbar',{
template:`<div>
navbar
<button @click='handleClick'>navbar-button</button>
</div>`,
methods:{
handleClick(){
this.$emit("myevent");
}
}
}),
Vue.component('sidebar',{
template:`<div style='background:yellow;width:200px;'>
<ul>
<li>1111</li>
<li>1111</li>
<li>1111</li>
</ul>
</div>`
})
new Vue({
el:"#box",
data:{
isShow:false
},
methods:{
handleEvent(){
this.isShow=!this.isShow;
}
}
})
</script>
</body>
(3)ref通信
- ref放在标签上,拿到的是原生节点
- ref放在组件上,拿到的是组件对象
ref可以绑多个
<body>
<div id="box">
<input type="text" ref='mytext'>
<button @click='handleAdd'>add</button>
<child ref='mychild'></child>
</div>
<script>
// 子组件
Vue.component("child",{
template:`<div>
child
</div>`,
data(){
return {
childname:"子组件的状态"
}
},
methods:{
add(data){
console.log("子组件的方法",data)
}
}
})
var vm = new Vue({
el:"#box",
data:{
},
methods:{
handleAdd(){
console.log("1111",this.$refs.mychild.childname);
this.$refs.mychild.add('孩子听话')
}
}
})
</script>
</body>
(4)非父子通信-事件总线
<body>
<div id="box">
<weixinauthor></weixinauthor>
<weixinuser></weixinuser>
</div>
<script>
var bus=new Vue(); //空vue实例 就是中央事件总线
Vue.component("weixinauthor",{
template:`<div style='background:blue'>
我是微信公众号作者
<input type='text' ref='mytext'>
<button @click='handleClick()'>发布</button>
</div>`,
methods:{
handleClick(){
bus.$emit('weixinmessage',this.$refs.mytext.value)
}
}
})
Vue.component('weixinuser',{
// 合适的位置先订阅好 bus.$on
template:`<div style='background:yellow'>
我是一个微信用户
</div>`,
mounted(){
bus.$on("weixinmessage",(data)=>{
console.log('收到推送了',data)
})
console.log("生命周期函数-当前组件的dom创建完成之后就会调用")
}
})
new Vue({
el:"#box",
})
</script>
</body>
(5)动态组件
<component>元素,动态地绑定多个组件到它的is属性
<keep-alive>保留状态,避免重新渲染
<body>
<div id="box">
<keep-alive>
<component :is='who'></component>
</keep-alive>
<footer>
<ul>
<li><a @click="who='home'">首页</a></li>
<li><a @click="who='list'">列表页</a></li>
<li><a @click="who='shopcar'">购物车页面</a></li>
</ul>
</footer>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
who:'home'
},
components:{
'home':{
template:`<div>home<input type='text'></div>`
},
'list':{
template:`<div>list</div>`,
},
'shopcar':{
template:`<div>shopcar</div>`,
}
}
})
</script>
</body>