用Vue中遇到的問題和處理方法(一)


   用Vue開發項目有一段時間,在實際項目中遇到一些問題,在里把問題記錄下來,並附上解決方案,給遇到同樣的問題的碼友提供一個解決思路吧:

  • 測試部拋出問題一:在Vue1.0路由vue-router中,當點擊菜單一個組件加載出來表格列表,輸入查詢條件查詢,當在單擊這個菜單后表格的數據沒有重置查詢條件和查詢結果.

        原因分析:Vue路由在頁面渲染一個組件后加載后,再加載這個組件,組件不會摧毀后在重新生成這個組件,不會重新觸發組件的生命周期中的方法.代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

    <title>learning vue</title>
</head>
<body>

<div id="app-container">
    <ul>
        <li v-for="item in $root.list">
            <a v-link="{ path: '/lang/' + item.id }">{{ item.name }}{{para}}{{params}}</a>
        </li>
    </ul>
    <router-view :params="params"></router-view>
</div>


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

<script>
    Vue.config.debug = true;
    Vue.use(VueRouter);
    var AppComponent = Vue.extend({
        data: function(){
            return {
                params:111,
                list: [
                    { id: '10001', name: 'C#', message: 'Hello C#' },
                    { id: '10002', name: 'Java', message: 'Hello Java.' },
                    { id: '10003', name: 'C++', message: 'Hello C++' },
                    { id: '10004', name: 'JavaScript', message: 'Hello JavaScript' }
                ]
            };
        }
    });
    var LangDetailComponent = Vue.extend({
        template: `<div><h1>{{ model.name }}</h1><p>{{ model.message }}</p></div>`,
        computed: {
            model: function(){
                var list = this.$root.list;
                var id = this.$route.params.id;
                for(var i = 0; i < list.length; i++){
                    if(list[i].id === id){
                        return list[i];
                    }
                }
            }
        },
        init:function () {
            alert("init");
        },
        created:function () {
            alert("created");
        },
        beforeCompile:function () {
            alert("beforeCompile");
        },
        compiled:function () {
            alert("compiled");
        },
        ready:function () {
            alert("ready");
        },
        attached:function () {
            alert("attached")
        },
        detached:function () {
            alert("detached")
        },
        beforeDestroy:function () {
            alert("beforeDestroy")
        },
        destroyed:function () {
            alert("destroyed")
        }

    });

    var router = new VueRouter();
    router.map({
        '/lang/:id': { component: LangDetailComponent }


    });
    router.start(AppComponent, '#app-container');
</script>

</body>
</html>

執行效果:

着三個路由都是同一個組件,但點擊其他的時候組件中的所有生命周期的方法都沒有調用,去vue-router的api上看沒有找到重新加載路由的配置配置項.

在實際開發中這個問題在兩個菜單共用一個組件,設置傳參來判斷加載不同的數據的情況下,會出現另一個ready方法不走導致數據顯示不真確.解決思路可以加監聽路由地址觸發ready事件.

而上面的解決方法是用v-if來重新加載組件,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">

    <title>learning vue</title>
</head>
<body>

<div id="app-container">
    <ul>
        <li v-for="item in $root.list">
            <a  href="javascript:void(0)" @click="click(item.path)">{{ item.name }}</a>
        </li>
    </ul>
    <router-view v-if="show"></router-view>
</div>


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

