Vue 元件實戰

HammerZe發表於2022-04-17

Vue 元件

Vue 生命週期鉤子

axios實現資料請求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
<div id="app">
    <ul>
        <li v-for="film in films_list">
            <p>電影名字是:{{film.name}}</p>
            <img :src="film.poster" alt="" width="100px" height="150px">
            <p>電影介紹:{{film.synopsis}}</p>
        </li>
    </ul>

</div>

</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            films_list:[]
        },
        created() {
            axios.get('http://127.0.0.1:5000/films').then(res => {
                console.log(res.data)
                this.films_list=res.data.data.films
            })

        }
    })
</script>
</html>
from flask import Flask,make_response,jsonify

app=Flask(__name__)
@app.route('/films')
def films():
    import json
    with open('./movie.json','r',encoding='utf-8') as f:
        res=json.load(f)
    obj = make_response(jsonify(res))
    obj.headers['Access-Control-Allow-Origin']='*'
    return obj

if __name__ == '__main__':
    app.run()

image


計算屬性

我們可以通過計算屬性computed來快取計算,什麼意思呢?

在Vue中我們可以使用插值來展示資料,插值的普通函式,只要頁面一重新整理,函式就會重新運算,不管和函式有關沒關的值都會變,函式也會重新計算,導致執行效率降低;

那麼我們可以將自定義函式寫在computed中來控制,把函式當成屬性來用,呼叫不需要加括號,只有這個函式使用的屬性(變數)發生變化,函式才重新運算,這樣做可以減輕壓力,減少資源浪費

案例一:首字母大寫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>計算屬性</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <div style="font-size: 20px">
        輸入內容:<input type="text" v-model="mytext"> ----》 {{mytext.substring(0,1).toUpperCase()+mytext.substring(1)}}
        <br><br>
        <p>函式繫結(會重新整理頁面,也不推薦):<input type="text" :value="getName()"></p>
        <p>計算屬性(推薦):<input type="text" :value="getName1"></p>
    </div>

    <hr>
    <div style="font-size: 20px">
         <p>輸入內容:<input type="text" v-model="mytext1"> -----》{{mytext1}}</p>
    </div>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            mytext: '',
            mytext1:''
        },
        methods:{
            getName(){
                console.log('函式方式,我執行了')
                return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)
            }
        },
        //計算屬性
        computed:{
            getName1(){
                console.log('計算屬性,我執行了')
                return this.mytext.substring(0,1).toUpperCase()+this.mytext.substring(1)
            }

        }
    })
</script>
</html>

計算屬性

我們可以發現只有和屬性相關的才會列印,如果下面輸入內容只是列印了普通函式,就算函式內和mytext1不相關

案例二:過濾案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>過濾案例</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
</head>
<body>
<div id="box">
    <p><input type="text" v-model="myText"  placeholder="請輸入要篩選的內容:"></p>
    <ul>
        <li v-for="data in newList">{{data}}</li>
    </ul>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#box',
        data: {
            myText: '',
            dataList: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf'],
        },

        computed:{

            newList(){
                var _this = this
                console.log('執行了',_this)
                 var datalist2 = _this.dataList.filter(function(item){
                    console.log(_this)
                     return item.indexOf(_this.myText) > -1

                })
                return datalist2

            }
        }
    })
</script>
</html>

計算屬性2



監聽屬性

watch來設定監聽屬性,當mytext發生變化,就會執行和mytext繫結的函式方法

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

    <input type="text" v-model="mytext">--->{{mytext}}


</div>

</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            mytext: '',
        },
        watch: {
            // 只要mytext發生變化,就會執行該函式
            mytext: function () {
                console.log('我變化了,執行')

            }
        }


    })
</script>
</html>

監聽屬性


區域性元件

寫在components裡的是區域性元件,位置被限制,只能再區域性使用

比如如下例子中,Top元件只能在只能再id為app的標籤(div)內使用, Top元件內如果想再定義子元件,只能在該元件內的template中的div內使用

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

