vue基礎筆記

Vue

漸進式 JavaScript 框架

經過對框架的瞭解與運用程度,來決定其在整個項目中的應用範圍,最終能夠獨立以框架方式完成整個web前端項目

1、走進Vue

一、what -- 什麼是Vue

能夠獨立完成先後端分離式web項目的JavaScript框架

二、why -- 爲何要學習Vue

三大主流框架之一:Angular React Vue
先進的前端設計模式:MVVM
能夠徹底脫離服務器端,之前端代碼複用的方式渲染整個頁面:組件化開發

三、special -- 特色

單頁面web應用
數據驅動
數據的雙向綁定
虛擬DOM

四、how -- 如何使用Vue

<div id="app">
    {{ }}
</div>
<script src="js/vue.min.js"></script>
<script>
    new Vue({
        el: '#app'
    })
</script>

2、Vue實例

一、el:實例

new Vue({
    el: '#app'
})
// 實例與頁面掛載點一一對應
// 一個頁面中能夠出現多個實例對應多個掛載點
// 實例只操做掛載點內部內容

二、data:數據

<div id='app'>
    {{ msg }}
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            msg: '數據',
        }
    })
    console.log(app.$data.msg);
    console.log(app.msg);
</script>
<!-- data爲插件表達式中的變量提供數據 -->
<!-- data中的數據能夠經過Vue實例直接或間接訪問-->

三、methods:方法

<style>
    .box { background-color: orange }
</style>
<div id='app'>
    <p class="box" v-on:click="pClick">測試</p>
    <p class="box" v-on:mouseover="pOver">測試</p>
</div>
<script>
    var app = new Vue({
        el: '#app',
        methods: {
            pClick () {
                // 點擊測試
            },
            pOver () {
                // 懸浮測試
            }
        }
    })
</script>
<!-- 瞭解v-on:爲事件綁定的指令 -->
<!-- methods爲事件提供實現體-->

四、computed:計算

<div id="app">
    <input type="text" v-model="a">
    <input type="text" v-model="b">
    <div>
        {{ c }}
    </div>
</div>

<script>
    // 一個變量依賴於多個變量
    new Vue({
        el: "#app",
        data: {
            a: "",
            b: "",
        },
        computed: {
            c: function() {
                // this表明該vue實例
                return this.a + this.b;
            }
        }
    })
</script>

五、watch:監聽

<div id="app">
    <input type="text" v-model="ab">
    <div>
        {{ a }}
        {{ b }}
    </div>
</div>

<script>
    // 多個變量依賴於一個變量
    new Vue({
        el: "#app",
        data: {
            ab: "",
            a: "",
            b: "",
        },
        watch: {
            ab: function() {
                // 邏輯根據需求而定
                this.a = this.ab[0];
                this.b = this.ab[1];
            }
        }
    })
</script>

六、delimiters:分隔符

<div id='app'>
    ${ msg }
</div>
<script>
    new Vue({
        el: '#app',
        data: {
            msg: 'message'
        },
        delimiters: ['${', '}']
    })
</script>

3、生命週期鉤子

  • 表示一個vue實例從建立到銷燬的這個過程,將這個過程的一些時間節點賦予了對應的鉤子函數
  • 鉤子函數: 知足特色條件被回調的方法
new Vue({
    el: "#app",
    data: {
        msg: "message"
    },
    beforeCreate () {
        console.log("實例剛剛建立");
        console.log(this.msg);
                    
    },
    created () {
        console.log("實例建立成功, data, methods已擁有");
        console.log(this.msg);
    },
    mounted () {
        console.log("頁面已被vue實例渲染, data, methods已更新");
    }
    // 拿到需求 => 肯定鉤子函數 => 解決需求的邏輯代碼塊
})

4、Vue指令

一、文本相關指令

<div id="app">
    <!-- 插值表達式 -->
    <p>{{ msg }}</p>
    <!-- eg:原文本會被msg替換 -->
    <p v-text='msg'>原文本</p>
    <!-- 能夠解析帶html標籤的文本信息 -->
    <p v-html='msg'></p>
    <!-- v-once控制的標籤只能被賦值一次 -->
    <p v-once>{{ msg }}</p>
</div>
<script type="text/javascript">
    // 指令: 出如今html標籤中能夠被vue解析處理的全局屬性
    new Vue({
        el: "#app",
        data: {
            msg: "message"
        }
    })
</script>

二、斗篷指令

<style type="text/css">
    [v-cloak] { display: none; }