<script>
    Vue.config.debug = true;
    Vue.use(VueRouter);
    var AppComponent = Vue.extend({
        data: function(){
            return {
                show:true,
                list: [
                    { id: '10001', name: 'C#', message: 'Hello C#',path:"/lan"},
                    { id: '10002', name: 'Java', message: 'Hello Java.',path:"/lan1"},
                    { id: '10003', name: 'C++', message: 'Hello C++' ,path:"/lan2"},
                    { id: '10004', name: 'JavaScript', message: 'Hello JavaScript',path:"/lan3" }
                ]
            };
        },
        methods:{
            click:function (path) {
                debugger;
                if(window.location.hash.replace("#!","")==path){
                    this.show=false;
                    Vue.nextTick(function () {
                        this.show=true;
                    }.bind(this))
                }else{
                    this.$router.go({path:path});
                }
            }
        }
    });
    var LangDetailComponent = Vue.extend({
        template: `<div><h1>C#</h1><p>232323</p></div>`,
        computed: {
            model: function(){
                var list = this.$root.list;
                var id = this.$route.params.id;
                for(var i = 0; i < list.length; i++){
                    if(list[i].id === id){
                        return list[i];
                    }
                }
            }
        },
        init:function () {
            alert("init");
        },
        created:function () {
            alert("created");
        },
        beforeCompile:function () {
            alert("beforeCompile");
        },
        compiled:function () {
            alert("compiled");
        },
        ready:function () {
            alert("ready");
        },
        attached:function () {
            alert("attached")
        },
        detached:function () {
            alert("detached")
        },
        beforeDestroy:function () {
            alert("beforeDestroy")
        },
        destroyed:function () {
            alert("destroyed")
        }

    });
    var LangDetailComponent1 = Vue.extend({
        template: `<div><h1>Java</h1><p>Hello Java.</p></div>`,
        computed: {
            model: function(){
                var list = this.$root.list;
                var id = this.$route.params.id;
                for(var i = 0; i < list.length; i++){
                    if(list[i].id === id){
                        return list[i];
                    }
                }
            }
        },
        init:function () {
            alert("init");
        },
        created:function () {
            alert("created");
        },
        beforeCompile:function () {
            alert("beforeCompile");
        },
        compiled:function () {
            alert("compiled");
        },
        ready:function () {
            alert("ready");
        },
        attached:function () {
            alert("attached")
        },
        detached:function () {
            alert("detached")
        },
        beforeDestroy:function () {
            alert("beforeDestroy")
        },
        destroyed:function () {
            alert("destroyed")
        }

    });
    var LangDetailComponent2 = Vue.extend({
        template: `<div><h1>C++</h1><p>Hello C++</p></div>`,
        computed: {
            model: function(){
                var list = this.$root.list;
                var id = this.$route.params.id;
                for(var i = 0; i < list.length; i++){
                    if(list[i].id === id){
                        return list[i];
                    }
                }
            }
        },
        init:function () {
            alert("init");
        },
        created:function () {
            alert("created");
        },
        beforeCompile:function () {
            alert("beforeCompile");
        },
        compiled:function () {
            alert("compiled");
        },
        ready:function () {
            alert("ready");
        },
        attached:function () {
            alert("attached")
        },
        detached:function () {
            alert("detached")
        },
        beforeDestroy:function () {
            alert("beforeDestroy")
        },
        destroyed:function () {
            alert("destroyed")
        }

    });
    var LangDetailComponent3 = Vue.extend({
        template: `<div><h1>JavaScript</h1><p>Hello JavaScript</p></div>`,
        computed: {
            model: function(){
                var list = this.$root.list;
                var id = this.$route.params.id;
                for(var i = 0; i < list.length; i++){
                    if(list[i].id === id){
                        return list[i];
                    }
                }
            }
        },
        init:function () {
            alert("init");
        },
        created:function () {
            alert("created");
        },
        beforeCompile:function () {
            alert("beforeCompile");
        },
        compiled:function () {
            alert("compiled");
        },
        ready:function () {
            alert("ready");
        },
        attached:function () {
            alert("attached")
        },
        detached:function () {
            alert("detached")
        },
        beforeDestroy:function () {
            alert("beforeDestroy")
        },
        destroyed:function () {
            alert("destroyed")
        }

    });

    var router = new VueRouter();
    router.map({
        '/lan': { component: LangDetailComponent },
        '/lan1': { component: LangDetailComponent1 },
        '/lan2': { component: LangDetailComponent2 },
        '/lan3': { component: LangDetailComponent3 }
    });
    router.start(AppComponent, '#app-container');
</script>

</body>
</html>

效果是:

 

這樣在點相同的菜單,組件就重新加載,后面想優化每個菜單都加click,菜單很多話對頁面是性能消耗,下篇想用vue能不能用事件委托綁定單擊事件.暫時先寫到這里.

這里在多說一句,Vue的路由是hash路由,所以要回去路由地址可以用 window.location.hash.replace("#!","")來獲取.不知道hash路由的可以百度下,這里就不多說了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM