Vue组件化开发

1. 全局组件

<div id="app">
  <button-counter></button-counter>
</div>
Vue.component("button-counter", {
  data: function(){
    return{
      count: 0
    }
  },
  template: "<button @click='handle'>点击了{{count}}次</button>",
  methods:{
    handle:function(){
      this.count+=2;
    }
  }
});

var vm = new Vue({
    el:"#app"
});

可以重用,子组件之间的数据都是独立的

<div id="app">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

2.局部组件

<div id="app">
  <hello-world></hello-world>
  <hello-a></hello-a>
  <hello-b></hello-b>
</div>
<script>
  var HelloWorld = {
    data: function() {
      return {
        msg:"HelloWorld"
      }
    },
    template:"<div>{{msg}}</div>"
  };

  var HelloA = {
    data: function() {
      return {
        msg:"HelloA"
      }
    },
    template:"<div>{{msg}}</div>"
  };

  var WorldB = {
    data: function() {
      return {
        msg:"WorldB"
      }
    },
    template:"<div>{{msg}}</div>"
  };

    var vm = new Vue({
        el:"#app",
        data:{
        },
        components: {
          "hello-world": HelloWorld,
          "hello-a": HelloA,
          "hello-b": WorldB,
        }
    });
</script>

局部组件只能在注册他的父组件中使用,在其子组件中不可用

3.组件注册注意事项:

  1. data必须是一个函数
    使用函数会形成一个闭包的环境,保证每一个组件都拥有独立的数据
  2. 组件模板内容必须是单个根元素
    错误示范
    template: "<button @click='handle'>点击了{{count}}次</button><button>又是一个按钮</button>",
    解决方法:外部包一个div
    template: "<div><button @click='handle'>点击了{{count}}次</button><button>又是一个按钮</button></div>",

单个根元素,每个组件必须只有一个根元素,否则后台会报错, 若要添加多个元素,则需要有一个根元素将子元素进行包裹,template里面用到的所有属性都需要在props数组内进行声明才可以进行使用,同时需要在使用组件的时候进行传值才可以, 否则该值会显示为undefined,使用了 JavaScript 的模板字符串来让多行的模板更易读

    <div id="app">
      <blog-post :key="post.id" v-for="post in posts" :post="post"></blog-post>
    </div>
    <script>
        Vue.component("blog-post", {
          props: ["post"],
          template: `
            <div class="blog-post">
              <h3>{{post.title}}</h3>
              <div v-html="post.content"></div>
            </div>
            `
        });

        var vm = new Vue({
            el:"#app",
            data:{
              posts:[
                {id: 1, title: "My journey with Vue", content: "1234"},
                {id: 2, title: 'Blogging with Vue', content: "1234"},
                {id: 3, title: 'Why Vue is so fun', content: "1234" }
              ]
            }
          });
    </script>
  1. 组件模板内容可以是模板字符串
template: `
  <div>
    <button @click='handle'>点击了{{count}}次</button>
    <button>模板字符串的方式</button>
  </div>
`
  1. 组件命名方式
  • kebab-case (短横线分隔命名)
    button-counter
  • camelCase (驼峰命名法)
    HelloWorld
    *如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签的模板中,必须使用短横线的方式使用组件,或者把所有的大写字母转成小写加短横线hello-world

组件基础

1.父组件向子组件传递数据
  1. 通过 Props父组件向子组件传递数据
    在父组件中,直接通过属性的方式传递给子组件:title="来自父组件的值"
    Props接收父组件传过来的数据,是一个数组:props: ["title"],

静态绑定:

    <div id="app">
      <blog-post title="来自父组件的值"></blog-post>
    </div>
    <script>
        Vue.component("blog-post", {
          data () {
            return {
              msg:"子组件本身的数据"
            }
          },
          props: ["title"],
          template: "<h3>{{msg + '--' +  title}}</h3>"
        });

        var vm = new Vue({
            el:"#app"
          });
    </script>

v-bind动态绑定属性值:pTitle要在父组件中定义

    <div id="app">
      <blog-post :title="pTitle"></blog-post>
    </div>
    <script>
        Vue.component("blog-post", {
          data () {
            return {
              msg:"子组件本身的数据"
            }
          },
          props: ["title"],
          template: "<h3>{{msg + '--' +  title}}</h3>"
        });

        var vm = new Vue({
            el:"#app",
            data:{
              pTitle:"12345"
            }
          });
    </script>

注意*:使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名

js中:驼峰命名法

Vue.component('blog-post', {
  // 在 JavaScript 中是 camelCase 的
  props: ['postTitle'],
  template: '<h3>{{ postTitle }}</h3>'
})

html中:短横线分隔命名

<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>

到这里,我们只看到了以字符串数组形式列出的 prop:
还有其他四种

(1)poros属性值内容为数字

:tai="30"属性值通过v-bind绑定则,30typeofnumber

    <div id="app">
		<alert-box :dong="90" :tai="30"></alert-box>
    </div>
    
    <script>
      Vue.component('alert-box', {
        props:["dong", "tai"],
        template: `
          <div>
            <strong>{{dong}}</strong>
            <input :value="tai+12"></input>
          </div>
        `
      })
        
      var vm = new Vue({
        el: '#app'
      })
    </script>

在这里插入图片描述
tai="30",直接绑定,则30typeofstring,将做字符串拼接

    <div id="app">
		<alert-box :dong="90" tai="30"></alert-box>
    </div>

在这里插入图片描述

(1)poros属性值内容为布尔值

