搜尋
首頁web前端js教程分分鐘帶你玩Vue.js組件

分分鐘帶你玩Vue.js組件

Mar 25, 2017 am 11:18 AM
jsvue

元件簡介

元件系統是Vue.js其中一個重要的概念,它提供了一種抽象,讓我們可以使用獨立可重複使用的小元件來建立大型應用,任意類型的應用介面都可以抽象化為一個組件樹: 

分分鐘帶你玩Vue.js組件

那麼什麼是組件呢? 
元件可以擴充HTML元素,封裝可重複使用的HTML程式碼,我們可以將元件視為自訂的HTML元素。

元件的建立和註冊

基本步驟 
Vue.js的元件的使用有3個步驟:建立元件建構器、註冊元件和使用元件。 

分分鐘帶你玩Vue.js組件

下面的程式碼示範了這3個步驟:

<!DOCTYPE html>
<html>
 <body>
 <p id="app">
  <!-- 3. #app是Vue实例挂载的元素,应该在挂载元素范围内使用组件-->
  <my-component></my-component>
 </p>
 </body>
 <script src="js/vue.js"></script>
 <script>
 
 // 1.创建一个组件构造器
 var myComponent = Vue.extend({
  template: &#39;<p>This is my first component!</p>&#39;
 })
 
 // 2.注册组件,并指定组件的标签,组件的HTML标签为<my-component>
 Vue.component(&#39;my-component&#39;, myComponent)
 
 new Vue({
  el: &#39;#app&#39;
 });
 
 </script>
</html>

運作結果如下: 

分分鐘帶你玩Vue.js組件

可以看到,使用元件和使用普通的HTML元素沒什麼區別。

理解組件的創建和註冊 

我們用以下幾個步驟來理解組件的創建和註冊: 
1. Vue.extend()是Vue構造器的擴展,調用Vue.extend()創建的是一個組件構造器,而不是一個特定的組件實例。 
2. Vue.extend()建構器有一個選項對象,選項對象的template屬性用來定義元件要渲染的HTML。 
3. 使用Vue.component()註冊元件時,需提供2個參數,第1個參數時元件的標籤,第2個參數是元件建構器。 
4. Vue.component()方法內部會呼叫元件建構器,建立一個元件實例。 
5. 元件應該掛載到某個Vue實例下,否則它不會生效。

請注意第5點,以下程式碼在3個地方使用了my-component標籤,但只有#app1和#app2下的my-component標籤才發揮作用。

<!DOCTYPE html>
<html>
 <body>
 <p id="app1">
  <my-component></my-component>
 </p>
 
 <p id="app2">
  <my-component></my-component>
 </p>
 
 <!--该组件不会被渲染-->
 <my-component></my-component>
 </body>
 <script src="js/vue.js"></script>
 <script>
 var myComponent = Vue.extend({
  template: &#39;<p>This is a component!</p>&#39;
 })
 
 Vue.component(&#39;my-component&#39;, myComponent)
 
 var app1 = new Vue({
  el: &#39;#app1&#39;
 });
 
 var app2 = new Vue({
  el: &#39;#app2&#39;
 })
 </script>
</html>

分分鐘帶你玩Vue.js組件

全域註冊和局部註冊

呼叫Vue.component()註冊元件時,元件的註冊是全域的,這表示該元件可以在任意Vue範例下使用。 
如果不需要全域註冊,或是讓元件使用在其它元件內,可以用選項物件的components屬性實現局部註冊。

上面的範例可以改為局部註冊的方式:

<!DOCTYPE html>
<html>
 <body>
 <p id="app">
  <!-- 3. my-component只能在#app下使用-->
  <my-component></my-component>
 </p>
 </body>
 <script src="js/vue.js"></script>
 <script>
 // 1.创建一个组件构造器
 var myComponent = Vue.extend({
  template: &#39;<p>This is my first component!</p>&#39;
 })
 
 new Vue({
  el: &#39;#app&#39;,
  components: {
  // 2. 将myComponent组件注册到Vue实例下
  &#39;my-component&#39; : myComponent
  }
 });
 </script>
</html>
 
由于my-component组件是注册在#app元素对应的Vue实例下的,所以它不能在其它Vue实例下使用。
 
<p id="app2">
 <!-- 不能使用my-component组件,因为my-component是一个局部组件,它属于#app-->
 <my-component></my-component>
</p>
 
<script>
 new Vue({
 el: &#39;#app2&#39;
 });
 </script>

如果你這樣做了,瀏覽器會提示一個錯誤: 

分分鐘帶你玩Vue.js組件

父組件和子組件

我們可以在組件中定義並使用其他元件中定義並使用其他元件,這就構成了父子組件的關係。

<!DOCTYPE html>
<html>
 <body>
 <p id="app">
  <parent-component>
  </parent-component>
 </p>
 </body>
 <script src="js/vue.js"></script>
 <script>
 
 var Child = Vue.extend({
  template: &#39;<p>This is a child component!</p>&#39;
 })
 
 var Parent = Vue.extend({
  // 在Parent组件内使用<child-component>标签
  template :&#39;<p>This is a Parent component</p><child-component></child-component>&#39;,
  components: {
  // 局部注册Child组件,该组件只能在Parent组件内使用
  &#39;child-component&#39;: Child
  }
 })
 
 // 全局注册Parent组件
 Vue.component(&#39;parent-component&#39;, Parent)
 
 new Vue({
  el: &#39;#app&#39;
 })
 
 </script>
</html>

這段程式碼的運作結果如下: 

分分鐘帶你玩Vue.js組件

我們分幾個步驟來理解這段程式碼:

我們分幾個步驟來理解這段程式碼:

var Child = Vue.extend(…)定义一了个Child组件构造器
var Parent = Vue.extend(…)定义一个Parent组件构造器
components: { ‘child-component&#39;: Child },将Child组件注册到Parent组件,
并将Child组件的标签设置为child-component。
template :&#39;<p>This is a Parent component</p>
<child-component></child-component>&#39;,在Parent组件内以标签的形式使用Child组件。
Vue.component(‘parent-component&#39;, Parent) 全局注册Parent组件

在頁面中使用標籤渲染Parent元件的內容,同時Child元件的內容也被渲染出來

分分鐘帶你玩Vue.js組件

Child元件是在Parent元件中註冊的,它只能在Parent元件中使用,確切地說:子元件只能在父元件的template中使用。

請注意以下兩種子組件的使用方式是錯誤的: 

1. 以子標籤的形式在父組件中使用

<p id="app">
 <parent-component>
 <child-component></child-component>
 </parent-component>
</p>

   


為什麼這種方式無效呢?因為當子元件註冊到父元件時,Vue.js會編譯好父元件的模板,模板的內容已經決定了父元件將要渲染的HTML。 

parent-component相當於運行時,它的一些子標籤只會被當作普通的HTML來執行,child-component不是標準的HTML標籤,會被瀏覽器直接忽視掉。

2. 在父元件標籤外使用子元件

<p id="app">
 <parent-component>
 </parent-component>
 <child-component>
 </child-component>
</p>

執行這段程式碼,瀏覽器會提示以下錯誤 

分分鐘帶你玩Vue.js組件

元件註冊語法糖

以上元件註冊的方式有些繁瑣,Vue.js這個過程,提供了註冊語法糖。

使用Vue.component()直接建立和註冊元件:

// 全局注册,my-component1是标签名称
Vue.component(&#39;my-component1&#39;,{
 template: &#39;<p>This is the first component!</p>&#39;
})
 
var vm1 = new Vue({
 el: &#39;#app1&#39;
})

Vue.component()的第1個參數是標籤名稱,第2個參數是一個選項對象,使用選項對象的template屬性定義元件模板。 
使用這種方式,Vue在背後會自動地呼叫Vue.extend()。

在選項物件的components屬性中實現局部註冊:

var vm2 = new Vue({
 el: &#39;#app2&#39;,
 components: {
 // 局部注册,my-component2是标签名称
 &#39;my-component2&#39;: {
  template: &#39;<p>This is the second component!</p>&#39;
 },
 // 局部注册,my-component3是标签名称
 &#39;my-component3&#39;: {
  template: &#39;<p>This is the third component!</p>&#39;
 }
 }
})


使用script或template標籤

尽管语法糖简化了组件注册,但在template选项中拼接HTML元素比较麻烦,这也导致了HTML和JavaScript的高耦合性。 
庆幸的是,Vue.js提供了两种方式将定义在JavaScript中的HTML模板分离出来

使用script标签

<!DOCTYPE html>
<html>
 <body>
 <p id="app">
  <my-component></my-component>
 </p>
 
 <script type="text/x-template" id="myComponent">
  <p>This is a component!</p>
 </script>
 </body>
 <script src="js/vue.js"></script>
 <script>
 
 Vue.component(&#39;my-component&#39;,{
  template: &#39;#myComponent&#39;
 })
 
 new Vue({
  el: &#39;#app&#39;
 })
 
 </script>
</html>


template选项现在不再是HTML元素,而是一个id,Vue.js根据这个id查找对应的元素,然后将这个元素内的HTML作为模板进行编译。 

分分鐘帶你玩Vue.js組件

注意:使用script标签时,type指定为text/x-template,意在告诉浏览器这不是一段js脚本,浏览器在解析HTML文档时会忽略script标签内定义的内容。 

分分鐘帶你玩Vue.js組件

使用template标签 

如果使用template>标签,则不需要指定type属性。

<!DOCTYPE html>
<html>
 <head>
 <meta charset="UTF-8">
 <title></title>
 </head>
 <body>
 <p id="app">
  <my-component></my-component>
 </p>
 
 <template id="myComponent">
  <p>This is a component!</p>
 </template>
 </body>
 <script src="js/vue.js"></script>
 <script>
 
 Vue.component(&#39;my-component&#39;,{
  template: &#39;#myComponent&#39;
 })
 
 new Vue({
  el: &#39;#app&#39;
 })
 
 </script>
