158-vue04-元件&元件間通訊&插槽

Pinkman2k發表於2020-12-17

昨日回顧

1 購物車案例
2 v-model之lazy,number,trim
	-lazy:input框的資料繫結等失去焦點以後再變化
   	-number:input框中333dsda,變成333
    -trim:input去前後空格
3 與後端互動
	-jq的ajax
	-fetche
    -axios:get,put,post,delete..(帶頭,帶資料。。。)
    -跨域問題(如何處理)
4 與後端互動之fetche
5 與後端互動之axios
6 計算屬性之首字母大寫
	-函式當作變數來使用,有快取,在頁面上使用多次,只執行一次
7 通過計算屬性重寫過濾案例
	
8 元件定義
	-元件化開發:全域性元件,區域性元件
    -元件中有html,css,js:資料是獨立的
## vue的開源專案,在本地執行起來(別人開源了一個djago專案,跑在本地)
1 vue專案:安裝node(python直譯器)---》一路下一步--》(node:python3,npm:pip)
2 使用pycharm開啟vue專案
3 terminal中輸入:npm install  (安裝這個vue專案所有的依賴:pip3 install -r requ.txt)
4 命令列下執行:npm run serve / npm run start / npm run dev 等同於:python manage.py runserver

今日內容

1 定義區域性元件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>
<div id="box">
<child></child>
<child1></child1>
</div>
</body>
<script>

    Vue.component('child1', {
        template: `
            <div>
                <div style="background: red" @click="handleClick">我是頭部</div>
                <div v-if="isShow">顯示消失</div>
                <child></child>
            </div>
        `,
        methods: {
            handleClick() {
                console.log('我被點選了')
                this.isShow = !this.isShow
            }
        },
        data() {
            return {
                isShow: true
            }
        },
    })
    var vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
        methods: {
            handleClick() {
                console.log('根元件我被點選了')
            }
        },
        //區域性元件
        components:{
            child:{  //child元件名
                template:`
                <div @click="handleClick">{{name}}</div>
                `, //元件模板
                methods:{
                    handleClick(){
                        console.log('我被點了')
                    }
                },
                data(){
                    return{
                        name:'lqz'
                    }
                },
            },
        }
    })
</script>
</html>

2 元件編寫方式與Vue例項的區別

1 自定義元件需要有一個root element,一般包裹在一個div中,跟vue例項一樣
2 父子元件的data是無法共享
3 元件可以有data,methods,computed....,但是data 必須是一個函式
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>
<div id="box">
    <navbar></navbar>
    {{aa}}
</div>

</body>
<script>
    Vue.component('navbar', {
        template: `
        <div>
            <button @click="handleClick">返回</button>
            我是NavBar{{aa}}
            <button style="background: red">主頁</button>
            <br>
            <child></child>
        </div>
    `,
        methods: {
            handleClick() {
                console.log('nav nav')
            },
        },
        components: {
            child: {
                template: `<button>兒子</button>`,
            }
        },
        data() {
            return {
                aa: 'lqz'
            }
        },
    })
    var vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
        methods: {
            handleClick() {
                console.log('根元件我被點選了')
            }
        },
    })

</script>
</html>

3 元件通訊之父傳子通訊

1 父子通訊
2 在全域性元件上自定義屬性
	<navbar myname="lqz" age="18"></navbar>
3 在元件中獲取
	props: ['myname','age']  #myname=lqz   age=18
        
4 區分開這兩種賦值方式
     <navbar myname="lqz" age="18"></navbar>
     <navbar :myname="'ffff'" age="19"></navbar>
     <navbar :myname="name" age="19"></navbar>

3.1父傳子通訊

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>
<div id="box">
    <!--myname是自定義屬性-->
    <navbar myname="lqz" age="18"></navbar>
    <navbar :myname="'ffff'" age="19"></navbar>
