【阿里云】各类产品,精心挑选的热门优惠云产品,总有一款适合你的业务形态【腾讯云】爆款2核2G云服务器首年40元,企业首购最高获赠300元京东卡

Vue3 组件

一、组件理论

组件图片


二、创建组件

<!-- `App.vue` 文件中,引入组件 -->
<template>
    <div>欧阳克</div>
    <!-- 4、使用组件里的html代码,这里的标签名 跟 key 对应上 -->
    <!-- 5、一般组件会起驼峰命名,比如:OneCom,TwoCom。 -->
    <!-- 5.1、引入的后,标签可以使用2种方式: -->
    <OneCom></OneCom>
    <one-com></one-com>
</template>
<script>
// 1、导入组件
import OneCom from './components/OneCom';
export default {
    // 2、组件加入,也是使用组件
    components:{
        // 3、key键随便起,value值就是上面引入的名字
        OneCom : OneCom,
        // 如果key和value名字一样,可以写一个
        // OneCom
    }
};
</script>
<!-- 创建 /components/OneCom.vue 文件 -->
<template>
    <div>OneCom组件文件</div>
</template>
<script>
export default {
    name : "OneCom"
};
</script>

三、子组件

<!-- 组件使用子组件 -->
<template>
    <div>OneCom组件文件</div>
    <!-- 3、使用TwoCom标签 -->
    <two-com></two-com>
</template>
<script>
// 1、引入 TwoCom 文件,2个子组件在同一个目录
import TwoCom from './TwoCom';
export default {
    name : "OneCom",
    // 2、使用 TwoCom 组件
    components:{
        TwoCom
    }
};
</script>
<!-- 创建 /components/TwoCom.vue 文件 -->
<template>
    <div>TwoCom组件文件</div>
</template>
<script>
export default {
    name : "TwoCom"
};
</script>

四、使用多组件

<!-- 文件引入多个组件 -->
<template>
    <div>
        <div>欧阳克</div>
        <one-com></one-com>
        <two-com></two-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom.vue";
import TwoCom from "./components/TwoCom.vue";
export default {
    components: {
        OneCom,
        TwoCom
    }
};
</script>
<!-- /components/OneCom.vue 文件 -->
<template>
    <div>OneCom组件文件</div>
</template>
<script>
export default {
    name : "OneCom"
};
</script>
<!-- /components/TwoCom.vue 文件 -->
<template>
    <div>TwoCom组件文件</div>
</template>
<script>
export default {
    name : "TwoCom"
};
</script>

五、属性传值给组件

1、属性传值

<template>
    <div>欧阳克</div>
    <!-- 普通传值,key和value -->
    <one-com title="php中文网"></one-com>
    <!-- 绑定变量传值 -->
    <one-com :title="title" :msg="msg" :arr="arr" :ob="ob"></one-com>
</template>
<script>
import OneCom from "./components/OneCom.vue";
export default {
    name: "Phpcn",
    data() {
        return {
            title: "使用变量的方式传值",
            msg: "消息",
            arr : [
                '欧阳克',
                '朱天蓬',
                '灭绝师太'
            ],
            ob: {
                name: "欧阳克",
                age: "38岁"
            }
        };
    },
    components:{
        OneCom : OneCom
    }
};
</script>
<!-- components/OneCom.vue 子文件 -->
<template>
    <div>
        <div>{{ title }}</div>
        <div>{{ msg }}</div>
        <div>{{ arr }}</div>
        <div>{{ ob }}</div>
    </div>
</template>
<script>
export default {
    name: "App",
    data() {
        return {

        };
    },
    // 1、props 参数,获取父文件的传值
    props: ["title", "msg", "arr", "ob"]
};
</script>

2、接收传值并限制数据

<template>
    <div>
        <one-com :title="title" :msg="msg" :arr="arr" :ob="ob"></one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom.vue";
export default {
    components: {
        OneCom,
    },
    data() {
        return {
            title: "使用变量的方式传值",
            msg: "消息",
            arr : [
                '欧阳克',
                '朱天蓬',
                '灭绝师太'
            ],
            ob: {
                name: "欧阳克",
                age: "38岁"
            }
        };
    },
};
</script>
<!-- components/OneCom.vue 子文件 -->
<!-- 1、接收还可以限制参数 -->
<!-- 2、type 接收数据,类型:String,Array, -->
<!-- 3、default 父文件没有传值,自己会给个默认值 -->
<!-- 4、required 等于true,就是必传的值 -->
<template>
    <div>
        <div>{{ title }}</div>
        <div>{{ msg }}</div>
        <div>{{ arr }}</div>
        <div>{{ ob }}</div>
    </div>