</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {},
        // 定義再這裡面的叫區域性元件,只能再區域性使用,只能再id為app的標籤內使用
        components: {
            'Top': {
                //寫在一個div裡
                template: `
                    <div>
                        <h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1>
                        <hr>
                        <button @click="handleC">點我看美女</button>
                    </div>
                `,
                //data是函式,可以設定返回值
                data() {
                    return {
                        name: "我是頭部"
                    }
                },
                methods: {
                    handleC() {
                        alert('美女')
                    }
                },
            },
            'Bottom': {
                template: `
                    <div>
                        <hr>
                        <h1 style="background: green;font-size: 60px;text-align: center">{{name}}</h1>

                    </div>
                `,
                data() {
                    return {
                        name: "我是尾部"
                    }
                },

            },

        },


    })
</script>
</html>

區域性元件


全域性元件

任意位置都可以使用但是也得是在vue例項託管的div範圍內

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


</div>

</body>
<script>
    // 定義全域性元件,任意位置都可以用,區域性內也可以使用
    Vue.component('top', {
            template: `
                <div>
                    <h1 style="background: pink;font-size: 60px;text-align: center">{{name}}</h1>
                    <hr>
                    <button @click="handleC">點我看美女</button>
                </div>
            `,
            data() {
                return {
                    name: "我是頭部"
                }
            },
            methods: {
                handleC() {
                    alert('美女')
                }
            },

        },)

    var vm = new Vue({
        el: '#app',
    })
</script>
</html>

全域性元件


元件通訊之父傳子

元件間data資料不同享,資料傳遞,如果我們想從父元件傳遞到子元件資料通過props自定義屬性來實現,比如如下例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    子元件顯示:<top :value="handleName"></top>
    <hr>
    父元件輸入內容:<input type="text" v-model="handleName">

</div>

</body>
<script>

    Vue.component('top', {
        template: ` <div>
                    <h1 style="background: tomato;font-size: 30px;text-align: center">{{value}}</h1>
                    </div>             `,
        // 必須叫props,陣列內放自定義屬性的名字
        props:{
            value: String,  // key是自定義屬性名,value是型別名,如果是別的型別就報錯
        },
        //props也可以寫成陣列的形式,不帶驗證功能
        // props:['value',]
    })
    var vm = new Vue({
        el: '#app',
        data: {
            handleName: ''
        }
    })
</script>
</html>

父傳子


元件通訊之子傳父

ps:Vue內建的物件都以$xx出現

我們可以通過自定義事件來實現子元件向父元件傳遞資料,在子元件中使用$emit('自定義事件',引數)來實現

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<top @myevent="handleRecv"></top>
    <hr>
  <h1 style="background: green;font-size: 60px;text-align: center">父元件</h1>
 <p>接收子元件傳送的資料:{{childText}}</p>
</div>

</body>
<script>

    Vue.component('top', {
        template: ` <div>
                        <h1 style="background: tomato;font-size: 60px;text-align: center">{{myheader}}</h1>
                        <p>子元件輸入內容:<input type="text" v-model="text"></p>
                        <p><button class="btn-success"  @click="handleSend">向父元件傳送資料</button></p>
                    </div>             `,
        data(){
            return {
                myheader:'子元件',
                text:''
            }
        },
        methods:{
            handleSend(){
                //myevent是自定義事件,代表將子元件的text交給myevent事件處理
                this.$emit('myevent',this.text)
            }
        }

    })
    var vm = new Vue({
        el: '#app',
        data: {
            //接收子元件的資料
            childText:''
        },
        methods: {
            handleRecv(data){
                // 接收引數,賦值給父元件的childText
                this.childText=data
            }
        }
    })
</script>
</html>

子傳父


ref屬性(元件間通訊)

普通標籤使用

普通標籤使用ref屬性,通過$refs獲取到的就是ref屬性所在的標籤,獲取到的是一個物件,如果多個標籤寫了ref屬性,那麼就將所有帶ref屬性的標籤弄到一個物件中,可以對html進行操作設定等,如下示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1 style="align-content: center">普通標籤使用ref</h1>
    <p><input type="text" ref="myinput"></p>
    <p><img src="" height="100px" width="100px" ref="myimg"></p>
    <p><button @click="handleC">點我</button>
</p>
</div>
</body>
<script>

    let vm = new Vue({
        el: '#app',
        data: {
             text:''
        },
        methods: {
            handleC(){
                console.log('我被點了')
                console.log(this.$refs)  // 是所有標籤寫了ref屬性的物件{myinput:真正的標籤,myimg:真正的標籤}
                console.log(this.$refs.myinput.value)
                //設定值
                this.$refs.myinput.value='HammerZe'
                //設定src屬性,顯示圖片
                this.$refs.myimg.src='https://img0.baidu.com/it/u=3608430476,1945954109&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=494'
            }
        }
    })
