最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue学习笔记之组件篇

    正文概述 掘金(isisxu)   2021-02-01   399

    1. vue组件生命周期图

    vue学习笔记之组件篇

    2. 组件生命周期函数

    • 刚初始化了一个空的实例对象, 这时候只有默认的一些生命周期函数和默认事件, 其他都未创建。
    • 如果要调用 methods 中的方法, 或者操作 data 中的数据, 最早只能在 created 生命周期函数中操作
    // 1. 实例创建阶段
    new Vue({
        el: "#app",
        // 在beforeCreate中,data和methods中的数据都还没有初始化
        beforeCreate () {}, 	// 表示实例完全被创建之前, 会执行这个函数
        // 在created中,data和methods中的数据都已经初始化好了
        created () {} 				// 表示实例被创建之后, 会执行这个函数
      
    })
    
    // 承接备注:查看Vue生命周期图例, 这里表示Vue开始编译模板, 把Vue代码中的那些指令进行执行, 最终在内存中生成一个编译好的最终模板字符串, 然后把这个字符串渲染为内存中的DOM,此时, 只是在内存中渲染好了模板, 并没有把模板挂载到真正的页面中。
    
    
    // 2. 运行期间:组件挂载和更新
    
    new Vue({
        el: "#app",
        // 在beforeMounted执行时,页面中的元素还没有被真正的替换过来,只是之前写的一些模板字符串
        beforeMounted () {}, 	// 组件挂载之前 表示模板已经编译完成,但是还没有把模板渲染到页面中
        
        // 表示模板已经编译完成,内存中的模板已经真实的渲染到了页面中去,已经可以看到渲染好的页面了
        // 注意: mounted是实例创建期间的最后一个生命周期函数,当执行完mounted生命周期函数就表示,
        // 实例已经被完全创建好了,此时如果没有其他操作的话,这个实例就在内存中一动不动
        // 注意: 如果要通过某些插件操作页面上的DOM节点,最早要在mounted生命周期中操作
        mounted () {} 				// 组件挂载完成后
        
        // 上面的是组件的创建阶段,接下来进入组件的运行阶段
        // 在这个生命周期函数执行的时候,页面中显示的数据还是旧的,但是data中的数据是最新的,
        // 页面尚未和最新的数据保持同步
        beforeUpdate () {} 		// 表示当前界面还没有被更新,数据肯定被更新了
        // 查看Vue生命周期图例,这里表示先根据data中最新的数据在内存中重新渲染出一份最新的内存DOM树当最新的
        // 内存DOM树更新之后会把最新的内存DOM树重新渲染到真实的页面中去这时候就完成了数据从data(model层)
        // 到view(视图层)的更新
        updated () {} 				// 表示当前页面和数据保持同步了,都是最新的
    })
    
    // 3. 组件销毁阶段
    new Vue({
        el: "#app",
      	// 在这个生命周期函数执行的时候.实例身上所有的data和methods以及过滤器、指令等等都是可用状态,还没有真正的执行销毁的过程
        beforeDestroy () {}, 	// 表示组件即将被销毁之前,此时Vue实例以及数据指令等还是可以使用
      	// 在这个生命周期函执行的时候,组件中的data和methods以及过滤器、指令等等都已经不可用了
        destroyed(){} 				// 表示组件已经完全被销毁了,此时组件数据等已不可用
    })
    

    生命周期函数补充:activated和deactivated函数,这两个生命周期函数是在组件实例被保持了状态使用了keep-alive时,才有效的。当被kepp-alive包裹渲染时,切换路由组件时,档切换到被包裹的组件时,被包裹的组件则处处于活跃状态调用activated,切换到其他组件时,该包裹的组件则处于活跃状态调用deactivated函数。

    3. 全局组件和局部组件

    3.1 全局组件

    • 全局组件new Vue构造函数外定义的就是全局组件,可以在其他的vue实例中都可以使用。

    • 注意点:在使用Vue.component定义全局组件的时候,组件名称使用驼峰命名,则在引用组件的时候,需要把大写的驼峰改为小写的字母,同时两个单词之间使用 - 连接

    <!---->
    <body>
      <!-- 只要是vue实例的el指定的范围内都可以访问-->
      <div id="app">
        <button-counter></button-counter>
      </div>
      <div id="ppa">
        <button-counter></button-counter>
      </div>
      <!-- 这里不可以访问,因为component创建的组件必须在vue实例el指定的元素范围内使用才可以 -->
      <!-- 这里将Vue.component命名的组件 buttonCounter,在引用的时候需要写成 button-counter;最好都采用小写-连接 -->
      <button-counter></button-counter>
      <script>
        Vue.component("buttonCounter", {
          data: () => {
            return {
              count: 0,
            };
          },
          template:
          '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
        });
        var vm1 = new Vue({
          el: "#app",
        });
        var vm2 = new Vue({
          el: "#ppa",
        });
      </script>
    </body>
    

    3.2 局部组件

    • 局部组件:在构造函数里面直接挂载在vue实例的components属性上;components是个对象,可以接受一组自定义的局部组件
    <body>
      <div id="app">
        <local-counter></local-counter>
      </div>
      <!-- 因为local-counter是局部组件,只能在vm1实例的el范围内使用 -->
      <div id="ppa">
        <local-counter></local-counter>
      </div>
      <script>
        // local-counter是自定义局部组件名,对应一个对象是其构造选项
        var vm1 = new Vue({
          el: "#app",
          components: {
            "local-counter": {
              template:
              '<button v-on:click="count++">You clicked me {{ count }} times.</button>',
              data: function () {
                return {
                  count: 0,
                };
              },
            },
          },
        });
        var vm2 = new Vue({
          el: "#ppa",
        });
      </script>
    </body>
    

    4. 父子组件

    • 父子组件关系的本质:只要一个组件在另一个组件的template中或者是实例的el绑定标签中。
    <!-- 父子组件关系一: -->
    <body>
        <!-- div#app是父组件的模板 -->
        <div id="app">
            <cpn></cpn>
        </div>
        <script>
            // cpn的template是子组件cpn的模板,渲染的时候cpn组件会被整个cpn的template模板内容替换
            Vue.component('cpn', {
                template: `
                    <div>
                        <h1>我是子组件</h1>
                    </div>
                `,
            })
            var vm = new Vue({
                el: '#app',
                data() {
                    return {
                        messageInfo: '我是父组件的message'
                    }
                }
            })
        </script>
    </body>
    
    <!-- 父子孙的组件关系二: -->
    
    <div id="app">
      <cpn1></cpn1>
    </div>
    
    <script>
      // 在vm实例的el绑定的div模板中使用cpn1组件,在cpn1组件的模板中使用cpn2组件
      Vue.component('cpn1', {
        template: `<div>
    									<h1>我是cpn1标题1</h1>
    									<cpn2></cpn2>
      						</div>`,
      })
    
      Vue.component('cpn2', {
        template: `<div>
    									<h1>我是cpn2标题2</h1>
      							</div>`,
      })
      var vm = new Vue({
        el: '#app',
      })
    </script>
    
    // 
    <div id="app">
      <cpn1></cpn1>
    </div>
    <script>
      var cpnConstructor = Vue.extend({
        template: `<h2>我是cpn2标题2</h2>`
      })
    
      // var cpn2 = {
      //     template: `<h2>我是cpn2标题2</h2>`
      // };
      Vue.component('cpn1', {
        template: `<div>
                    <h1>我是cpn1标题1</h1>
                    <cpn2></cpn2>
      					</div>`,
        components: {
          cpn2: cpnConstructor // 这里可以放extend的构造器或者直接放cpn2定义的选项对象
        }
      })
    
      var vm = new Vue({
        el: '#app',
      })
    </script>
    

    5. 父子组件通信

    • 背景:子组件虽然在父组件的模板中嵌套,但是子组件不能访问父组件data的数据,父组件也不能访问子组件的data数据;所以父子之间交互数据需要通信了。
    • 最常见的应用就是:组件 A 在它的模板中使用了组件 B。它们之间必然需要相互通信:父组件可能要给子组件下发数据,子组件则可能要将它内部发生的事情告知父组件。
    • 注意
    1. Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,因为对于传递的引用类型的值,也就是说prop接受到的是对象或者数组,那么父子组件指向的同一块内存,子组件内部修改会影响父组件。
    2. 子组件如果需要修改prop,则可以在子组件内部进行一份prop的拷贝
    

    5.1 父组件向子组件传递

    • 父组件向子组件传递方式:通过props属性 和 vm.$attrs属性
    • 命名总结:HTML 特性是不区分大小写的。所以,当使用的不是字符串模板时,camelCase (驼峰式命名) 的 prop 需要转换为相对应的 xxx-ccc (短横线分隔式命名);在js中使用驼峰式,html中使用短横线
    // 示例1:静态使用props,静态传值vue,注意属性时分隔符不能驼峰式
    <div id="app">
      <cpn1 my-message="vue"></cpn1>
    </div>
    <script>
      Vue.component('cpn1', {
        // 声明props
        props: ['myMessage'],
        // 就像data一样,props里面的数据也可以在模板中使用,
        // 同样也可以在vm实例中通过 this.myMessage 来使用
        template: '<h1>hello {{myMessage}}</h1>',
    
      })
      var vm = new Vue({
        el: '#app',
      })
    </script>
    
    // hello vue
    
    // 动态props父组件传递数据到子组件
    
    <body>
        <div id="app">
            <!-- myCpn自定义组件写成my-cpn  cpnList是子组件props中声明的属性写成cpn-list,接受父组件传递的属性-->
          	<!-- v-bind:cpn-list="list" 简写 :cpn-list="list" -->
          	<!-- cpn-list是子组件props中定义的属性cpnList,用于接收父组件传递来的list -->
            <my-cpn :cpn-list="list" :cpn-pers-info="persInfo"></my-cpn>
        </div>
        <script>
            Vue.component('myCpn', {
                // 在子组件的模板中使用子组件props中的属性
                template: `<div>
                            <h1>我是子组件myCpn</h1>
                            <h1>接收到的数据:{{cpnList}}</h1>
                            <h1>接收到的数据:{{cpnPersInfo}}</h1>
                        </div>`,
                props: ['cpnList', 'cpnPersInfo']
            });
            var vm = new Vue({
                el: "#app",
                data() {
                    return {
                        list: ['数码', '家电', '旅行'],
                        persInfo: {
                            name: 'Bob',
                            age: 20
                        },
                    }
                }
            });
        </script>
    </body>
    

    5.2 子组件向父组件传递

    • 子组件向父组件传递数据是通过自定义事件
    <body>
      	<!-- 子组件模板 -->
        <template id="son">
            <div>
              	<!-- 1. 子组件通过点击事件触发事件函数 -->
                <button v-for="item of categories" @click="btnClick(item)">{{item.name}}</button>
            </div>
        </template>
      
      	<!-- 父组件模板 -->
        <div id="app">
          	<!-- 3. 父组件通过监听子组件的自定义事件item-click进行处理,注意自定义的事件的函数没有event对象,但是这里默认会将子组件的数据item带过去 -->
            <cpn-button @item-click="cpnClick"></cpn-button>
        </div>
      
        <script>
          	// 子组件
            Vue.component('cpnButton', {
                data() {
                    return {
                        categories: [
                            { id: '1', name: '家电' },
                            { id: '2', name: '科技' },
                            { id: '3', name: '户外' },
                        ],
                    }
                },
                template: '#son',
                methods: {
                    btnClick(item) {
                     		// 2. 子组件将点击获取到的数据通过 this.$emit(自定义事件名,传递给父组件的数据)发射自定义事件;自定义事件名要小写短横线连接
                        this.$emit('item-click', item)
                    }
                }
            })
    
          	// 父组件实例
            new Vue({
                el: '#app',
                methods: {
                  	// 4. 父组件监听的自定义事件函数接收到子组件传递来的item数据 
                    cpnClick(item) {
                        console.log("---", item)
                    }
                }
            })
        </script>
    </body>
    

    6. 父子组件的访问

    6.1 父访问子

    • 两种访问方式:通过children或者children或者children或者refs
    1. this.$children:是一个包含所有子组件对象的数组
    2. this.$refs:默认是`{}`,当在子组件上绑定ref属性时,this.$refs的结构就变成
    `{ 绑定的ref属性: 对应的子组件 }`
    
    <!-- this.$children示例 -->
    <body>
      <div id="app">
          <cpn></cpn>
          <button @click="btn">按钮</button>
      </div>
      <template id="cpn">
          <div>
              <h1>{{message}}</h1>
          </div>
      </template>
      <script>
          var vm = new Vue({
              el: "#app",
              data: {
                  message: "我是父组件app",
              },
              methods: {
                  btn() {
                      console.log(this.$children[0].message)
                      this.$children[0].show();
                  }
              },
              components: {
                  cpn: {
                      template: '#cpn',
                      data() {
                          return {
                              message: "我是子组件cpn",
                          }
                      },
                      methods: {
                          show() {
                              console.log(this.message);
                          }
                      }
    
                  }
              }
          });
      </script>
    </body>
    
    <!-- this.$refs示例: -->
    <body>
        <div id="app">
            <cpn ref="cpnA"></cpn>
            <cpn ref="cpnB"></cpn>
            <button @click="showSon">按钮</button>
        </div>
        <template id="cpn">
            <div>
                <h1>{{message}}</h1>
            </div>
        </template>
        <script>
            var vm = new Vue({
                el: "#app",
                data() {
                    return {}
                },
                methods: {
                    showSon() {
                        console.log(this.$refs)
                        console.log(this.$refs.cpnA)
                        console.log(this.$refs.cpnB)
                    }
                },
                components: {
                    cpn: {
                        template: '#cpn',
                        data() {
                            return {
                                message: "我是子组件cpn",
                            }
                        },
                        methods: {
                            show() {
                                console.log(this.message);
                            }
                        }
    
                    }
                }
            });
        </script>
    </body>
    

    6.2 子访问父

    • this.$parent:可以访问到父组件,但是不提倡这样做,这样会破坏子组件的复用性,比如在子组件中修改父组件A的name属性,但是其他B的组件引用这个子组件,B组件中并没有name属性;会导致没有解耦
    • this.$root: 会直接访问到根实例

    7 动态组件

    • ***动态组件定义:通过使用vue内置的<component>元素,并对其使用is特性进行动态绑定,你可以在同一个挂载点动态切换多个组件
    • 使用vue内置的<component>元素 + 绑定特殊属性is进而完成动态组件
    <!-- 基本使用 -->
    <!-- 解析:当用户点击home按钮则在下方的component位置渲染出home组件,点击posts按钮会在下方渲染出posts组件 -->
    <body>
        <div id='app'>
            <div>
                <!-- 注意 currentTab = tab是内联js语句,执行后currentTab发生变化触发currentTabComponent -->
                <button v-for="tab in tabs" @click="currentTab = tab">
                    {{ tab }}
                </button>
                <!-- component为vue的内置组件和特殊属性is搭配起来表示
                    根据currentTabComponent的变化进而渲染成不同的组件,被渲染出的组件会完全替换内置的component组件
                -->
                <component :is="currentTabComponent"></component>
            </div>
        </div>
    
        <script>
            Vue.component("home", {
                template: "<div>Home component</div>"
            });
            Vue.component("posts", {
                template: "<div>Posts component</div>"
            });
            new Vue({
                el: "#app",
                data: {
                    currentTab: "Home",
                    tabs: ["Home", "Posts"]
                },
                computed: {
                    currentTabComponent: function () {
                        return this.currentTab.toLowerCase();
                    }
                }
            });
        </script>
    </body>
    

    当在这些组件之间切换的时候,你有时会想保持之前这些组件的状态,以避免反复重渲染导致的性能问题。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。

    <!-- 失活的组件将会被缓存,下次渲染就不会重新创建组件实例,并且组件之前的状态也会被缓存记录!-->
    <keep-alive>
      <component v-bind:is="currentTabComponent"></component>
    </keep-alive>
    

    8 异步组件

    segmentfault.com/a/119000002…


    起源地下载网 » vue学习笔记之组件篇

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元