</template>
<script>
export default {
    data() {
        return {};
    },
    // 数组和对象,要用方法返回。没有语法检查,就可以直接写对应的格式
    props: {
        title: {
            type: String,
            default: function () {
                return "php中文网";
            },
            required : true
        },
        msg: {
            type: String,
            default: "默认msg",
        },
        arr: {
            type: Array,
            default: function () {
                return ["欧阳克","朱天蓬"];
            }
        },
        ob: {
            type: Object,
            default: function () {
                return { name: "朱天蓬", age: "48岁" };
            }
        }
    }
};
</script>
# 2、子传父,事件传值 (2个子组件,tabBar 点击tabBar,另一个子组件里的数据要改变,就要经过父组件)
// App.vue文件
<template>
    <div>{{teacher}}</div>
    <one-com @app_edit="app_edit"></one-com>
</template>
<script>
import OneCom from './components/OneCom';
export default {
    data() {
        return {
            teacher : "欧阳克"
        };
    },
    components: {
        OneCom,
    },
    methods : {
        app_edit(e){
            console.log('我是父文件的app_edit方法');
            this.teacher = e;
        }
    }
};
</script>

// components/OneCom.vue 子文件
// 使用 $emit 方法,调用父文件的方法(https://v3.cn.vuejs.org/api/instance-methods.html#emit)
// 所有子传父,都是通过事件传过去的
<template>
    <div>
        <button @click="edit('朱天蓬')">传给父文件</button>
        <button @click="edit('灭绝师太')">传给父文件</button>
    </div>
</template>
<script>
export default {
    data() {
        return {

        };
    },
    methods : {
        edit(teacher){
            console.log('我是子文件的edit方法');
            this.$emit('app_edit',teacher);
        }
    }
};
</script>

3、父子组件之间相互访问 $parent

# 1、子组件调用父组件的方法:$parent 或 $root
// App.vue文件
<template>
    <one-com></one-com>
</template>
<script>
import OneCom from './components/OneCom';
export default {
    data() {
        return {

        };
    },
    components: {
        OneCom
    },
    methods : {
        app_fun() {
            console.log("我是app.vue文件的app_fun方法");
        }
    }
};
</script>

// components/OneCom.vue 子文件
<template>
    <div>{{ one_fun() }}</div>
</template>
<script>
export default {
    data() {
        return {};
    },
    methods: {
        one_fun() {
            console.log("我是子组件的one_fun方法");
            // 使用 $parent 访问父组件, 在使用.app_func找到方法
            this.$parent.app_fun();
            // 使用 $parent.$parent 访问多层组件,$parent代表1层
            this.$parent.$parent.app_fun();
            // 使用 $root 访问最顶层的文件,$root 根节点,可以把这个代码放到 TwoCom.vue 文件里测试
            this.$root.app_fun();
        }
    }
};
</script>


# 2、父组件调用子组件的方法:$refs
// components/OneCom.vue 子文件
<template>
    <div>子组件</div>
</template>
<script>
export default {
    data() {
        return {};
    },
    methods: {
        one_fun() {
            console.log("我是子组件的one_fun方法");
        }
    }
};
</script>


// app.vue 文件
<template>
    <div>
        // 子组件要先起个别名
        <one-com ref="one" @click="app_fun()"></one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    data() {
        return {};
    },
    components: {
        OneCom
    },
    methods: {
        app_fun() {
            // 通过 $refs 访问子组件,one找到别名子组件,在使用.one_fun找到方法
            this.$refs.one.one_fun();
            console.log("我是app.vue文件的app_fun方法");
        }
    }
};
</script>

4、插槽

# 1、使用 slot 标签,做为占位:也叫插槽
// components/OneCom.vue 子文件
<template>
    <div>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <slot></slot>
    </div>
</template>

// App.vue文件
<template>
    <div>
        // 使用子组件,传button标签
        <one-com>
            <button>按钮</button>
        </one-com>
        // 使用子组件,传a标签
        <one-com>
            <a>a链接</a>
        </one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    data() {
        return {};
    },
    components: {
        OneCom
    }
};
</script>


# 2、插槽命名:如果多个插槽,传2次按钮,会出现4个按钮,所以要用命名的方法
// components/OneCom.vue 子文件
<template>
    <div>
        <slot></slot>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        // 使用name参数,给插槽起名
        <slot name="two"></slot>
    </div>
</template>