</style>
<div id="app" v-cloak>
    {{ msg }}
</div>
<script src="js/vue.min.js"></script>
<script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
            msg: "message"
        }
    })
</script>
<!-- 避免頁面閃爍-->

三、屬性指令

<!-- 給自定義全局屬性綁定變量 -->
<p v-bind:abc="abc"></p>
<!-- 以原字符串形式綁定全局屬性 -->
<p v-bind:title="'abc'"></p>

<!-- 單類名綁定 -->
<p v-bind:class="c1"></p>
<!-- 多類名綁定 -->
<p v-bind:class="[c2, c3]"></p>
<!-- 類名狀態綁定 -->
<p v-bind:class="{c4: true|false|var}"></p>
<!-- 多類名狀態綁定 -->
<p v-bind:class="[{c5: true}, {c6: flase}]"></p>

<!-- 樣式綁定 -->
<div :style="div_style"></div>
<div :style="{width: '100px', height: '100px', backgroundColor: 'blue'}"></div>
<script type="text/javascript">
    new Vue({
        el:"#app",
        data: {
            abc: "abc",
            c1: "p1",
            c2: "p2",
            c3: "p3",
            div_style: {
                width: "200px",
                height: "200px",
                backgroundColor: "cyan"
            }
        }
    })
</script>
<!-- v-bind: 指令能夠簡寫爲 : -->

四、事件指令

<!-- v-on: 指令 簡寫 @ -->
<!-- 不傳參事件綁定,但事件回調方法能夠獲取事件對象 -->
<p @click="fn"></p>
<!-- ()能夠傳入具體實參 -->
<p @click="fn()"></p>
<!-- ()狀況下,事件對象應該顯式傳入 -->
<p @click="fn($event)"></p>

五、表單指令

<div id="app">
    <!-- v-model針對於表單元素 -->
    <form action="" method="get">
        <!-- 一、雙向綁定:服務於文本輸入框 -->
        <!-- v-model存儲的值爲輸入框的value值 -->
        <div>
            <input type="text" name="usr" v-model="in_val">
            <input type="password" name="ps" v-model="in_val" >
            <textarea name="info" v-model="in_val"></textarea>
        </div>

        <!-- 二、單選框 -->
        <div>
            <!-- 單選框是以name進行分組,同組中只能發生單選 -->
            <!-- v-model存儲的值爲單選框的value值 -->
            男:<input type="radio" name="sex" value="男" v-model="ra_val">
            女:<input type="radio" name="sex" value="女" v-model="ra_val">
            {{ ra_val }}
        </div>

        <!-- 三、單一複選框 -->
        <!-- v-model存儲的值爲true|false -->
        <!-- 或者爲自定義替換的值 -->
        <div>
            <input type="checkbox" v-model='sin_val' true-value="選中" false-value="未選中" />
            {{ sin_val }}
        </div>

        <!-- 四、多複選框 -->
        <!-- v-model存儲的值爲存儲值多複選框value的數組 -->
        <div>
            <input type="checkbox" value="喜愛男的" name="cless" v-model='more_val' />
            <input type="checkbox" value="喜愛女的" name="cless" v-model='more_val' />
            <input type="checkbox" value="不挑" name="cless" v-model='more_val' />
            {{ more_val }}
        </div>
    </form>
</div>

<script type="text/javascript">
    new Vue({
        el: '#app',
        data: {
            in_val: '',
            // 默認值能夠決定單選框默認選項
            ra_val: '男',
            // 默認值爲true,單一複選框爲選中,反之false爲不選中
            sin_val: '',
            // 數組中存在的值對應的複選框默認爲選中狀態
            more_val: ['喜愛女的','不挑']
        }
    })
</script>

六、條件指令

