Vue组件

fetch和axios

  axios与fetch实现数据请求

    fetch(不是所有浏览器都支持,谷歌浏览器支持),XMLHttpRequest 是一个设计粗糙的 API,配置和调用方式非常混乱,而且基于事件的异步模型写起来不友好。 兼容性不好

  polyfill: https://github.com/camsong/fetch-ie8

  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/nowPlaying
                fetch("./json/test.json").then(res => res.json()).then(res => {
                    console.log(res.data.films)
                    this.datalist = res.data.films
                })
            }
        }
    })

    /*
     // post-1
      fetch("**",{
          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-2
      fetch("**",{
          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>

  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.data
                    this.datalist = res.data.data.films
                }).catch(err=>{
                    console.log(err);
                })
            }
          }
      })
    </script>
</body>
</html>

Mixins

  混入 (mixins) 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

虚拟dom与diff算法 key的作用

  1、Vue2.0 v-for 中 :key 有什么用呢?

其实呢不只是vue,react中在执行列表渲染时也会要求给每个组件添加key这个属性。
key简单点来说就是唯一标识,就像ID一样唯一性
要知道,vue和react都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面。而隐藏在背后的原理便是其高效的Diff算法。


只做同层级的对比
按照key值比较,出现新的key就插入
通组件对比

  2、虚拟DOM的diff算法

   具体实现

    把树按照层级分解

     同key值比较

     通组件对比

<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

组件开发基础

  什么是组件以及组件的作用

扩展 HTML 元素,封装可重用的代码,目的是复用
    -例如:有一个轮播,可以在很多页面中使用,一个轮播有js,css,html
    -组件把js,css,html放到一起,有逻辑,有样式,有html

组件注册方式

1 全局组件
    Vue.component
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></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>

  定义局部组件

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>`,
            }

        }
})

组件编写方式与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'
        }
    },
})

组件通信

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.mytext
5 事件总线var bus = new Vue();* mounted生命周期中进行监听

  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>

  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>

  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>

  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>

  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>

动态组件

 <component> 元素,动态地绑定多个组件到它的 is 属性
2 <keep-alive> 保留状态,避免重新渲染

  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>

  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>

 

posted @ 2022-04-14 14:49  那就凑个整吧  阅读(81)  评论(0编辑  收藏  举报