Vue基本用法:组件

局部组件的使用:

如果实例化对象Vue对象中既有el,又有 template,并且 template 中定义了模板的内容,那么 template 模板的优先级大于el 。

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 虽然 id="app" 的 div 没有渲染,但是这个标签必须得有,因为 el:"#app" 对它进行了绑定 -->
    <div id="app">

    </div>
</body>
<script src="./vue.js"></script>
<script>

    // 如果实例化对象Vue对象中既有el,又有 template,并且 template 中定义了模板的内容,那么 template 模板的优先级大于el
    new Vue({
        el: "#app",
        data(){
            return {
                msg: "NEO"
            }
        },
        template:`
            <div>
                <h2>{{ msg }}</h2>    
            </div>
        `
        // 由于 template 的优先级高于 el, 所以浏览器上会优先渲染 template 中的内容  
    })
</script>
</html>

浏览器效果示例:

组件三步走:

1、 声明子组件
2、 挂载子组件: 在 components 中挂载子组件
3、 使用子组件: 在 html标签中,或 其它子组件的 template 中使用子组件,并且 在template中定义html标签时,一定要用一对闭合标签包裹起来。

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 虽然 id="app" 的 div 没有渲染,但是这个标签必须得有,因为 el:"#app" 对它进行了绑定 -->
    <div id="app">

    </div>
</body>
<script src="./vue.js"></script>
<script>

    // App 组件: header组件、 aside组件、 content组件
    // 1. 声明子组件: Vue中组件的名字首字母要大写(跟标签做区分)
    let App = {     // 声明App组件,其对应的是一个对象,该对象跟 Vue 实例化的时候一样,唯一不同的是没有 el 
        data(){
            // 在这个 data 中绑定当前组件()的数据属性
            return {
                myText: "neoneoneo"
            }
        },
        // 渲染页面的时候, template 中的内容会替换到 <App /> --- 该组件(App)会渲染到页面
        template:`
            <div id="aa">
                <h2>{{ myText }}</h2>
            </div>
        `,
    }


    // 如果实例化对象Vue对象中既有el,又有 template,并且 template 中定义了模板的内容,那么 template 模板的优先级大于el
    new Vue({
        el: "#app",
        data(){
            return {
                msg: "NEO"
            }
        },
        // 3. 使用子组件; <App /> 相当于一个自定义标签,你也可以把这个自定义标签定义为Div,为了和 <div> 标签区分,所以自定义的标签首字母要大写
        template:`
            <div id="bb">
                <App />
            </div>
        `,
        // 由于 template 的优先级高于 el, 所以浏览器上会优先渲染 template 中的内容

        // 2. 挂载子组件
        components:{
            App     // 等价于 App: App; key 和 value 一样的时候,可以只写一个 key
        }
    })
</script>
</html>

浏览器效果示例: 

 

局部组件:Vue中没有 template 且 子组件挂载子组件

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <!-- 使用子组件 -->
        <App />
    </div>
</body>
<script src="./vue.js"></script>
<script>
    let Vheader = {
        data(){
            return {

            }
        },

        // 所有template 中的html内容,都要用一对闭合标签包裹起来,如: <div></div>
        template:`
            <div>
                <h2>HELLO</h2>
                <h2>WORLD</h2>
            </div>
        `
    }

    // 声明子组件
    let App = {
        data(){
            return {
                myText: "neoneoneo"
            }
        },
        
        // template 用于定义模板的内容
        // 把 Vheader 子组件在下面的template中使用
        template:`
            <div id="aa">
                <h2>{{ myText }}</h2>
                <Vheader />
            </div>
        `,

        // 挂载子组件
        components:{
            Vheader
        }
    }

    new Vue({   // 没有 template 
        el: "#app",
        data(){
            return {
                msg: "NEO"
            }
        },
        
        // 2. 挂载子组件
        components:{
            App     // 等价于 App: App; key 和 value 一样的时候,可以只写一个 key
        }
    })
</script>
</html>

浏览器效果示例:

全局组件:

Vue全局组件用 Vue.component 去声明

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <App></App>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    // 全局组件的注册: Vue.component(),第一个参数是组件的名字,第二个参数 options参数。全局组件可以在全局任意地方使用
    Vue.component("VBtn",{
        data(){
            return {

            }
        },
        template:`<button>按钮</button>`,
    })

    let Vheader = {
        data(){
            return {

            }
        },
        // 全局组件使用的时候,,不需要再挂载 
        template:`
            <div>
                <h2>HELLO</h2>
                <h2>WORLD</h2>
                <VBtn></VBtn>
                <VBtn />
            </div>
        `
    }

    let App = {
        data(){
            return {
                myText: "neoneoneo"
            }
        },
        // 全局组件使用的时候,,不需要再挂载 
        template:`
            <div id="aa">
                <h2>{{ myText }}</h2>
                <Vheader />
                <br/>
                <VBtn />
            </div>
        `,

        components:{
            Vheader
        }
    }

    new Vue({
        el: "#app",
        data(){
            return {}
        },
        components:{
            App
        }
    })
