批改状态:合格
老师批语:
组件从形式上看就是一个自定义的HTML标签,组件是可复用的vue实例,要构造函数Vue的子类。
<script>// 第一步:创建组件const childComponent = Vue.extend({template: `<h2>Hello World</h2>`});// 第二步:注册组件Vue.component("child-component", childComponent);// Vue实例const vm = new Vue({el: "#app"});</script>
<!-- 第三步:将组件挂载到页面中。 --><div id="app"><child-component></child-component><child-component></child-component><child-component></child-component></div>

以上是一个Vue组件从创建到挂载到页面中的过程。其中可以省略掉第一步的创建过程,直接在第二步注册的时候自动执行创建。
Vue.component(id, [function | object | definition])
id:字符串类型,组件名称。function:可以传入函数Vue.extend({ /* ... */ });{ /* ... */ };Vue.component('my-component')。因此,上述Vue基础实例可以使用以下方法简化:
Vue.component("child-component", {template: `<h2>Hello World</h2>`});
实例 利用全局组件做一个点赞的小案例:
<div id="app"><btn-inc></btn-inc><btn-inc></btn-inc><btn-inc></btn-inc></div><hr><template id="inc"><div><button @click="count++">点赞:+{{count}}</button></div></template><script>Vue.component("btn-inc", {template: "#inc",data() {return {count: 0}}});const vm = new Vue({el: "#app"});</script>

注意:
使用Vue.component()方法创建的组件是全局组件。
全局组件必须声明在Vue实例的外部,并且必须声明在实例创建前。
局部组件:需要在实例化对象中通过components属性进行注册。
1.第一种写法:直接写在组件里面的template属性中。
const vm = new Vue({// 局部组件是属于vue实例的。components: {"btn-inc": {template: `<h2>Hello {{site}} </h2>`,data () {return {site: "PHP中文网"}}}}}).$mount("#app");
使用:
<div id="app"><btn-inc></btn-inc><btn-inc></btn-inc><btn-inc></btn-inc></div>
2.在自定义html标签中渲染
<div id="app"><btn-inc></btn-inc><btn-inc></btn-inc><btn-inc></btn-inc></div><template id="hello"><div><h2>Hello {{site}} </h2></div></template>
const vm = new Vue({components: {"btn-inc": {// 创建一个id为hello的自定义hmtl标签template: "#hello",data () {return {site: "PHP中文网"}}}}}).$mount("#app");
3.给模板字面量赋给一个变量值
const hello = `<h2>Hello {{site}} </h2>`;const vm = new Vue({components: {"btn-inc": {template: hello,data () {return {site: "PHP中文网"}}}}}).$mount("#app");
使用:
<div id="app"><btn-inc></btn-inc><btn-inc></btn-inc><btn-inc></btn-inc></div>
4.根据ES6新特性进行简化
现在,我把整个模板和它的data()函数全部拿出来做一个对象字面量付给一个变量hello:
let hello = {template: `<h2>Hello {{site}}</h2>`,data () {return {site: "PHP中文网"}}};
然后,在vue实例的components组件中定义一个组件名也为hello的组件:
const vm = new Vue({components: {hello: hello}}).$mount("#app");
由于ES6有一个新特性,当对象的属性和值相同时,可简写,所以我还可以这样写:
const vm = new Vue({components: {hello,}}).$mount("#app");
使用:
<div id="app"><hello></hello><hello></hello><hello></hello></div>

注意事项:
在使用子组件的时候,例如上述我们定义的<btn-inc>组件,我们会发现他的data并不是一个对象:
data: {site: "PHP中文网"}
取而代之的是函数,也就是说一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立拷贝:
data () {return {site: "PHP中文网"}}
以上这一点是特别需要注意的。
父组件向子组件传值是通过props属性进行的,Prop是我们在组件上注册的一些自定义attitude。当一个值传递给一个prop attribute的时候,它就变成组件实例的一个property。为了给下面的user-info组件传递用户id,用户名,用户邮箱值,我们可以使用一个props数组将其包含在该组件可接收的prop列表中:
const vm = new Vue({el: "#app",data () {return {users: [{ id: 1, name: "残破的蛋蛋", email: "canpo@dd.cn" },{ id: 2, name: "拤碎的蛋蛋", email: "qiasui@dd.cn" },{ id: 3, name: "漂亮的蛋蛋", email: "piaoliang@dd.cn" },]}},components: {userInfo: {props: ["selfId", "selfUsername", "selfEmail"],template: `<div><span>id:{{selfId}},</span><span>用户名:{{selfUsername}},</span><span>邮箱:{{selfEmail}}</span></div>`}}});
一个组件可以拥有任意数量的prop,任何值都可以传递给prop,在上述案例中,我们就可以在组件实例中访问到这个值,就跟直接访问data中的值一样。
一个组件被注册了之后,我们就可以这样把数据作为一个自定义的attribute传递进来:
<div id="app"><user-infov-for="user of users":self-username="user.name":self-id="user.id":self-email="user.email":key="user.id"></user-info></div>


正常情况下,子组件向父组件传参的是无法直接传递的,需要用到Vue内建的$emit()方法传入事件名称来触发一个事件,
$emit(eventName, […args])
eventName:事件方法,字符串类型
[…args]*:子组件传递给父组件的参数值
以下是一个点赞的案例:首先声明一个Vue实例,并创建一个组件<btn-inc>,由于子组件向父组件传值需要使用同名事件方法通过$emit()进行传值,因此我们需要在子组件<button>上添加一个点击事件方法@click="$emit('click-count', 10)并传递一个click-count方法和值。
<!-- 子组件 --><template id="btn"><div><button @click="$emit('click-count', 10)">点赞 + {{myCount}}</button><span>{{myUsername}}</span></div></template>
父组件<btn-inc>上需要监听一个点击事件click-count:
<div id="app"><btn-inc :my-count="count" :user-name="username" @click-count="handle"></btn-inc></div>
在Vue实例下创建一个handle方法来处理点击事件,这样我们就可以通过子组件向父组件传值了:
handle(value) {this.count += value}
完整的案例代码:
<div id="app"><btn-inc :my-count="count" :user-name="username" @click-count="handle"></btn-inc></div><template id="btn"><div><button @click="$emit('click-count', 10)">点赞 + {{myCount}}</button><span>{{myUsername}}</span></div></template><script>const vm = new Vue({data () {return {count: 0,username: "残破的蛋蛋"};},components: {btnInc: {props: ["userName", "myCount"],template: "#btn",}},methods: {handle(value) {console.log(this.count);this.count += value}},}).$mount("#app");</script>


上面两个案例讲述了父组件向子组件传参以及子组件向父组件传参,下面这个案例讲展示父子组件之间如何双向传参。
<div id="app"><!-- 父组件 --><p>父组件:{{price}} 元</p><my-input :my-price="price" @input-text="handle"></my-input></div><!-- 子组件 --><template id="myinput"><div><input type="text" :value="myPrice" @input="$emit('input-text', $event.target.value)"> 元</div></template><script>const vm = new Vue({data() {return {price: 4588};},// 子组件向父组件传参时通过声明同名事件实现的components: {myInput: {template: "#myinput",props: ["my-price"],}},methods: {handle (value) {this.price = value;}},}).$mount("#app");</script>

不论我们是在输入框内改变子组件的值,还是在控制台中修改父组件的值,另外一个值都会随之而改变,这就是组件之间的双向传参。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号