<div id="app">
    <button @click="toggle">顯隱切換</button>
    <!-- v-if -->
    <div class="box r" v-if="isShow"></div>
    <!-- v-show -->
    <div class="box o" v-show="isShow"></div>
    <!-- 1.條件渲染的值爲true|false -->
    <!-- 2.true表明標籤顯示方式渲染 -->
    <!-- 3.false v-if不渲染到頁面,v-show以display:none渲染到頁面,但也不會顯示 -->

    <!-- v-if v-else-if v-else 案例 -->
    <ul>
        <li @mouseover="changeWrap(0)">red</li>
        <li @mouseover="changeWrap(1)">green</li>
        <li @mouseover="changeWrap(2)">blue</li>
    </ul>
    <!-- red頁面邏輯結構 -->
    <div class="wrap red" v-if="tag == 0" key="0">...</div>
    <!-- green頁面邏輯結構 -->
    <div class="wrap green" v-else-if="tag == 1" key="1">...</div>
    <!-- blue頁面邏輯結構 -->
    <div class="wrap blue" v-else key="2">...</div>
    <!-- v-if相關分支操做,在未顯示狀況下,是不會被渲染到頁面中 -->
    <!-- 經過key全局屬性操做後,渲染過的分支會創建key對應的緩存,提升下一次渲染速度 -->

    <!-- v-show 案例 -->
    <ul>
        <li @mouseover="changeMain(0)">red</li>
        <li @mouseover="changeMain(1)">green</li>
        <li @mouseover="changeMain(2)">blue</li>
    </ul>
    <!-- red頁面邏輯結構 -->
    <div class="main red" v-show="whoShow(0)">...</div>
    <!-- green頁面邏輯結構 -->
    <div class="main green" v-show="whoShow(1)">...</div>
    <!-- blue頁面邏輯結構 -->
    <div class="main blue" v-show="whoShow(2)">...</div>
</div>
<script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
            isShow: false,
            tag: 0,
            flag: 0
        },
        methods: {
            toggle () {
                this.isShow = !this.isShow;
            },
            changeWrap (num) {
                this.tag = num;
            },
            changeMain (num) {
                // this.flag num
                this.flag = num;
            },
            whoShow (num) {
                // this.flag num
                return this.flag == num;
            }
        }
    })
</script>

七、循環指令

<div id="app">
    <h1>{{ msg }}</h1>
    <!-- v-for="item in items" -->
    <!-- 遍歷的對象: 數組[] 對象(字典){} -->
    <ul>
        <li>{{ list[0] }}</li>
        <li>{{ list[1] }}</li>
        <li>{{ list[2] }}</li>
        <li>{{ list[3] }}</li>
        <li>{{ list[4] }}</li>
    </ul>

    <!-- n爲遍歷的元素值 -->
    <ul>
        <li v-for="n in list">{{ n }}</li>
    </ul>

    <!-- 通常列表渲染須要創建緩存 -->
    <!-- 列表渲染是循環,須要賦值變量給key,使用key須要v-bind:處理 -->
    <!-- v-for變量數組[]時,接收兩個值時,第一個爲元素值,第二個爲元素索引 -->
    <ul>
        <li v-for="(n, i) in list" :key="i">value:{{ n }} | index: {{ i }}</li>
    </ul>

    <ul>
        <li>{{ dic['name'] }}</li>
        <li>{{ dic.age }}</li>
        <li>{{ dic.gender }}</li>
    </ul>

    <!-- v-for變量對象{}時,接收三個值時,第一個爲元素值,第二個爲元素鍵,第三個爲元素索引 -->
    <ul>
        <li v-for="(v, k, i) in dic" :key="k">value:{{ v }} | key:{{ k }} | index: {{ i }}</li>
    </ul>


    <!-- 遍歷的嵌套 -->
    <div v-for="(person, index) in persons" :key="index" style="height: 21px;">
        <div v-for="(v, k) in person" :key="k" style="float: left;">{{ k }} : {{ v }}&nbsp;&nbsp;&nbsp;</div>
    </div>
</div>
<script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
            msg: "列表渲染",
            list: [1, 2, 3, 4, 5],
            dic: {
                name: 'zero',
                age: 88888,
                gender: 'god'
            },
            persons: [
                {name: "zero", age: 8},
                {name: "egon", age: 78},
                {name: "liuXX", age: 77},
                {name: "yXX", age: 38}
            ]
        }
    })
</script>

八、todolist案例

<div id="app">
    <div>
        <input type="text" v-model="val">
        <button type="button" @click="submitMsg">提交</button>
    </div>
    <ul>
        <li v-for="(v, i) in list" :key="i" @click="removeMsg(i)">{{ v }}</li>
    </ul>
    {{ list }}
</div>
<script type="text/javascript">
    new Vue({
        el: "#app",
        data: {
            val: "",
            list: []
        },
        methods: {
            submitMsg () {
                if (this.val) {
                    this.list.push(this.val);
                    this.val = ""
                }
            },
            removeMsg(index) {
                this.list.splice(index, 1)
            }
        }
    })
</script>

5、組件

  • 每個組件都是一個vue實例
  • 每一個組件均具備自身的模板template,根組件的模板就是掛載點
  • 每一個組件模板只能擁有一個根標籤
  • 子組件的數據具備做用域,以達到組件的複用

