
组件
1 fetch和axios
axios与fetch实现数据请求
(1)fetch(不是所有浏览器都支持,谷歌浏览器支持)
XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好。 兼容性不好
polyfill: https://github.com/camsong/fetch-ie8
1.1 fetche使用
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>fetch</title><script src="js/vue.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"/></li></ul></div><script type="text/javascript">new Vue({el: "#box",data: {datalist: []},methods: {handleClick() {//https://m.maizuo.com/v5/?co=mzmovie#/films/nowPlayingfetch("./json/test.json").then(res => res.json()).then(res => {console.log(res.data.films)this.datalist = res.data.films})}}})/*// post-1fetch("**",{method:'post',headers: {"Content‐Type": "application/x‐www‐form‐urlencoded"},body: "name=kerwin&age=100",credentials:"include"}).then(res=>res.json()).then(res=>{console.log(res)});// post-2fetch("**",{method:'post',headers: {"Content‐Type": "application/json"},body: JSON.stringify({myname:"kerwin",myage:100})}).then(res=>res.json()).then(res=>{console.log(res)});*/</script></body></html>
1.2 axios的使用
<!DOCTYPE html><html><head><meta charset="utf-8"><title>axios</title><script type="text/javascript" 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"/></li></ul></div><script type="text/javascript">new Vue({el:"#box",data:{datalist:[]},methods:{handleClick(){axios.get("./json/test.json").then(res=>{console.log(res.data.data.films) // axios 自动包装data属性 res.datathis.datalist = res.data.data.films}).catch(err=>{console.log(err);})}}})</script></body></html>
2 计算属性
复杂逻辑,模板难以维护(1) 基础例子(2) 计算缓存 VS methods-计算属性是基于它们的依赖进行缓存的。-计算属性只有在它的相关依赖发生改变时才会重新求值(3) 计算属性 VS watch- v-model3
2.1 通过计算属性实现名字首字母大写
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><!--大段的代码写在这里不好,使用计算属性-->{{mytext.substring(0,1).toUpperCase()+mytext.substring(1)}}<p>计算属性:{{getname}}</p><!--普通方法要加括号--><p>普通方法:{{getNameMethod()}}</p><!--区别是在同一个页面中使用多次计算属性,不会多次执行--></div></body><script>var vm = new Vue({el: '#box',data: {mytext:'lqz',},computed:{getname(){//依赖的状态改变了,会重新计算console.log('计算属性')return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)}},methods:{getNameMethod(){console.log('普通方法')return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)}}})</script></html>
2.2 通过计算属性重写过滤案例
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><p><input type="text" v-model="mytext" @input="handleChange"></p><ul><li v-for="data in newlist">{{data}}</li></ul></div></body><script>var vm = new Vue({el: '#box',data: {mytext: '',datalist: ['aaa', 'abc', 'abcde', 'abcdef', 'bbb', 'bac'],},computed: {newlist() {var newlist = this.datalist.filter(item => {return item.indexOf(this.mytext) > -1})return newlist},},})</script></html>
4 虚拟dom与diff算法 key的作用
4.1 Vue2.0 v-for 中 :key 有什么用呢?
其实呢不只是vue,react中在执行列表渲染时也会要求给每个组件添加key这个属性。key简单点来说就是唯一标识,就像ID一样唯一性要知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。只做同层级的对比按照key值比较,出现新的key就插入通组件对比
4.2 虚拟DOM的diff算法
4.3 具体实现
4.3.1 把树按照层级分解
4.3.2 同key值比较
4.3.3 通组件对比

<div id="box"><div v-if="isShow">111</div><p v-else>222</p><!--{tag:div,value:111}{tag:p,value:222}直接不比较,直接删除div,新增p--><div v-if="isShow">111</div><div v-else>222</div><!--{tag:div,value:111}{tag:div,value:222}比较都是div,只替换文本内容--></div>
https://segmentfault.com/a/1190000020170310
5 组件化开发基础
5.1 组件是什么?有什么用
扩展 HTML 元素,封装可重用的代码,目的是复用-例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html-组件把js,css,html放到一起,有逻辑,有样式,有html
6 组件注册方式
1 全局组件Vue.component2 局部组件
6.1 定义全局组件,绑定事件,编写样式
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><navbar></navbar></div></body><script>//没有代码提示,语法检查,目前这么用//后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包Vue.component('navbar',{template:`<div><button @click="handleClick">返回</button>我是NavBar<button style="background: red">主页</button></div>`,methods:{handleClick(){console.log('nav nav')}}})var vm = new Vue({el: '#box',data: {},})</script></html>
6.2 定义局部组件
Vue.component('navbar', {template: `<div><button @click="handleClick">返回</button>我是NavBar<button style="background: red">主页</button><br><child></child></div>`,methods: {handleClick() {console.log('nav nav')},},components: {child: {template: `<button>儿子</button>`,}}})
7 组件编写方式与Vue实例的区别
1 自定义组件需要有一个root element,一般包裹在一个div中2 父子组件的data是无法共享3 组件可以有data,methods,computed....,但是data 必须是一个函数
Vue.component('navbar', {template: `<div><button @click="handleClick">返回</button>我是NavBar{{aa}}<button style="background: red">主页</button><br><child></child></div>`,methods: {handleClick() {console.log('nav nav')},},components: {child: {template: `<button>儿子</button>`,}},data(){return {aa:'lqz'}},})
8 组件通信
1 父子组件传值 (props down, events up)2 父传子之属性验证props:{name:Number}Number,String,Boolean,Array,Object,Function,null(不限制类型)3 事件机制a.使用 $on(eventName) 监听事件b.使用 $emit(eventName) 触发事件4 Ref<input ref="mytext"/> this.$refs.mytext5 事件总线var bus = new Vue();* mounted生命周期中进行监听
8.1 父子通信之父传子
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><!--保证属性名和props中的属性名和变量名一致即可--><navbar myname="lqz"></navbar><navbar myname="egon"></navbar><!--注意数据绑定--><navbar :myname="egon"></navbar><!--可以传多个,但是注意,传入的isshow是字符串,可以使用数据绑定变成布尔--><navbar :myname="egon" isshow="false"></navbar><navbar :myname="egon" :isshow="false"></navbar></div></body><script>//没有代码提示,语法检查,目前这么用//后面会使用webpack打包,直接定义成 xx.vue文件,通过webpack打包Vue.component('navbar', {template: `<div><button>返回</button>父组件传递的内容是:{{myname}}<button>主页</button><br></div>`,props:['myname']})var vm = new Vue({el: '#box',data: {},})</script></html>
属性验证
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><navbar myname="egon" :isshow="false"></navbar><!--报错--><navbar myname="egon" isshow="false"></navbar></div></body><script>Vue.component('navbar', {template: `<div><button>返回</button>父组件传递的内容是:{{myname}}传入的布尔是{{isshow}}<button>主页</button><br></div>`,// props:['myname'],props:{myname:String,isshow:Boolean,},})var vm = new Vue({el: '#box',data: {},})</script></html>
8.2 父子通信之子传父(通过事件)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box">子组件中监听自定义事件,随便起名<!-- <navbar @myevent="handleClick"></navbar>--><navbar @myevent="handleClick($event)"></navbar></div></body><script>Vue.component('navbar', {template: `<div><button>返回</button>组件<button @click="handleEvent">点击按钮把子组件数据传递到父组件</button><br></div>`,data(){return {name:'lqz'}},methods:{handleEvent(){// this.$emit('myevent') //myevent:子组件中监听自定义事件this.$emit('myevent',100) //100表示传递的参数}}})var vm = new Vue({el: '#box',data: {},methods:{handleClick(ev){console.log('点击子组件,我会执行')console.log(ev)}}})</script></html>
8.3 通过子传父控制字组件显示隐藏
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box">普通方式<button @click="isShow=!isShow">点击隐藏显示</button><navbar v-show="isShow"></navbar><hr>字传父方式<mybutton @myevent="handleShow"></mybutton><navbar v-show="isShow"></navbar></div></body><script>Vue.component('mybutton', {template: `<div><button @click="handleClick">点我隐藏显示</button></div>`,methods: {handleClick() {this.$emit('myevent')}}})Vue.component('navbar', {template: `<div><ul><li>111</li><li>222</li><li>333</li></ul></div>`,data() {return {name: 'lqz'}},methods: {handleEvent() {// this.$emit('myevent') //myevent:子组件中监听自定义事件this.$emit('myevent', 100) //100表示传递的参数}}})var vm = new Vue({el: '#box',data: {isShow: true},methods: {handleShow() {this.isShow=!this.isShow}}})</script></html>
8.4 ref属性
ref放在标签上,拿到的是原生节点ref放在组件上,拿到的是组件对象,通过这种方式实现子传父(this.$refs.mychild.text)通过这种方式实现父传子(调用子组件方法传参数)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><!-- 通过ref,获取input的值--><input type="text" ref="mytext"><button @click="handleClick">点我</button><child ref="mychild"></child></div></body><script>Vue.component('child',{template:`<div>child</div>`,data(){return {text:'子组件数据'}},methods:{add(){console.log('子组件的add方法')}}})var vm = new Vue({el: '#box',data: {},methods: {handleClick() {console.log(this)//this.$refs.mytext 获取到input控件,取出value值console.log(this.$refs.mytext.value)console.log(this.$refs.mychild.text)// this.$refs.mychild.add()this.$refs.mychild.add('传递参数')}}})</script></html>
8.5 事件总线(不同层级的不通组件通信)
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><child1></child1><child2></child2></div></body><script>var bus=new Vue() //new一个vue的实例,就是中央事件总线Vue.component('child1', {template: `<div><input type="text" ref="mytext"><button @click="handleClick">点我</button></div>`,methods:{handleClick(){bus.$emit('suibian',this.$refs.mytext.value) //发布消息,名字跟订阅消息名一致}}})Vue.component('child2', {template: `<div><div>收到的消息 {{msg}}</div></div>`,data(){return {msg:''}},mounted(){//生命周期,当前组件dom创建完后悔执行console.log('当前组件dom创建完后悔执行')//订阅消息bus.$on('suibian',(item)=>{console.log('收到了',item)this.msg=item})}})var vm = new Vue({el: '#box',data: {},methods: {handleClick() {console.log(this)//this.$refs.mytext 获取到input控件,取出value值console.log(this.$refs.mytext.value)console.log(this.$refs.mychild.text)// this.$refs.mychild.add()this.$refs.mychild.add('传递参数')}}})</script></html>
9 动态组件
1 <component> 元素,动态地绑定多个组件到它的 is 属性2 <keep-alive> 保留状态,避免重新渲染
9.1 基本使用
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><ul><li><a @click="who='child1'">首页</a></li><li><a @click="who='child2'">商品</a></li><li><a @click="who='child3'">购物车</a></li></ul><component :is="who"></component></div></body><script>var bus = new Vue() //new一个vue的实例,就是中央事件总线Vue.component('child1', {template: `<div>首页</div>`,})Vue.component('child2', {template: `<div>商品</div>`,})Vue.component('child3', {template: `<div>购物车</div>`,})var vm = new Vue({el: '#box',data: {who:'child1'},})</script></html>
9.2 keep-alive使用
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><script src="js/vue.js"></script></head><body><div id="box"><ul><li><a @click="who='child1'">首页</a></li><li><a @click="who='child2'">商品</a></li><li><a @click="who='child3'">购物车</a></li></ul><keep-alive><component :is="who"></component></keep-alive></div></body><script>var bus = new Vue() //new一个vue的实例,就是中央事件总线Vue.component('child1', {template: `<div>首页</div>`,})Vue.component('child2', {template: `<div>商品<input type="text"></div>`,})Vue.component('child3', {template: `<div>购物车</div>`,})var vm = new Vue({el: '#box',data: {who:'child1'},})</script></html>

