1. 程式人生 > 實用技巧 >java開發兩年,連Spring的依賴注入的方式都搞不清楚,你工作可能有點懸!

java開發兩年,連Spring的依賴注入的方式都搞不清楚,你工作可能有點懸!

元件化開發

基本概念

vue.js 有兩大法寶,一個是資料驅動,另一個就是元件化

什麼叫元件化

所謂元件化,就是把頁面拆分成多個元件,每個元件依賴的 CSS、JS、模板、圖片等資源放在一起開發和維護
因為元件是資源獨立的,所以元件在系統內部可複用,元件和元件之間可以巢狀,如果專案比較複雜,可以極大簡化程式碼量,並且對後期的需求變更和維護也更加友好。

元件化思想

1.如果我們將一個頁面中所有的處理邏輯全部放在一起,處理起來就會變得非常複雜,而且不利於後續的管理以及擴充套件.
2.但如果,我們講一個頁面拆分成一個個小的功能塊,每個功能塊完成屬於自己這部分獨立的功能,那麼之後整個頁面的管理和維護就變得非常容易了.
參考:

元件基礎

認識元件

根元件

被掛載管理的元素塊就是一個根元件。在此根元件中可以巢狀多個子元件,根元件一般來說只需要一個

<body>
  <div id='app'>
  </div>

  <script src="vue.js"></script>
  <script>
    const app = new Vue({
      el:'#app',
    })
  </script>
</body>

子元件

子元件即是被巢狀在根元件中的元件,子元件可複用,並且資料都是相互獨立的。
子元件擁有根元件所擁有的所有屬性

元件宣告

元件的使用分三個步驟:

1.建立元件構造器
2.註冊元件
3.使用元件
1.呼叫Vue.extend()方法建立元件構造器
2.呼叫Vue.component()方法註冊元件
3.在Vue例項的作用範圍內使用元件

全域性元件

全域性元件會自動進行註冊,任何Vue的例項都能進行使用。
使用Vue.component("name",{})對其進行宣告並註冊。

<body>
    <div id='app'>
        <!-- 3.使用元件  -->
        <cpn></cpn>

    </div>

    <script src="vue.js"></script>
    
    <script>
        // 1.建立元件構造器物件
        const cpnC = Vue.extend({
            template: `
            <div>
                <h2>第一個元件</h2>
            </div>`
        })
        // 2.註冊元件 (全域性元件)
        Vue.component('cpn',cpnC);

        const app = new Vue({
            el:'#app',
        })
    </script>
</body>

區域性元件

區域性元件在Vue例項下使用components進行註冊,它只能在當前例項使用

<body>
    <div id='app'>
        <!-- 3.使用元件  -->
        <cpn></cpn>
    </div>

    <script src="vue.js"></script>
    
    <script>
	// 1.建立元件構造器物件
        const cpnC = Vue.extend({
            template:`
            <div>
                <h2>第一個元件</h2>
            </div>`
        })

        const app = new Vue({
            el:'#app',
            // 2.註冊元件(區域性元件)
            components: {
                cpn:cpnC,
            }
        })
    </script>
</body>

元件語法糖寫法

這種寫法居多

<body>
    <div id='app'>
        <cpn1></cpn1>
        <cpn2></cpn2>
    </div>

    <script src="vue.js"></script>
    
    <script>
        // 全域性語法糖
        Vue.component('cpn2',{
            template:`
                <div>
                    <h1>第一個元件</h1>
                </div>`
        })

        const app = new Vue({
            el:'#app',
            components: {
                // 區域性語法糖
                cpn1: {
                    template: `
                        <div>
                            <h1>第一個元件</h1>
                        </div>
                    `
                }
            }
        })
    </script>
</body>

元件模板抽離寫法

如果在定義元件時在template屬性中寫HTML程式碼,是不太友好的,你可以將模板抽離出來。
而且這個方法是用的最多
使用<template>標籤配合id屬性將其作為子元件模板:(以下抽離包括全域性和區域性)

<body>
    <div id='app'>
        <cpn1></cpn1>
        <cpn2></cpn2>
    </div>

    <template id='cpn1'>
        <div>
            <h1>元件抽離</h1>
        </div>
    </template>

    <template id='cpn2'>
        <div>
            <h1>元件抽離</h1>
        </div>
    </template>
    <script src="vue.js"></script>
    
    <script>
        // 全域性抽離寫法
        Vue.component('cpn1', {
            template:'#cpn1'
        })


        const app = new Vue({
            el:'#app',
            // 區域性抽離寫法
            components: {
                cpn2: {
                    template:'#cpn2',
                }
            }
        })
    </script>
</body>

子元件中的data

上面已經說過,子元件可以擁有data/methods/computed/watch/filter等物件。
但是需要注意的是子元件的data必須是一個函式,且必須返回一個Object
這是因為每個子元件是相互獨立的,每一個元件例項都有屬於元件的狀態
如果元件中的data是一個物件,那麼元件進行多次呼叫的時候就會互相影響。
所以子元件中的data必須是一個函式,因為函式呼叫時會重新申請記憶體,返回一個全新的Object

<body>
    <div id='app'>
        <cpn1></cpn1>
        <cpn2></cpn2>
    </div>

    <template id='cpn1'>
        <div>
            <h1>{{title}}</h1>
            <p>{{content}}</p>
        </div>
    </template>
		
    <template id='cpn2'>
        <div>
            <h1>{{title}}</h1>
            <p>{{content}}</p>
        </div>
    </template>
		
    <script src="vue.js"></script>
    
    <script>
	// 全域性註冊的元件
        Vue.component('cpn1', {
            template:'#cpn1',
	    // data必須是函式
            data() {
                return {
                    title:'我是標題11',
                    content:'我是內容11',
                }
            }
        })

        const app = new Vue({
            el: '#app',
	    // 區域性註冊的元件
            components: {
                cpn2: {
                    template: '#cpn2',
		    // data必須是函式
                    data() {
                        return {
                            title: '我是標題22',
                            content: '我是內容22',
                        }
                    }
                }
            }
        })
    </script>
</body>

元件通訊

通訊的意義

元件之間的通訊是十分有必要的,當Vue專案啟動後,父元件獲取到了一些資料,它將如何把這些資料分發到子元件上。
再比如,子元件上產生了一個新資料,它將如何把該資料交由父元件?

父傳子(props)

