• Vue_组件化


     我们通过Vue的component方法来定义一个全局组件。

    <div id="app">
        <!--使用定义好的全局组件-->
        <counter></counter>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        // 定义全局组件,两个参数:1,组件名称。2,组件参数
        Vue.component("counter",{
            template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
            data(){
                return {
                    count:0
                }
            }
        })
        var app = new Vue({
            el:"#app"
        })
    </script>
    • 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等

    • 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。

    • 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板

    • 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。

    • data必须是一个函数,不再是一个对象。

    效果:

    2.组件的复用

    定义好的组件,可以任意复用多次:

    <div id="app">
        <!--使用定义好的全局组件-->
        <counter></counter>
        <counter></counter>
        <counter></counter>
    </div>

    效果:

    你会发现每个组件互不干扰,都有自己的count值。怎么实现的?

    组件的data属性必须是函数

    当我们定义这个 <counter> 组件时,它的data 并不是像之前直接提供一个对象:

    data: {
      count: 0
    }

    取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

    data: function () {
      return {
        count: 0
      }
    }

    如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!

    3.局部组件

    一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。

    因此,对于一些并不频繁使用的组件,我们会采用局部注册。

    我们先在外部定义一个对象,结构与创建组件时传递的第二个参数一致:

    const counter = {
        template:'<button v-on:click="count++">你点了我 {{ count }} 次,我记住了.</button>',
        data(){
            return {
                count:0
            }
        }
    };

    然后在Vue中使用它:

    var app = new Vue({
        el:"#app",
        components:{
            counter:counter // 将定义的对象注册为组件
        }
    })
    • components就是当前vue对象子组件集合。

      • 其key就是子组件名称

      • 其值就是组件对象名

    • 效果与刚才的全局注册是类似的,不同的是,这个counter组件只能在当前的Vue实例中使用

    4.组件通信

    通常一个单页应用会以一棵嵌套的组件树的形式来组织:

    • 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分

    • 左侧内容区又分为上下两个组件

    • 右侧边栏中又包含了3个子组件

    各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。

    4.1.props(父向子传递)

    1. 父组件使用子组件时,自定义属性(属性名任意,属性值为要传递的数据)

    2. 子组件通过props接收父组件数据,通过自定义属性的属性名

    父组件使用子组件,并自定义了title属性:

    <div id="app">
        <h1>打个招呼:</h1>
        <!--使用子组件,同时传递title属性-->
        <introduce title="大家好,我是锋哥"/>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        Vue.component("introduce",{
            // 直接使用props接收到的属性来渲染页面
            template:'<h1>{{title}}</h1>',
            props:['title'] // 通过props来接收一个父组件传递的属性
        })
        var app = new Vue({
            el:"#app"
        })
    </script>

    效果:

    4.2.props验证

    我们定义一个子组件,并接收复杂数据:

    const myList = {
        template: '
        <ul>
            <li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>
        </ul>
        ',
        props: {
            items: {
                type: Array,
                default: [],
                required: true
            }
        }
    };
    • 这个子组件可以对 items 进行迭代,并输出到页面。

    • props:定义需要从父组件中接收的属性

      • items:是要接收的属性名称

        • type:限定父组件传递来的必须是数组

        • default:默认值

        • required:是否必须

    当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

    我们在父组件中使用它:

    <div id="app">
        <h2>传智播客已开设如下课程:</h2>
        <!-- 使用子组件的同时,传递属性,这里使用了v-bind,指向了父组件自己的属性lessons -->
        <my-list :items="lessons"/>
    </div>
    var app = new Vue({
        el:"#app",
        components:{
            myList // 当key和value一样时,可以只写一个
        },
        data:{
            lessons:[
                {id:1, name: 'java'},
                {id:2, name: 'php'},
                {id:3, name: 'ios'},
            ]
        }
    })

    效果:

     type类型,可以有:

     注意:子组件模板有且只有一个根标签

    3.动态静态传递

    给 prop 传入一个静态的值:

    <introduce title="大家好,我是锋哥"/>

    给 prop 传入一个动态的值: (通过v-bind从数据模型中,获取title的值)

    <introduce :title="title"/>

    静态传递时,我们传入的值都是字符串类型的,但实际上任何类型的值都可以传给一个 props。

    <!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
    <!-- 这是一个JavaScript表达式而不是一个字符串。-->
    <blog-post v-bind:likes="42"></blog-post>
    
    <!-- 用一个变量进行动态赋值。-->
    <blog-post v-bind:likes="post.likes"></blog-post>

    4.子向父的通信:$emit

    来看这样的一个案例:

    <div id="app">
        <h2>num: {{num}}</h2>
        <!--使用子组件的时候,传递num到子组件中-->
        <counter :num="num"></counter>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="text/javascript">
        Vue.component("counter", {// 子组件,定义了两个按钮,点击数字num会加或减
            template:'
                <div>
                    <button @click="num++">加</button>  
                    <button @click="num--">减</button>  
                </div>',
            props:['num']// count是从父组件获取的。
        })
        var app = new Vue({
            el:"#app",
            data:{
                num:0
            }
        })
    </script>
    • 子组件接收父组件的num属性

    • 子组件定义点击按钮,点击后对num进行加或减操作

    我们尝试运行,好像没问题,点击按钮试试:

    子组件接收到父组件属性后,默认是不允许修改的。怎么办?

    既然只有父组件能修改,那么加和减的操作一定是放在父组件:

    var app = new Vue({
        el:"#app",
        data:{
            num:0
        },
        methods:{ // 父组件中定义操作num的方法
            increment(){
                this.num++;
            },
            decrement(){
                this.num--;
            }
        }
    })

    但是,点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,怎么做?

    我们可以通过v-on指令将父组件的函数绑定到子组件上:

    <div id="app">
        <h2>num: {{num}}</h2>
        <counter :count="num" @inc="increment" @dec="decrement"></counter>
    </div>

    在子组件中定义函数,函数的具体实现调用父组件的实现,并在子组件中调用这些函数。当子组件中按钮被点击时,调用绑定的函数:

    Vue.component("counter", {
        template:'
            <div>
                <button @click="plus">加</button>  
                <button @click="reduce">减</button>  
            </div>',
        props:['count'],
        methods:{
            plus(){
                this.$emit("inc");
            },
            reduce(){
                this.$emit("dec");
            }
        }
    })
    • vue提供了一个内置的this.$emit()函数,用来调用父组件绑定的函数

    效果:

     

    踩坑:

      子组件必须写在父组件的前面,不然加载不到

    学习中,博客都是自己学习用的笔记,持续更新改正。。。
  • 相关阅读:
    CSP 模拟17
    晚测7
    CSP 模拟16
    CSP 模拟14
    CSP 模拟13
    Cypress系列(67)- 环境变量设置指南
    Cypress系列(66)- 测试运行最佳实践
    Cypress系列(65)- 测试运行失败自动重试
    Cypress系列(64)- 数据驱动策略
    Cypress系列(63)- 使用 Custom Commands
  • 原文地址:https://www.cnblogs.com/Tunan-Ki/p/11868835.html
Copyright © 2020-2023  润新知