// App.vue文件
<template>
    <div>
        <one-com>
            <button>按钮</button>
            // 使用 template 标签,v-slot参数,找到有名字的插槽
            <template v-slot:two>
                <button>按钮</button>
            </template>
        </one-com>
        <one-com>
            <a>a链接</a>
            // 也可以#简写,是v-slot的语法糖
            <template #two>
                <a>a链接</a>
            </template>
        </one-com>
        <one-com>
            // 还可以找没有名字的插槽
            <template v-slot:default>
                <a>a标签</a>
            </template>
        </one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    components: {
        OneCom,
    }
};
</script>


# 3、插槽默认值,没传插槽的话,使用默认值。传值的话,就会覆盖默认值
// components/OneCom.vue 子文件
<template>
    <div>
        <slot>第一个插槽</slot>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <slot name="two">第二个插槽</slot>
    </div>
</template>


# 4、父级使用插槽,使用子组件数据
// components/OneCom.vue 子文件
<template>
    <div>
        <slot></slot>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <slot name="two" :php="php"></slot>
    </div>
</template>
<script>
export default {
    data() {
        return {
            php: "PHP中文网"
        }
    }
};
</script>

// App.vue 文件
<template>
    <div>
        <one-com>
            <button>按钮</button>
            // data 是接收数据,里面是 OneCom.vue 的 {php: "欧阳克"}
            <template v-slot:two="data">
                <button>按钮{{ data.php }}</button>
            </template>
        </one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    components: {
        OneCom
    }
};
</script>

三、文件样式

# 1、`style` 标签 `scoped` 属性设置样式只能本组件使用
// OneCom.vue 文件
<template>
    // 1.1、Vue3.2 允许根节点穿透
    <div class="red">{{ name }}</div>
    <div>
        // 1.2、无法穿透
        <div class="red">{{ name }}</div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            name: "欧阳克"
        }
    }
};
</script>

// 1.3、App.vue 文件
<template>
    <div>
        <div class="red">php中文网</div>
        <one-com></one-com>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    components: {
        OneCom
    }
};
</script>
// 1.4、增加scoped属性,OneCom.vue文件中,不能使用class="red"
<style scoped>
.red {
    color: red;
}
</style>


# 2、`lang="scss"` 支持 `scss` 语法
<style scoped lang="scss">
    
</style>

四、组件生命周期

# 1、App.vue文件,生命周期钩子的函数
<template>
    <div>欧阳克</div>
</template>
<script>
export default {
    beforeCreate() {
        console.log("1在创建组件之前调用");
    },
    created() {
        console.log("2组件创建完成调用");
    },
    beforeMount() {
        console.log("3模版挂载之前调用");
    },
    mounted() {
        console.log("4模版挂载完成调用");
    }
};
</script>


# 2、App.vue文件,内容改变会执行 生命周期钩子的函数
<template>
    <div>
        <input type="text" v-model="php" />
    </div>
</template>
<script>
export default {
    data() {
        return {
            php : "php中文网"
        };
    },
    beforeUpdate() {
        console.log("5改变内容之前调用");
    },
    updated() {
        console.log("6改变内容之后调用");
    }
};
</script>


# 3、OneCom文件,每个vue文件都有生命周期钩子的函数
<template>
    <div>
        欧阳克
    </div>
</template>
<script>
export default {
    beforeUnmount() {
        console.log("9组件销毁之前调用");
    },
    unmounted() {
        console.log("10组件销毁之后调用");
    }
};
</script>
# 3.1、App.vue,引入组件文件
<template>
    <div>
        // 如果用v-show,就不会销毁
        <one-com v-if="show"></one-com>
        <button @click="show = !show">销毁</button>
        // keep-alive 缓存,跟v-show一样,不会被销毁,也有自己的事件。 属于v-if和v-show的结合体,又能保留,又能执行事件
        <keep-alive>
            <one-com v-if="show"></one-com>
        </keep-alive>
    </div>
</template>
<script>
import OneCom from "./components/OneCom";
export default {
    components: {
        OneCom
    },
    data() {
        return {
            show: true
        }
    }
};
</script>

# 4、OneCom文件,keep-alive 缓存组件事件
<template>
    <div>
        欧阳克
    </div>
</template>
<script>
export default {
    activated() {
        console.log("11组件缓存前调用");
    },
    deactivated() {
        console.log("12组件缓存后调用");
    }
};
</script>
生命周期作用
beforeCreate在创建组件之前调用
created组件创建完成调用
beforeMount模版挂载之前调用
mounted模版挂载完成调用
beforeUpdate改变内容之前调用
update改变内容之后调用
beforeUnmount组件销毁之前调用
unmounted组件销毁之后调用