父元件向子元件傳遞資料時,則通過props進行傳遞。
接收值在父元件模板中採用 - 分割命名,在props中採用駝峰式,在子元件模板中進行使用時採用與props中同樣的命名方式
這是因為 - 分割命名方式不是Js的合法變數名,如果props中採用 - 來進行命名,子元件模板在使用時將查詢不到該變數名
總結一句話:如果props中採用了駝峰標識(例如:cInfo),那麼在父元件中使用必須用 - 來分割(例如:c-info

<body>
    <!-- 父元件模板 -->
    <div id='app'>
	<!-- 定義接收:一定要使用 - 來分割,不能使用駝峰標識 -->
        <cpn :c-message='message' :c-moves='moves' :c-info='info'></cpn>
    </div>


    <!-- 子元件模板 -->
    <template id='cpn'>
	<!-- 在子元件中就能使用 props 中接收的變數來渲染 -->
        <div>
            <h1>{{cMessage}}</h1>
            <ul>
                <li v-for='item in cMoves'>{{item}}</li>
            </ul>
            {{cMoves}}

            <h2>{{cInfo.name}}</h2>
        </div>
    </template>

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

    <script>
        // 父元件
        const app = new Vue({
            el: '#app',
            data: {
                message: '父元件的message',
                moves:['父元件1','父元件2','父元件3'],
                info: {
                    name:'hollow',
                    age:18,
                    height:1.88,
                }
            },
						
            components: {
                // 子元件
                cpn: {
                    template: '#cpn',
		    // 使用props來接收父元件傳過來的三個變數
                    props: {
		    // 接受收的時候可以隨便取名
                        cMessage: {
                            type:String,
                            default:'null',
                            required:true,
                        },
                        cMoves: {
                            type:Array,
                            default:[],
                        },
                        cInfo: {
                            type:Object,
                            default:{},
                        }
                    }
                }
            }
        })
    </script>
</body>

props中的其他引數

在上述中我在props中添加了其他引數

描述
type String、Array、Object等 定義接收的資料型別
default 預設值 如果定義了default,那麼接收到的就是預設值
required true/false 定義是否必須接收引數,不寫預設false

子傳父($emit)

1.在子元件中建立自定義函式
2.在自定義函式使用$emit,把需要修改或者傳遞的值或方法給父元件
3.父元件接收子元件傳遞過來的自定義函式
4.父元件通過接收的值或方法來進行下一步操作

<body>
    <div id='app'>
	<!-- 3.父元件接收子元件傳遞過來的自定義函式 -->
        <cpn @item-click='cpnClick'></cpn>
    </div>

    <template id='cpn'>
        <div>
	    <!-- 1.在子元件中建立自定義函式 -->
            <button v-for='item in categories' @click='btnClick(item)'>{{item.name}}</button>
        </div>
    </template>
    <script src="vue.js"></script>
    
    <script>
        const app = new Vue({
            el:'#app',
            components: {
                cpn: {
                    template:'#cpn',
                    data() {
                        return {
                            categories:[
                                {id:'aaa',name:'熱門推薦'},
                                {id:'bbb',name:'事件數碼'},
                                {id:'ccc',name:'家用家電'},
                                {id:'ddd',name:'電腦辦公'},
                            ]
                         }
                     },
                    methods: {
                        // 2.自定義函式:使用$emit,把需要修改或者傳遞的值或方法給父元件
                        btnClick(item) {
                            this.$emit('item-click',item);
                        }
                    }
                },
            },

	    // 4.父元件通過接收的值或方法來進行下一步操作
            methods: {
                cpnClick(item) {
                    console.log('cpnclick',item);
                }
            }
        })
    </script>
</body>

元件訪問

父訪問子($children)

有的時候我們想直接通過父元件拿到子元件這個物件,呼叫其下面的某一個方法,可以使用$children屬性完成操作。

<body>
    <div id='app'>
        <cpn></cpn>
        <button @click='btnClick'>app按鈕</button>
    </div>


    <template id='cpn'>
        <div>
            <h1>我是子元件</h1>
        </div>
    </template>
    <script src="vue.js"></script>

    <script>
        const app = new Vue({
            el: '#app',
            methods: {
                btnClick() {
		    // 使用$children獲取子元件的內容進行操作
                    console.log(this.$children);
                    this.$children[0].show();
                    console.log(this.$children[0].name);
                }
            },
            components: {
                cpn: {
                    template:'#cpn',
                    methods: {
                        show() {
                            console.log('showMessage');
                        }
                    },
                    data() {
                        return {
                            name:'我是子元件',
                        }
                    },
                }
            }
        })
    </script>
</body>

父訪問子(refs)

上述的訪問方法並不常用,因為父元件非常依賴索引值來訪問子元件。
使用$refs來訪問子元件就方便的多,我們需要給子元件取一個名字,再用父元件進行呼叫,這個是非常常用的手段。

<body>
    <div id='app'>
	<!-- 設定ref屬性 -->
        <cpn ref="ref1"></cpn>
        <button @click='btnClick'>app按鈕</button>
    </div>


    <template id='cpn'>
        <div>
            <h1>我是子元件</h1>
        </div>
    </template>
    <script src="vue.js"></script>

    <script>

        const app = new Vue({
            el: '#app',
            data: {

            },
            methods: {
                btnClick() {
		    // 通過 $refs 來獲取子元件的內容進行操作
                    this.$refs.ref1.show();
                    console.log(this.$refs.ref1.name);
                }
            },
            components: {
                cpn: {
                    template:'#cpn',
                    methods: {
                        show() {
                            console.log('showMessage');
                        }
                    },
                    data() {
                        return {
                            name:'我是子元件',
                        }
                    },
                }
            }
        })
    </script>
</body>

子訪問父(\(parent)和\)(root)

如果在子元件中想拿到父元件的物件,使用$parent即可,如果存在多層巢狀,它只會拿自己上一層。
如果存在三級或以上巢狀,可以直接使用$root來訪問根元件。與$parent使用相同,但是它是具體的一個物件,而並非Array。
下面程式碼我一起演示了$parent$root

<body>
    <!-- 根元件 -->
    <div id='app'>
        <cpn></cpn>
    </div>

    <!-- 子元件 -->
    <template id='cpn'>
	<!-- 子元件裡掛載子子元件 -->
        <ccpn></ccpn>
    </template>

    <!-- 子子元件 -->
    <template id='ccpn'>
        <div>
            <h2>我是子子元件</h2>
            <button @click='btnClick'>按鈕</button>
        </div>
    </template>
    <script src="vue.js"></script>
    
    <script>
        const app = new Vue({
	    // 根元件
            el: '#app',
            data: {
                message:'你好啊',
                name:'我是根的name',
            },
            components: {
		// 子元件
                cpn: {
                    template:'#cpn',
                    data() {
                        return {
                            name:'我是cpn的name',
                        }
                    },
		    // 子元件裡註冊元件,也就是子子元件
                    components: {
                        ccpn: {
                            template:'#ccpn',
                            methods: {
                                btnClick() {
                                    // 通過this.$parent和this.$root訪問父元件,也可以通過.的方式獲取變數和方法
                                    console.log('父元件是:',this.$parent);
                                    console.log(this.$parent.name);
                                    console.log('根元件是',this.$root);
                                    console.log(this.$root.name);
                                }
                            },
                        }
                    }
                }
            }
        })
    </script>
</body>