一、根組件

<div id="app">
    <h1>{{ msg }}</h1>
</div>
<script type="text/javascript">
    // 經過new Vue建立的實例就是根組件(實例與組件一一對應,一個實例就是一個組件)
    // 每一個組件組件均擁有模板,template
    var app = new Vue({
        // 根組件的模板就是掛載點
        el: "#app",
        data : {
            msg: "根組件"
        },
        // 模板: 由""包裹的html代碼塊,出如今組件的內部,賦值給組件的$template變量
        // 顯式書寫模塊,就會替換掛載點,但根組件必須擁有掛載點
        template: "<div>顯式模板</div>"
    })
    // app.$template
</script>

二、局部組件

<div id="app">
    <local-tag></local-tag>
    <local-tag></local-tag>
</div>
<script>
    var localTag = {
        data () {
            return {
                count: 0
            }
        },
        template: '<button @click="btnAction">局部{{ count }}</button>',
        methods: {
            btnAction () {
                this.count ++
            }
        }
    }
    new Vue({
        el: "#app",
        components: {
            'local-tag': localTag
        }
    })
</script>

三、全局組件

<div id="app">
    <global-tag></global-tag>
    <global-tag></global-tag>
</div>
<script>
    Vue.component('global-tag', {
        data () {
            return {
                count: 0
            }
        },
        template: '<button @click="btnAction">全局{{ count }}</button>',
        methods: {
            btnAction () {
                this.count ++
            }
        }
    })
    new Vue({
        el: "#app"
    })
</script>

四、父組件傳遞數據給子組件

  • 經過綁定屬性的方式進行數據傳遞
<div id="app">
    <global-tag :sup_data1='sup_data1' :supData2='sup_data2'></global-tag>
</div>
<script type="text/javascript">
    Vue.component('global-tag', {
        props:['sup_data1', 'supdata2'],
        template: '<div>{{ sup_data1 }} {{ supdata2 }}</div>'
    })
    new Vue({
        el: '#app',
        data: {
            sup_data1: '數據1',
            sup_data2: '數據2'
        }
    })
</script>

五、子組件傳遞數據給父組件

  • 經過發送事件請求的方式進行數據傳遞
<div id="app">
    <global-tag @send_action='receiveAction'></global-tag>
</div>
<script type="text/javascript">
    Vue.component('global-tag', {
        data () {
            return {
                sub_data1: "數據1",
                sub_data2: '數據2'
            }
        },
        template: '<div @click="clickAction">發生</div>',
        methods: {
            clickAction () {
                this.$emit('send_action', this.sub_data1, this.sub_data2)
            }
        }
    })
    new Vue({
        el: '#app',
        methods: {
            receiveAction (v1, v2) {
                console.log(v1, v2)
            }
        }
    })
</script>

六、父子組件實現todoList

<div id="app">
    <div>
        <input type="text" v-model="val">
        <button type="button" @click="submitMsg">提交</button>
    </div>
    <ul>
        <!-- <li v-for="(v, i) in list" :key="i" @click="removeMsg(i)">{{ v }}</li> -->
        <todo-list v-for="(v, i) in list" :key="i" :v="v" :i="i" @delect_action="delect_action"></todo-list>
    </ul>
</div>
<script type="text/javascript">
    Vue.component("todo-list", {
        template: "<li @click='delect_action'><span>第{{ i + 1 }}條: </span><span>{{ v }}</span></li>",
        props: ['v', 'i'],
        methods: {
            delect_action () {
                this.$emit("delect_action", this.i)
            }
        }
    })
    
    new Vue({
        el: "#app",
        data: {
            val: "",
            list: []
        },
        methods: {
            submitMsg () {
                // 往list中添加input框中的value
                if (this.val) {
                    this.list.push(this.val);
                    this.val = ""
                }
            },
            delect_action(index) {
                this.list.splice(index, 1)
            }
        }
    })
</script>

6、Vue-CLI 項目搭建

一、環境搭建

  • 安裝node
官網下載安裝包,傻瓜式安裝:https://nodejs.org/zh-cn/
  • 安裝cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 安裝腳手架
cnpm install -g @vue/cli
  • 清空緩存處理
npm cache clean --force

二、項目的建立

  • 建立項目
vue creat 項目名
// 要提早進入目標目錄(項目應該建立在哪一個目錄下)
// 選擇自定義方式建立項目,選取Router, Vuex插件
  • 啓動/中止項目
npm run serve / ctrl+c
// 要提早進入項目根目錄
  • 打包項目