</html>

在理解了组件的创建和注册过程后,我建议使用script>或template>标签来定义组件的HTML模板。 
这使得HTML代码和JavaScript代码是分离的,便于阅读和维护。 
另外,在Vue.js中,可创建.vue后缀的文件,在.vue文件中定义组件,这个内容我会在后面的文章介绍

组件的el和data选项

传入Vue构造器的多数选项也可以用在 Vue.extend() 或Vue.component()中,不过有两个特例: data 和el。 
Vue.js规定:在定义组件的选项时,data和el选项必须使用函数。

下面的代码在执行时,浏览器会提出一个错误

Vue.component(&#39;my-component&#39;, {
 data: {
 a: 1
 }
})

   分分鐘帶你玩Vue.js組件

另外,如果data选项指向某个对象,这意味着所有的组件实例共用一个data。 
我们应当使用一个函数作为 data 选项,让这个函数返回一个新对象:

Vue.component(&#39;my-component&#39;, {
 data: function(){
 return {a : 1}
 }
})

  

使用props

组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。

props基础示例 
下面的代码定义了一个子组件my-component,在Vue实例中定义了data选项。

var vm = new Vue({
 el: &#39;#app&#39;,
 data: {
 name: &#39;keepfool&#39;,
 age: 28
 },
 components: {
 &#39;my-component&#39;: {
  template: &#39;#myComponent&#39;,
  props: [&#39;myName&#39;, &#39;myAge&#39;]
 }
 }
})

