vue 基础 (二) 组件传值

组件间传值

1 父向子传值prop

<!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>
  </head>
  <body>
    <div id="app">
      <parentchild-value :msg="msgprop"></parentchild-value>      
    </div>
    <script>
      let parentchildvalue={
        props:["msg"],
        template:`<div>{{msg}}</div>`
      }
      let vue = new Vue({
        el: "#app",
        data:{
          msgprop:"父向子传值prop"
        },
        methods: {},
        components:{
          "parentchild-value":parentchildvalue
        }
      });
    </script>
  </body>
</html>

 

2 子向父传值 inject

<!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>
  </head>
  <body>
    <div id="app">
      <h1>子向父传值 inject</h1>
      <childparent-value></childparent-value>
      <div></div>
    </div>
    <script>
      let childparentvalue = {
        inject: ["provide"],
        template: `<div>{{provide}}</div>`,
      };
      let vue = new Vue({
        el: "#app",
        data: {
          value: "inject 传值",
        },
        methods: {},
        provide() {
          return {
            provide: this.value,
          };
        },
        components: {
          "childparent-value": childparentvalue,
        },
      });
    </script>
  </body>
</html>

 

3测试子获取root组件值和方法
<!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>
  </head>
  <body>
    <div id="app">
      <h1>3测试子获取root组件值和方法</h1>
      <child-root></child-root>
    </div>
    <script>

      let childRoot = {
        template: `<div><span>{{rootmsg}}</span><button @click="handle">调用root方法</button></div>`,
        data() {
          return {
            rootmsg: this.$root.rootmsg,
          };
        },
        methods: {
          handle: function () {
            this.$root.rootHandle();
          },
        },
      };

      let vue = new Vue({
        el: "#app",
        data: {
          rootmsg:"rootmsg"
        },
        methods: {
          rootHandle: function () {
            console.log(this.$root)
            alert("root方法调用");
          },
          showName:function(){
            alert("showname")
          },
          handle: function () {
            this.$root.showName();
            this.$root.rootHandle();
            console.log(this.$root)
          },
        },
        components: {
          "child-root": childRoot,
        },
      });
    </script>
  </body>
</html>

 

4测试子获取parent组件值的方法
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>4测试子获取parent组件值的方法</h1>
        <child-parent></child-parent>
    </div>
    <script>
     //4测试子获取parent组件值的方法
     var childParent = {
        template: `<div><span>{{parentmsg}}</span><button @click="handle">调用root方法</button></div>`,
        data() {
          return {
            parentmsg: this.$parent.parentmsg,
          };
        },
        methods: {
          handle: function () {
            this.$parent.rootHandle();
          },
        },
      };
      var vm = new Vue({
        el: "#app",
        data: {
          parentmsg:"parent"
        },
        methods: {
          rootHandle:function(){
            alert("parent 方法")
          }       
        },
        components:{
          "child-parent":childParent,         
        },
      });
    </script>
  </body>
</html>

5测试父调子值和方法
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>5测试父调子值和方法</h1>
        <span>测试父调子的值</span><span></span>
        <button @click="refHandle">测试调用子的方法</button>
        <child-refs ref="ref"></child-refs>
      </div>
    </div>
    <script>
       //5测试父调子值和方法
       var childRefs = {
        data() {
          return {
            refmsg: "我是refmsg",
          };
        },
        template: `<div>{{refmsg}}</div>`,
        methods: {
          refHandle: function () {
            alert(this.refmsg + "方法");
          },
        },
      };
      var vm = new Vue({
        el: "#app",
        data: {
     
        },
        methods: {
          refHandle: function () {
            console.log(this.$refs.ref);
            this.$refs.ref.refHandle();
          },
        },
        components:{
          "child-refs":childRefs,         
        },
      });
    </script>
  </body>
</html>
//6测试子向夫emit传值
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>6测试子向夫emit传值</h1>
        <childe-emit @parent="emitHandle">点击接收子的消息内容</childe-emit>
      </div>
    </div>
    <script>
      //6测试子向夫emit传值
      var childEmit = {
        data() {
          return {
            name: "emit子消息",
          };
        },
        template: `<div><button @click="handleChlid">子按钮</button></div>`,
        methods: {
          handleChlid: function () {
            this.$emit("parent", this.name);
          },
        },
      };
      var vm = new Vue({
        el: "#app",
        data: {},
        methods: {
          emitHandle: function (name) {
            alert("接收到子的name了=" + name);
          },
        },
        components: {
          "childe-emit": childEmit,
        },
      });
    </script>
  </body>
</html>

 

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>11测试$attr 继承父组件的props</h1>
        <parent-attr></parent-attr>
      </div>
    </div>
    <script>
      Vue.component("parent-attr", {
        data() {
          return {
            msg: "你好世界",
          };
        },
        template: `<div style="color:blue" :pchild="msg" >测试$attr<child-attr type="checkbox" data-status="哈哈" ></child-attr></div>`,
        methods: {},
      });

      Vue.component("child-attr", {
        inheritAttrs: false,
        template: `<input type="text" v-bind="$attrs"/>`,
        methods: {
          handle: function () {},
        },
      });

      var vm = new Vue({
        el: "#app",
        data: {},
        methods: {

        },
        components: {
        
        },
      });
    </script>
  </body>
</html>

 