npm run build
// 要在項目根目錄下進行打包操做

三、認識項目

  • 項目目錄
dist: 打包的項目目錄(打包後會生成)
node_modules: 項目依賴
public: 共用資源
src: 項目目標,書寫代碼的地方
    -- assets:資源
    -- components:組件
    -- views:視圖組件
    -- App.vue:根組件
    -- main.js: 入口js
    -- router.js: 路由文件
    -- store.js: 狀態庫文件
vue.config.js: 項目配置文件(沒有能夠本身新建)
  • 配置文件:vue.config.js
module.exports={
    devServer: {
        port: 8888
    }
}
// 修改端口,選作
  • main.js
new Vue({
    el: "#app",
    router: router,
    store: store,
    render: function (h) {
        return h(App)
    }
})
  • .vue文件
<template>
    <!-- 模板區域 -->
</template>
<script>
    // 邏輯代碼區域
    // 該語法和script綁定出現
    export default {
        
    }
</script>
<style scoped>
    /* 樣式區域 */
    /* scoped表示這裏的樣式只適用於組件內部, scoped與style綁定出現 */
</style>

四、項目功能

  • vue-router
{
    path: '/',
    name: 'home',
    // 路由的重定向
    redirect: '/home'
}

{
    // 一級路由, 在根組件中被渲染, 替換根組件的<router-view/>標籤
    path: '/one-view',
    name: 'one',
    component: () => import('./views/OneView.vue')
}

{
    // 多級路由, 在根組件中被渲染, 替換根組件的<router-view/>標籤
    path: '/one-view/one-detail',
    component: () => import('./views/OneDetail.vue'),
    // 子路由, 在所屬路由指向的組件中被渲染, 替換該組件(OneDetail)的<router-view/>標籤
    children: [{
        path: 'show',
        component: () => import('./components/OneShow.vue')
    }]
}
<!-- router-link渲染爲a標籤 -->
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link :to="{name: 'one'}">One</router-link> |

<!-- 爲路由渲染的組件佔位 -->
<router-view />
a.router-link-exact-active {
    color: #42b983;
}
// router的邏輯轉跳
this.$router.push('/one-view')

// router採用history方式訪問上一級
this.$router.go(-1)
  • vuex
// 在任何一個組件中,都可以經過this.$store.state.msg訪問msg的數據
// state永遠只能擁有一種狀態值
state: {
    msg: "狀態管理器"
},
// 讓state擁有多個狀態值
mutations: {
    // 在一個一個組件中,都可以經過this.$store.commit('setMsg', new_msg)來修改state中的msg
    setMsg(state, new_msg) {
        state.msg = new_msg
    }
},
// 讓mutations擁有多個狀態值
actions: {

}
  • vue-cookie
// 安裝cookie的命令
// npm install vue-cookie --save
// 爲項目配置全局vue-cookie
import VueCookie from 'vue-cookie'
// 將插件設置給Vue原型,做爲全局的屬性,在任何地方均可以經過this.$cookie進行訪問
Vue.prototype.$cookie = VueCookie
// 持久化存儲val的值到cookie中
this.$cookie.set('val', this.val)
// 獲取cookie中val字段值
this.$cookie.get('val')
  • axios
// 安裝 axios(ajax)的命令
// npm install axios--save
// 爲項目配置全局axios
import Axios from 'axios'
Vue.prototype.$ajax = Axios
let _this = this
this.$ajax({
    method: 'post',
    url: 'http://127.0.0.1:5000/loginAction',
    params: {
        usr: this.usr,
        ps: this.ps
    }
}).then(function(res) {
    // this表明的是回調then這個方法的調用者(axios插件),也就是發生了this的重指向
    // 要更新頁面的title變量,title屬於vue實例
    // res爲回調的對象,該對象的data屬性就是後臺返回的數據
    _this.title = res.data
}).catch(function(err) {
    window.console.log(err)
})
# 用pycharm啓動該文件模擬後臺
from flask import Flask, request, render_template
from flask_cors import CORS
app = Flask(__name__)
CORS(app, supports_credentials=True)

@app.route('/')
def index():
    return "<h1>主頁</h1>"

@app.route('/loginAction', methods=['GET', 'POST'])
def test_action():
    # print(request.args)
    # print(request.form)
    # print(request.values)
    usr = request.args['usr']
    ps = request.args['ps']
    if usr != 'abc' or ps != '123':
        return 'login failed'
    return 'login success'


if __name__ == '__main__':
    app.run()
相關文章
相關標籤/搜索