为了便于理解,你可以将这个Vue实例看作my-component的父组件。 
如果我们想使用父组件的数据,则必须先在子组件中定义props属性,也就是props: [‘myName', ‘myAge']这行代码。

定义子组件的HTML模板:

 <template id="myComponent">
 <table>
 <tr>
  <th colspan="2">
  子组件数据
  </th>
 </tr>
 <tr>
  <td>my name</td>
  <td>{{ myName }}</td>
 </tr>
 <tr>
  <td>my age</td>
  <td>{{ myAge }}</td>
 </tr>
 </table>
</template>

将父组件数据通过已定义好的props属性传递给子组件:

<p id="app">
 <my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
</p>

注意:在子组件中定义prop时,使用了camelCase命名法。由于HTML特性不区分大小写,camelCase的prop用于特性时,需要转为 kebab-case(短横线隔开)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。

这段程序的运行结果如下: 


分分鐘帶你玩Vue.js組件

父组件是如何将数据传给子组件的呢?相信看了下面这图,也许你就能很好地理解了。

分分鐘帶你玩Vue.js組件

在父组件中使用子组件时,通过以下语法将数据传递给子组件:

<child-component v-bind:子组件prop="父组件数据属性"></child-component>

prop的绑定类型

单向绑定 

既然父组件将数据传递给了子组件,那么如果子组件修改了数据,对父组件是否会有所影响呢? 
我们将子组件模板和页面HTML稍作更改:

<p id="app">
 
 <table>
  <tr>
   <th colspan="3">父组件数据</td>
  </tr>
  <tr>
   <td>name</td>
   <td>{{ name }}</td>
   <td><input type="text" v-model="name" /></td>
  </tr>
  <tr>
   <td>age</td>
   <td>{{ age }}</td>
   <td><input type="text" v-model="age" /></td>
  </tr>
 </table>
 
 <my-component v-bind:my-name="name" v-bind:my-age="age"></my-component>
</p>
 
<template id="myComponent">
 <table>
  <tr>
   <th colspan="3">子组件数据</td>
  </tr>
  <tr>
   <td>my name</td>
   <td>{{ myName }}</td>
   <td><input type="text" v-model="myName" /></td>
  </tr>
  <tr>
   <td>my age</td>
   <td>{{ myAge }}</td>
   <td><input type="text" v-model="myAge" /></td>
  </tr>
 </table>
</template>

运行这个页面,我们做两个小试验: 

1. 在页面上修改子组件的数据 

分分鐘帶你玩Vue.js組件

修改了子组件的数据,没有影响父组件的数据。 

2. 在页面上修改父组件的数据 

分分鐘帶你玩Vue.js組件

修改了父组件的数据,同时影响了子组件。 

prop默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意修改了父组件的状态

双向绑定 

可以使用.sync显式地指定双向绑定,这使得子组件的数据修改会回传给父组件。

分分鐘帶你玩Vue.js組件

单次绑定 

可以使用.once显式地指定单次绑定,单次绑定在建立之后不会同步之后的变化,这意味着即使父组件修改了数据,也不会传导给子组件。

分分鐘帶你玩Vue.js組件

示例

为了尽快消化这些知识,我们来做一个小示例吧。

<!DOCTYPE html>
<html>
 
 <head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" href="styles/demo.css" />
 </head>
 
 <body>
  <p id="app">
   <p id="searchBar">
    Search <input type="text" v-model="searchQuery" />
   </p>
   <simple-grid :data="gridData" :columns="gridColumns" :filter-key="searchQuery">
   </simple-grid>
  </p>
 
  <template id="grid-template">
   <table>
    <thead>
     <tr>
      <th v-for="col in columns">
       {{ col | capitalize}}
      </th>
     </tr>
    </thead>
    <tbody>
     <tr v-for="entry in data | filterBy filterKey">
      <td v-for="col in columns">
       {{entry[col]}}
      </td>
     </tr>
    </tbody>
   </table>
  </template>
 
 </body>
 <script src="js/vue.js"></script>
 <script>
  Vue.component(&#39;simple-grid&#39;, {
   template: &#39;#grid-template&#39;,
   props: {
    data: Array,
    columns: Array,
    filterKey: String
   }
  })
 
  var demo = new Vue({
   el: &#39;#app&#39;,
   data: {
    searchQuery: &#39;&#39;,
    gridColumns: [&#39;name&#39;, &#39;age&#39;, &#39;sex&#39;],
    gridData: [{
     name: &#39;Jack&#39;,
     age: 30,
     sex: &#39;Male&#39;
    }, {
     name: &#39;Bill&#39;,
     age: 26,
     sex: &#39;Male&#39;
    }, {
     name: &#39;Tracy&#39;,
     age: 22,
     sex: &#39;Female&#39;
    }, {
     name: &#39;Chris&#39;,
     age: 36,
     sex: &#39;Male&#39;
    }]
   }
  })
 </script>
 
</html>

   


除了以上介绍的知识点,这个示例还用到了两个知识点: 

1. prop验证

props: {
 data: Array,
 columns: Array,
 filterKey: String
}

   


这段代码表示:父组件传递过来的data和columns必须是Array类型,filterKey必须是字符串类型。 
更多prop验证的介绍,请参考:官方文档prop验证

2. filterBy过滤器 
可以根据指定的字符串过滤数据。 

分分鐘帶你玩Vue.js組件

总结

使用组件的前提是创建并注册组件,本篇文章详细介绍了组件从创建到使用的步骤,并介绍了几种不同的方式去创建和注册组件;然后介绍了组件的props选项,它用于将父组件的数据传递给子组件,最后我们用一个小的示例演示了这些知识点。

相关文章:

图文详解Vue.js开发环境快速搭建方法

使用vue.js编写好玩的拼图小游戏实例代码

使用require.js+vue开发微信上传图片组件方法

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。