</script>
</html>

浏览器效果示例:

slot 组件:

<slot></slot> slot 是Vue 提供的内置组件,它能够分发内容 

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <App></App>
    </div>
</body>
<script src="./vue.js"></script>
<script>
    
    Vue.component("VBtn",{
        data(){
            return {

            }
        },
        // slot 标签是 Vue 的内置组件,<VBtn></VBtn>中的内容能够被分发到 slot 处
        template:`
            <button>
                <slot></slot>
            </button>
        `,
    })

    let Vheader = {
        data(){
            return {

            }
        },
       
        // <VBtn></VBtn> 中的“登陆”、“注册”能够被分发到 slot 处 
        template:`
            <div>
                <h2>HELLO</h2>
                <h2>WORLD</h2>
                <VBtn>登陆</VBtn>
                <VBtn>注册</VBtn>
            </div>
        `
    }

    let App = {
        data(){
            return {
                myText: "neoneoneo"
            }
        },
        
        template:`
            <div id="aa">
                <h2>{{ myText }}</h2>
                <Vheader />
                <br/>
                <VBtn />
            </div>
        `,

        components:{
            Vheader
        }
    }

    new Vue({
        el: "#app",
        data(){
            return {}
        },
        components:{
            App
        }
    })
</script>
</html>

浏览器效果示例:

 

父子组件传值:

父组件向子组件传值:
1. 在子组件中使用 props 声明自定义属性,这些自定义属性就可以直接在子组件中任意使用;
2. 父组件中要定义这些属性(步骤1中 props 声明的属性)

示例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">

    </div>
</body>
<script src="./vue.js"></script>
<script>
    // 全局组件 VBtn 从 父组件 Vheader 中获取值
    Vue.component("VBtn",{
        data(){
            return {

            }
        },
        template:`
            <button>
                按钮 {{ btid }}
            </button>
        `,
        props: ['btid']
    })

    let Vheader = {
        data() {
            return {

            }
        },

        // props 挂载父组件的属性;props 对应的是一个数组; props 中声明的属性就相当于在 data 中绑定了
        // mypro 这个属性要在父组件中定义传值
        props: ['mypro', 'post'],

        // 在 template 中可以使用 mypro 这个自定义属性
        template: `
            <div>
                <h2>HELLO</h2>
                <h2>WORLD</h2>
                <h6>{{ mypro }}</h6>

                <p>{{ post.title }}</p>

                <VBtn :btid="post.id"></VBtn>
            </div>
        `
    }

    // 声明子组件
    let App = {
        data() {
            return {
                myText: "我是父组件App中的数据",
                child_pro: "要传给子组件的值",

                post: {
                    id: 1,
                    title: 'My Journey with Vue'
                }
            }
        },

        // 父组件要把子组件自定义属性的值传过去,通过 v-bind
        template: `
            <div id="aa">
                <h2>{{ myText }}</h2>
                <Vheader :mypro='child_pro' v-bind:post="post"></Vheader>
            </div>
        `,

        components: {
            Vheader
        }
    }

    new Vue({
        el: "#app",
        data() {
            return {
                msg: "NEO"
            }
        },
        template: `<App />`,
        components: {
            App
        }
    })
</script>

</html>

浏览器效果示例:

 

props 传值官方文档:https://cn.vuejs.org/v2/guide/components-props.html#%E4%BC%A0%E9%80%92%E9%9D%99%E6%80%81%E6%88%96%E5%8A%A8%E6%80%81-Prop

子组件往父组件传值:

触发父组件中自定义声明的事件,需要使用 Vue 提供的内置 $emit 方法

示例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">

    </div>