11测试$attr 继承父组件的props
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>11测试$attr 继承父组件的props</h1>
        <parent-attr></parent-attr>
      </div>
    </div>
    <script>
      Vue.component("parent-attr", {
        data() {
          return {
            msg: "你好世界",
          };
        },
        template: `<div style="color:blue" :pchild="msg" >测试$attr<child-attr type="checkbox" data-status="哈哈" ></child-attr></div>`,
        methods: {},
      });

      Vue.component("child-attr", {
        inheritAttrs: false,
        template: `<input type="text" v-bind="$attrs"/>`,
        methods: {
          handle: function () {},
        },
      });

      var vm = new Vue({
        el: "#app",
        data: {},
        methods: {

        },
        components: {
        
        },
      });
    </script>
  </body>
</html>
12测试动态组件
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <div class="box">
          <h1>12测试动态组件</h1>
          <button v-for="tab in tabs" @click="currentTab=tab.title">
            {{tab.displayName}}
          </button>
          <keep-alive>
            <component :is="currentTabComponent"></component>
          </keep-alive>        
        </div>
      </div>
    </div>
    <script>
        //12测试动态组件
        Vue.component("tab-introduce", {
        data() {
          return {
            content: "java无难事",
          };
        },
        template: `<div><input type="text" v-model="content"/></div>`,
      });

      Vue.component("tab-comment", {
        template: `<div>这是一本好书</div>`,
      });

      Vue.component("tab-qa", {
        template: `<div>有人看过吗</div>`,
      });


      var vm = new Vue({
        el: "#app",
        data: {
          currentTab: "introduce",
          tabs: [
            { title: "introduce", displayName: "图书介绍" },
            { title: "comment", displayName: "图书评价" },
            { title: "qa", displayName: "图书问答" },
          ],

        }, 
        computed: {
          currentTabComponent: function () {
            return "tab-" + this.currentTab;
          },
        },
        methods: {

        },
        components: {
        
        },
      });
    </script>
  </body>
</html>
13测试组件异步更新队列
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
    <style>
      .box {
        width: 500px;
        border: 1px solid red;
        float: left;
      }
      ul {
        list-style: none;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="box">
        <h1>13测试组件异步更新队列</h1>
        <async-component></async-component>
      </div>
    </div>
    <script>
      //13测试组件异步更新队列
      Vue.component("async-component",{
        data() {
          return {
            message:"java无难事"
          }
        },
        template:` <div>
          <p >{{message}}</p>
          <p >{{message}}</p>
          <button @click="change">修改内容</button>
        </div>`,
        methods:{
          change:function(){
            this.message='深入理解vc'
            // this.$nextTick(()=>{})
            // console.log(this)
            // console.log(this.$refs)
            // console.log(this.$refs.msg.textContent);
          }
        }
      })


      var vm = new Vue({
        el: "#app",
        data: {
          currentTab: "introduce",
          tabs: [
            { title: "introduce", displayName: "图书介绍" },
            { title: "comment", displayName: "图书评价" },
            { title: "qa", displayName: "图书问答" },
          ],

        }, 
        computed: {
          currentTabComponent: function () {
            return "tab-" + this.currentTab;
          },
        },
        methods: {

        },
        components: {
        
        },
      });
    </script>
  </body>
</html>

 

 

keep-alive 
keep-alive 是 Vue.js 中的一个内置抽象组件,用于缓存不活动的组件实例,而不是销毁它们。这对于保留组件状态或避免重新渲染开销较大的组件时非常有用。当组件被包裹在 <keep-alive> 中时,它的状态会被保留,当它再次被访问时,Vue 会重新渲染组件的已保留状态,而不是从头开始重新创建它。

基本用法
html
<keep-alive>  
  <component :is="currentView"></component>  
</keep-alive>
在这个例子中,currentView 是一个动态组件名,它决定了 <keep-alive> 内部应该渲染哪个组件。当 currentView 更改时,如果新的组件已经在 <keep-alive> 中被渲染过,那么它将不会被重新创建,而是会重新激活其已缓存的实例。

生命周期钩子
当组件被 <keep-alive> 包裹时,它会有两个额外的生命周期钩子:

activated:当组件被激活时调用。
deactivated:当组件被停用时调用。
这两个钩子允许你在组件被缓存和重新激活时执行特定的逻辑。

排除和包含
<keep-alive> 允许你指定哪些组件应该被缓存,哪些不应该。这可以通过 include 和 exclude 属性来实现,它们接受逗号分隔的字符串、正则表达式或一个数组。

include:只有匹配的组件会被缓存。
exclude:任何匹配的组件都不会被缓存。
html
<!-- 逗号分隔的字符串 -->  
<keep-alive include="ComponentA,ComponentB">  
  <component :is="currentView"></component>  
</keep-alive>  
  
<!-- 正则表达式 (使用 v-bind) -->  
<keep-alive :include="/A|B/">  
  <component :is="currentView"></component>  
</keep-alive>  
  
<!-- 数组 (使用 v-bind) -->  
<keep-alive :include="['ComponentA', 'ComponentB']">  
  <component :is="currentView"></component>  
</keep-alive>
注意事项
使用 <keep-alive> 时,需要注意内存使用,因为缓存的组件实例会占用内存。
如果组件内部有大量的数据或复杂的计算,那么即使使用 <keep-alive>,也可能不会显著提高性能,因为重新激活组件时仍然需要执行这些计算。
在某些情况下,你可能需要手动清除 <keep-alive> 的缓存,Vue 没有直接提供 API 来清除缓存,但你可以通过改变 currentView 的值来间接实现,或者通过其他方式(如使用 Vuex)来管理组件的缓存状态。

 

 

 

 

posted on 2024-09-20 01:37  是水饺不是水饺  阅读(24)  评论(0)    收藏  举报

导航