设置按钮为不可按:disabled="true"

    <div id="app">
		<alert-box :dong="true" :tai="30"></alert-box>
    </div>
    
    <script>
      Vue.component('alert-box', {
        props:["dong", "tai"],
        template: `
          <div>
            <button :disabled="dong">{{tai}}</button>
          </div>
        `
      })
        
      var vm = new Vue({
        el: '#app'
      })
    </script>

与数字相似,若以v-bind绑定,则为布尔值,若直接绑定,则"true"为字符串

(1)poros属性值内容为数组

    <div id="app">
			<alert-box :list="list"></alert-box>
    </div>
    
    <script>
      Vue.component('alert-box', {
        props:["list"],
        template: `
          <ul>
            <li :key="index" v-for="(item, index) in list">{{item}}</li>  
          </ul>
        `
      })
        
      var vm = new Vue({
        el: '#app',
        data:{
          list:["banbana", "orange", "pear"]
        }
      })
    </script> 

在这里插入图片描述

(1)poros属性值内容为对象

    <div id="app">
			<alert-box :list="list"></alert-box>
    </div>
    
    <script>
      Vue.component('alert-box', {
        props:["list"],
        template: `
          <div>
            <h1 :key="index" v-for="(item, index) in list">{{item.name + "---" + item.age}}</h1>
          </div>
        `
      })
        
      var vm = new Vue({
        el: '#app',
        data:{
          list:[{
            name:"ming",
            age:20
          },{
            name:"hong",
            age:10
          }]
        }
      })
    </script>

在这里插入图片描述

1.子组件向父组件传值–基本用法$emit 方法

props传递数据原则:单向数据流
因此子组件通过自定义事件的方式传递信息

  • 子组件通过自定义事件向父组件传递信息
    <button @click="$emit('enlarge-text')">Enlarge text</button>
  • 父组件监听子组件的事件
    <blog-post @enlarge-text="postFontSize += 5"></blog-post>

添加一个按钮来放大字号

    <div id="app">
      <div :style="{fontSize: postFontSize + 'px'}">
        <blog-post :key="post.id" v-for="post in posts" :post="post" @enlarge-text="handle"></blog-post>
      </div>
    </div>
    <script>
        Vue.component("blog-post", {
          props: ["post"],
          template: `
            <div class="blog-post">
              <h3>{{post.title}}</h3>
              <div v-html="post.content"></div>
              <button @click="$emit('enlarge-text')">Enlarge text</button>
            </div>
            `
        });

        var vm = new Vue({
            el:"#app",
            data:{
              posts:[
                {id: 1, title: "My journey with Vue", content: "1234"},
                {id: 2, title: 'Blogging with Vue', content: "1234"},
                {id: 3, title: 'Why Vue is so fun', content: "1234" }
              ],
              postFontSize: 10
            },
         
            methods: {
              handle: function(){
                this.postFontSize += 5;
              }
            } 
          },
        );
    </script>

使用事件抛出一个值$emit('enlarge-text', 5) $event
例如我们可能想让 组件决定它的文本要放大多少。这时可以使用 $emit 的第二个参数来提供这个值

    <div id="app">
      <div :style="{fontSize: postFontSize + 'px'}">
        <blog-post :key="post.id" v-for="post in posts" :post="post" @enlarge-text="postFontSize += $event"></blog-post>
      </div>
    </div> 
    <script>
        Vue.component("blog-post", {
          props: ["post"],
          template: `
            <div class="blog-post">
              <h3>{{post.title}}</h3>
              <div v-html="post.content"></div>
              <button @click="$emit('enlarge-text', 1)">Enlarge text</button>
            </div>
            `
        });

        var vm = new Vue({
            el:"#app",
            data:{
              posts:[
                {id: 1, title: "My journey with Vue", content: "1234"},
                {id: 2, title: 'Blogging with Vue', content: "1234"},
                {id: 3, title: 'Why Vue is so fun', content: "1234" }
              ],
              postFontSize: 30
            }
          });
    </script>

或者,如果这个事件处理函数是一个方法,将$event作为函数的参数传递过来

    <div id="app">
      <div :style="{fontSize: postFontSize + 'px'}">
        <blog-post :key="post.id" v-for="post in posts" :post="post" @enlarge-text="handle($event)"></blog-post>
      </div>
    </div>
    <script>
        Vue.component("blog-post", {
          props: ["post"],
          template: `
            <div class="blog-post">
              <h3>{{post.title}}</h3>
              <div v-html="post.content"></div>
              <button @click="$emit('enlarge-text',1)">Enlarge text</button>
            </div>
            `
        });

        var vm = new Vue({
            el:"#app",
            data:{
              posts:[
                {id: 1, title: "My journey with Vue", content: "1234"},
                {id: 2, title: 'Blogging with Vue', content: "1234"},
                {id: 3, title: 'Why Vue is so fun', content: "1234" }
              ],
              postFontSize: 10
            },
         
            methods: {
              handle: function(val){
                this.postFontSize += val
              }
            } 
          },
        );
    </script>

也可以省略不写,那么这个值将会作为第一个参数传入这个方法
@enlarge-text="handle"

插槽

通过插槽分发内容

    <div id="app">
			<alert-box>我在最后</alert-box>
    </div>
    
    <script>
      Vue.component('alert-box', {
        template: `
          <div class="demo-alert-box">
            <strong>Error!</strong>
            <h1>我在这儿</h1>
            <slot></slot>
          </div>
        `
      })
        
      var vm = new Vue({
        el: '#app'
      })
    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值