</div>
</body>
<script>
    Vue.component('navbar', {
        template: `
        <div>
            <button @click="handleClick">返回</button>
            我是NavBar---{{age}}
            <button style="background: red">{{myname}}</button>
        </div>
    `,
        props: ['myname','age']
    })

    var vm = new Vue({
        el: '#box',
        data: {
            name: 'xxx',
        },
    })

</script>
</html>

3.2 屬性驗證

1 限制父傳子的變數型別
	  props: {
            myname:String,
            isshow:Boolean,
            varies:'' //傳遞,但不驗證型別
        }
2 父傳子時注意以下的區別
    <navbar myname="lqz" :isshow="isshow"></navbar>
    <navbar myname="lqz" :isshow="false"></navbar>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <!--myname是自定義屬性-->
<!--    <navbar myname="lqz" isshow="false"></navbar>-->
    <navbar myname="lqz" :isshow="isshow"></navbar>
    <navbar myname="lqz" :isshow="false"></navbar>

</div>


</body>
<script>
    Vue.component('navbar', {
        template: `
        <div>
            <button>返回</button>
            我是NavBar---{{isshow}}
            <button style="background: red">{{myname}}</button>
        </div>
    `,
        props: {
            myname:String,
            isshow:Boolean
        }
    })

    var vm = new Vue({
        el: '#box',
        data: {
            name: 'xxx',
            isshow:true,
        },
    })

</script>
</html>

4 元件通訊之子傳父通訊