</body>
<script src="./vue.js"></script>
<script>
    /* 想要实现的效果:点击 VBtn 中的按钮,修改App 中post对象的id值 */


    Vue.component("VBtn",{
        data(){
            return {
                // 把 父组件传递过来的 btnid 赋值给 bid
                bid: this.btnid
            }
        },

        // 给 button 添加一个点击事件
        template:`
            <button @click="vbtnToHeader">
                按钮 {{ bid }}
            </button>
        `,
        // props 中声明的属性,即相当于绑定到了 data 中
        props: ['btnid'],

        // 给button 中的点击事件添加对应的方法
        methods: {
            vbtnToHeader(){
                console.log(this)   // 每个组件中的 this 都是指该组件对象,即一个 VueComponent 对象
                this.bid++;
                console.log(this.btnid)
                // $emit 是 Vue 提供的内置方法,用于触发父组件中自定义声明的事件。 this.$emit("父组件中自定义声明的事件", "要传递的值")
                // vheaderClickHandler 是 VBtn 的父组件 Vheader 中对应的 自定义事件;后面的参数是传递到 vheaderClickHandler 对应的方法中
                this.$emit('vheaderClickHandler', this.bid);
            }
        }
    })

    let Vheader = {
        data() {
            return {

            }
        },

        props: ['mypro', 'post'],

        // vheaderClickHandler 是自定义的事件(属性能自定义,事件也能自定义),该自定义事件绑定了一个方法 clickHandler
        template: `
            <div>
                <h2>HELLO</h2>
                <h2>WORLD</h2>
                <h6>{{ mypro }}</h6>

                <p>{{ post.title }}</p>

                <VBtn :btnid="post.id" @vheaderClickHandler="clickHandler"></VBtn>
            </div>
        `,


        methods:{
            clickHandler(val){
                alert(val);
                // 这个 this 表示 Vheader 当前组件 VueComponent 对象
                this.id = val;      // 到这一步,就已经实现点击 VBtn 按钮修改按钮中id数据;但此时 post对象中id的值并没有改变;所以, 如果想要修改 post对象中id的值,就要接着往父组件emit

                // 继续往父组件 emit 来修改 post 中id的值
                this.$emit('updatePost', val)
            }
        }
    }

    let App = {
        data() {
            return {
                myText: "我是父组件App中的数据",
                child_pro: "要传给子组件的值",

                post: {
                    id: 1,
                    title: 'My Journey with Vue'
                }
            }
        },

        template: `
            <div id="aa">
                <h1>post中的id :{{ post.id }}</h1>
                <h2>{{ myText }}</h2>
                <Vheader :mypro='child_pro' v-bind:post="post" @updatePost="updatePostHandler"></Vheader>
            </div>
        `,

        components: {
            Vheader
        },

        methods:{
            updatePostHandler(val){
                this.post.id = val;
            }
        }
    }

    new Vue({
        el: "#app",
        data() {
            return {
                msg: "NEO"
            }
        },
        template: `<App />`,
        components: {
            App
        }
    })
</script>

</html>

浏览器效果示例:

 

平行组件传值:

假如 A 组件要向 B组件传值,即 A ==> B,那么接收方B要用 $on 声明事件, 发送方要用 $emit 触发事件。
$on('事件的名字', function(val){})    // val 是要传过来的数据
$emit('A组件中声明的事件名', val)    // val 是要传递过去的数据

// $on 和 $emit 这两个方法必须绑定在同一个实例化对象中(bus 对象)

平行组件的这种传值方式,不仅能用于平行组件之间传值,同样也能用于父传子、子传父。

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <!-- 使用 App 组件 -->
        <App />
    </div>
    
</body>
<script src="./vue.js"></script>
<script>

    // $emit 和 $on 要绑定在同一个实例化对象中;该示例中我们绑定到一个全局变量 Vue 实例
    let bus = new Vue();    // 这是一个新的 Vue 对象,和下面的Vue 对象不是同一个内存地址

    // Test01 和 Test02 是平行的关系;现在想要实现的效果是点击按钮,就把 Test01 中的数据传递级给 Test02

    Vue.component('Test02', {
        data(){
            return {
                passedData:''
            }
        },
        template:`
            <h2>{{ passedData }}</h2>
        `,

        created(){
            // 注意:要把 $on 绑定到 bus 上,而不能绑定到 this上;
            bus.$on('passDataEvent', (val) => {
                this.passedData = val;
                console.log(this);      // VueComponent
                /*
                注意:$on的第二个参数回调函数,不能用 function(){},要用箭头函数。如果用 function(){},那么函数中的 this 指的是当前对象,即 bus (Vue 对象);
                用 箭头函数,this 的指向会发生改变,改为 声明了该对象的上下文,即 Test02 组件。
                
                判断 this 指的是谁,只需要看是谁调用的该函数即可
                */
            })
        }
    })

    Vue.component('Test01', {
        data(){
            return {
                msg:"我是 Test01 中的数据,我要去Test02"
            }
        },
        template:`
            <button @click="passDataHandler">传递</button>
        `,

        methods:{
            passDataHandler(){
                // $emit 绑定到 bus 上;注意:不能绑定到 this 上
                bus.$emit('passDataEvent', this.msg);   // 第一个参数是 $on 中声明的事件名,第二个参数是要传递的数据
            }
        }
    })

    let Vheader = {
        data(){
            return {

            }
        },
        template:`
            <div class="vheader">
                <Test01 />
                <Test02 />
            </div>
        `,
    }

    let App = {
        data(){
            return {

            }
        },
        template:`
            <div class="apps">
                <Vheader />
            </div>
        `,

        // 挂载
        components:{
            Vheader
        }
    }
    new Vue({
        el: "#app",
        data(){
            return {

            }
        },

        // 挂载 App组件
        components:{
            App
        }
    })
</script>
</html> 

浏览器效果示例:

点击按钮前:

 

点击按钮后:

Code your future.
原文地址:https://www.cnblogs.com/neozheng/p/14292395.html