</script>
</html>

ref屬性1

元件使用ref屬性

ref屬性,如果放在元件上,就是當前元件物件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 元件使用ref屬性   -->
<top ref="top"></top>
<p>通訊:<input type="text" v-model="text"></p>
<p>父元件按鈕:<button @click="handleC">點我</button></p>
</p>
</div>
</body>
<script>
   Vue.component('top', {
        template: `
            <div>
                <h1>{{myheader}}</h1>
                <p>子元件按鈕:<button @click="handleC">點我看美女</button></p>
                <hr>
            </div>
        `,
        data() {
            return {
                myheader: "頭部",
            }
        },
        methods:{
            handleC(){
                alert("美女")
            }
        }



    },)
    let vm = new Vue({
        el: '#app',
        data: {
             text:''
        },
        methods: {
        //放在元件上
        handleC() {
             console.log(this.$refs.top) //VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
            /*子傳父*/
            // 父元件拿子元件的值
            console.log(this.$refs.top.myheader)
            // this.text=this.$refs.top.myheader
            // 父元件呼叫子元件的方法
            this.$refs.top.handleC()

            /*父傳子*/
            this.$refs.top.myheader=this.text
        }
        }
    })
</script>
</html>

ref屬性2

事件匯流排(不常用)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="box">
    <child1></child1>
    <child2></child2>
</div>
</body>
<script>
    var bus=new Vue() //new一個vue的例項,就是中央事件匯流排
    Vue.component('child1', {
        template: `<div>
            <input type="text" ref="mytext">
            <button @click="handleClick">點我</button>
        </div>`,
        methods:{
            handleClick(){
                bus.$emit('suibian',this.$refs.mytext.value) //釋出訊息,名字跟訂閱訊息名一致
            }
        }
    })
    Vue.component('child2', {
        template: `<div>
                    <div>收到的訊息 {{msg}}</div>
                    </div>`,
        data(){
            return {msg:''}
        },
        mounted(){
            //生命週期,當前元件dom建立完後悔執行
            console.log('當前元件dom建立完後悔執行')
            //訂閱訊息
            bus.$on('suibian',(item)=>{
                console.log('收到了',item)
                this.msg=item
            })
        }
    })
    var vm = new Vue({
        el: '#box',
        data: {},
        methods: {
            handleClick() {
                console.log(this)
                //this.$refs.mytext 獲取到input控制元件,取出value值
                console.log(this.$refs.mytext.value)
                console.log(this.$refs.mychild.text)
                // this.$refs.mychild.add()
                this.$refs.mychild.add('傳遞引數')

            }
        }

    })
</script>
</html>

動態元件和keep-alive

動態元件:實現點選不同的連線顯示不同的頁面,實現跳轉,使用component標籤,用is屬性繫結,指定哪個顯示哪個

keep-alive:通過keep-alive標籤實現元件不銷燬,保留原來輸入的內容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<style>
    #menu {
        font-size: 18px;
        font-weight: bold;
    }

    #menu li {
        text-decoration: none; /*去掉前面的圓點*/
        list-style: none;
        float: left;
        margin-right: 20px;

    }

</style>
<body>
<div id="app">
    <ul id="menu">
        <li @click="changeC('index')">首頁</li> &nbsp;
        <li @click="changeC('order')" >訂單</li>
        <li @click="changeC('good')">商品</li>
    </ul>


    <keep-alive>
        <component :is='who'></component>
    </keep-alive>


</div>

</body>
<script>
    //三個元件
    Vue.component('index', {
        template: `
            <div style="overflow:hidden;">
                <h1>首頁內容</h1>
            </div>
        `,
    },)
    //保留輸入的訂單資訊
    Vue.component('order', {
        template: `
            <div>
                <h1>訂單內容</h1>
                請輸入要查詢的訂單:<input type="text">
            </div>
        `,
    },)
    Vue.component('good', {
        template: `
            <div>
                <h1>商品內容</h1>
            </div>
        `,
    },)

    var vm = new Vue({
        el: '#app',
        data: {
            //預設顯示index
            who: 'index'

        },
        methods: {
            changeC(data) {
                this.who = data
            }
        }

    })
</script>
</html>

動態元件

相關文章