1 通過事件實現:
	點選一下子元件,就會觸發父元件某個函式的執行
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
<navbar @myevent="handleClick"></navbar>
</div>
</body>
<script>
    Vue.component('navbar', {
        template: `
        <div>
            <button @click="handleNav">點我,觸發父元件的某個函式執行</button>
        </div>
    `,
        data(){
            return {
                name:'lqz'
            }
        },
        methods:{
            handleNav(){
                console.log('我是nav的函式,我執行了')
                this.$emit('myevent',100,this.name,99)
            }
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {
        },
        methods:{
            handleClick(ev,a,b){
                console.log('我是父元件的函式,我執行了')
                console.log(ev)
                console.log(a)
                console.log(b)
            }
        }


    })


</script>
</html>

4.2 小案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <child @myevent="handle"></child>
    <hr>
    {{name}}
</div>

</body>
<script>
    Vue.component('child', {
        template: `
        <div>
        <input type="text" v-model="mytext">
        <button @click="handleClick">點我</button>
        </div>
    `,
        data() {
            return {
                mytext: ''
            }
        },
        methods: {
            handleClick() {
                this.$emit('myevent', this.mytext)
            }
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {
            name: ''
        },
        methods: {
            handle(a) {
                this.name = a
            }
        }
    })
</script>
</html>

5 ref屬性(也可實現元件間通訊,子父,父子都可以使用)

ref放在標籤上,拿到的是原生節點
ref放在元件上,拿到的是元件物件,
通過這種方式實現子傳父(this.$refs.mychild.text)
通過這種方式實現父傳子(呼叫子元件方法傳引數)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <input type="text" ref="myref">

    <child ref="mychild"></child>
    <hr>
    <button @click="handleButton">點我</button>
</div>

</body>
<script>
    Vue.component('child', {
        template: `
        <div>
        <input type="text" v-model="mytext">
        <hr>
        我是子元件的input
        </div>
    `,
        data() {
            return {
                mytext: ''
            }
        },
        methods:{
            add(a){
                console.log('我是子元件的add方法')
                console.log(a)
                return '返回了'
            }
        }
    })

    var vm = new Vue({
        el: '#box',
        data: {
            name: 'asdf'
        },
        methods: {
            handle(a) {
                this.name = a
            },
            handleButton(){
                console.log(this.$refs.mychild.mytext)
                console.log(this.$refs.mychild.add(this.name))
            }
        }


    })


</script>
</html>

6 事件匯流排bus

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">

    <child1></child1>
    <hr>
    <child2></child2>

</div>

</body>
<script>

    //定義一個事件匯流排
    var bus=new Vue()


    //元件1
    Vue.component('child1', {
        template: `
        <div>
        <input type="text" v-model="text">
        <button @click="handleClick">點我傳遞資料到另一個元件</button>
        </div>
    `,
        data() {
            return {
                text: ''
            }
        },
        methods: {
            handleClick() {
                console.log(this.text)
                bus.$emit('suibian',this.text) //通過事件匯流排傳送
            }
        }
    })
    //元件2
    Vue.component('child2', {
        template: `
        <div>
        收到的訊息是:{{recv_text}}
        </div>
    `,
        data(){
            return {
                recv_text:''
            }
        },
        mounted(){//元件掛載(生命週期鉤子函式中的一個),開始監聽事件匯流排上的隨便
            bus.$on('suibian',(item)=>{
                console.log('收到了',item)
                this.recv_text=item
            })

        },
    })

    var vm = new Vue({
        el: '#box',
        data: {},

    })


</script>
</html>

7 動態元件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">

    <ul>
        <li @click="who='child1'">首頁</li>
        <li @click="who='child2'">商品</li>
        <li @click="who='child3'">訂單</li>
    </ul>
    <!--<component :is="who"></component>-->
    <keep-alive>
        <component :is="who"></component>
    </keep-alive>
</div>

</body>
<script>

    var vm = new Vue({
        el: '#box',
        data: {
            who: 'child1'
        },
        components: {
            child1: {
                template: `
                <div>我是首頁 
                <input type="text">
                </div>
                `,
            },
            child2: {
                template: `
                <div>我是商品 </div>
                `,
            },
            child3: {
                template: `
                <div>我是訂單 </div>
                `,
            }
        }
    })
</script>
</html>

8 slot插槽

8.1 基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <child1>
        <ul>
            <li v-for="i in 4">{{i}}</li>
        </ul>
    </child1>
    <hr>
    <child2></child2>
    <hr>
    <child3></child3>
</div>

</body>
<script>

    var vm = new Vue({
        el: '#box',
        data: {
            who: 'child1'
        },
        components: {
            child1: {
                template: `

                <div>


                <slot></slot>
                <hr>
                我是首頁

                <input type="text">

                </div>
                `,

            },
            child2: {
                template: `
                <div>我是商品 </div>
                `,

            },
            child3: {
                template: `
                <div>我是訂單 </div>
                `,

            }
        }

    })


</script>
</html>

8.2 插槽案例(一個元件通過插槽控制另一個元件的顯示隱藏)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <child1>
        <button @click="isShow=!isShow">點我隱藏child2</button>
    </child1>
    <hr>
    <child2 v-if="isShow"></child2>
</div>

</body>
<script>

    var vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
        components: {
            child1: {
                template: `

                <div>
                <slot></slot>
                </div>
                `,

            },
            child2: {
                template: `
                <div>
                 <ul>
                 <li v-for="i in 4">{{i}}</li>
                </ul>
                 </div>
                `,

            },
     }

    })


</script>
</html>

8.3 具名插槽(指定標籤放到元件的某個插槽中)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="js/vue.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <child1>
        <button @click="isShow=!isShow" slot="button1">點我隱藏child2</button>

        <div slot="div1">我是div</div>
    </child1>
    <hr>
    <child2 v-if="isShow"></child2>
</div>

</body>
<script>

    var vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
        components: {
            child1: {
                template: `

                <div>
                <slot name="button1"></slot>
                <hr>
                我是華麗的分割線
                <hr>
                <slot name="div1"></slot>
                </div>
                `,

            },
            child2: {
                template: `
                <div>
                 <ul>
                 <li v-for="i in 4">{{i}}</li>
                </ul>
                 </div>
                `,

            },
     }

    })


</script>
</html>

相關文章