Vue

Vue

在咱們的大型項目開發的時候咱們每每都會採用先後端分離的方案,而咱們的前端通常都是採用Vue框架來實現先後端分離。那這樣咱們就不能不講一下Vue開發的優勢了:css

  • 先進的前端設計模式:MVVM
  • 能夠徹底脫離服務器端,以 前端代碼複用的方式渲染整個頁面:組件化開發
特色
  • 單頁面Web應用
  • 數據驅動
  • 數據的雙先綁定
  • 虛擬DOM

平時開發能夠直接使用js文件導入的形式使用Vue開發html

開發版本前端

生產版本vue

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

實例成員

  • eljava

    • 實例與頁面掛載點一一對應node

    • 一個頁面中能夠出現多個實例對應多個掛載點ios

    • 實例只操做掛載點內部內容ajax

  • datavue-router

    • data爲插值表達式中的變量提供數據

    • data中的數據能夠經過Vue實例直接或間接訪問

  • methods

    • methods爲事件提供實現體
  • computed

    • 一個變量依賴於多個變量
    • 當依賴的變量發生變化,便會觸發
  • watch:監聽

    • 用於監聽某個變量的變化
  • delimiters:分隔符

    • 當咱們的{{}}與其餘組件發生衝突時可使用這個來替換新的標識符

指令

  • 文本指令(數據須要在Vue中定義)

    • 插值表達式

      <p>{{ msg }}</p>

    • v-text(替換原文本)

      <p v-text='msg'>原文本</p>

    • v-html(替換原文本,而且解析html標籤)

    • v-once(只渲染一次)

  • 斗篷指令

    <div id="app">
        <p>{{ msg }}</p>
        <p>{{ msg }}</p>
        <p>{{ msg }}</p>
        <p>{{ msg }}</p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script type="text/javascript">
        new Vue({
            el: "#app",
            data: {
                msg: "message"
            }
        })
    </script>

    在這種狀況下回發生一個問題就是頁面是先加載後渲染數據的,因此你能夠看到先是一堆的{{ msg }}而後纔是渲染的數據。解決這個辦法有兩個方法

    • 將導入Vue.js的語句放在head裏

      <html>
          <head>
              <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
          </head>
          <body>
              <div id="app">
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
              </div>
          </body>
          <script type="text/javascript">
              new Vue({
                  el: "#app",
                  data: {
                      msg: "message"
                  }
              })
          </script>
      </html>
    • 經過斗篷指令

      <html>
          <head>
              <style type="text/css">
                  [v-cloak] { 
                      display: none;
                  }
              </style>
          </head>
          <body>
              <div id="app" v-cloak>
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
                  <p>{{ msg }}</p>
              </div>
          </body>
          <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
          <script type="text/javascript">
              new Vue({
                  el: "#app",
                  data: {
                      msg: "message"
                  }
              })
          </script>
      </html>
  • 屬性指令(屬性綁定變量)

    • 綁定屬性

      <p v-bind:abc="abc"></p>

    • 綁定類

      • 單類名綁定

        <p v-bind:class="c1"></p>

      • 多類名綁定

        <p v-bind:class="[c2, c3]"></p>

        控制每一個類樣式 {c4: true|false|var}

    • 綁定樣式

      • <div :style="div_style"></div>
      • <div :style="{width: '100px', height: '100px', backgroundColor: 'blue'}"></div>
  • 事件指令(綁定事件)

    v-on: 指令 簡寫 @
    不傳參事件綁定,但事件回調方法能夠獲取事件對象
    <p @click="fn"></p>
    參數能夠經過傳入具體實參
    <p @click="fn()"></p>
    方法函數須要參數並無傳入的狀況下,事件對象默認傳入(事件對象:$event)
    <p @click="fn()"></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>

組件

  • 每個組件都是一個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>

生命週期鉤子

  • 表示一個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已更新");
    }
    // 拿到需求 => 肯定鉤子函數 => 解決需求的邏輯代碼塊
})

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項目經常使用命令
  • 建立項目
vue create 項目名
  • 啓動/中止項目
npm run serve / ctrl+c
  • 打包項目
npm run build
三、Vue項目
  • 項目目錄
dist: 打包的項目目錄(打包後會生成)
node_modules: 項目依賴
public: 共用資源
src: 項目目標,書寫代碼的地方
    -- assets:資源
    -- components:組件
    -- views:視圖組件
    -- App.vue:根組件
    -- main.js: 入口js
    -- router.js: 路由文件
    -- store.js: 狀態庫文件
vue.config.js: 項目配置文件(沒有能夠本身新建)
  • 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-cookies
// 安裝cookie的命令
// npm install vue-cookies --save
// 爲項目配置全局vue-cookie
import VueCookies from 'vue-cookies'
// 將插件設置給Vue原型,做爲全局的屬性,在任何地方均可以經過this.$cookie進行訪問
Vue.prototype.$cookies = VueCookies
// 持久化存儲val的值到cookie中
this.$cookies.set('val', this.val, 300)
// 獲取cookie中val字段值
this.$cookies.get('val')
// 刪除cookie鍵值對
this.$cookies.remove('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()
相關文章
相關標籤/搜索