vue

為{幸葍}努か 提交于 2019-11-28 08:35:03

Vue

渐进式 JavaScript 框架

通过对框架的了解与运用程度,来决定其在整个项目中的应用范围,最终可以独立以框架方式完成整个web前端项目

 

一、走进Vue

1、what -- 什么是Vue

可以独立完成前后端分离式web项目的JavaScript框架

2、why -- 为什么要学习Vue

三大主流框架之一:Angular React Vue先进的前端设计模式:MVVM可以完全脱离服务器端,以前端代码复用的方式渲染整个页面:组件化开发

3、special -- 特点

单页面web应用数据驱动数据的双向绑定虚拟DOM

4、how -- 如何使用Vue

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

 

二、Vue实例

1、el:实例

new Vue({    el: '#app'})// 实例与页面挂载点一一对应// 一个页面中可以出现多个实例对应多个挂载点// 实例只操作挂载点内部内容

2、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实例直接或间接访问-->

3、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为事件提供实现体-->

4、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>

5、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>

6、delimiters:分隔符

<div id='app'>    ${ msg }</div><script>    new Vue({        el: '#app',        data: {            msg: 'message'        },        delimiters: ['${', '}']    })</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指令

1、文本相关指令

<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>

2、斗篷指令

<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><!-- 避免页面闪烁-->

3、属性指令

<!-- 给自定义全局属性绑定变量 --><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: 指令可以简写为 : -->

4、事件指令

<!-- v-on: 指令 简写 @ --><!-- 不传参事件绑定,但事件回调方法可以获取事件对象 --><p @click="fn"></p><!-- ()可以传入具体实参 --><p @click="fn()"></p><!-- ()情况下,事件对象应该显式传入 --><p @click="fn($event)"></p>

5、表单指令

<div id="app">    <!-- v-model针对于表单元素 -->    <form action="" method="get">        <!-- 1、双向绑定:服务于文本输入框 -->        <!-- 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>​        <!-- 2、单选框 -->        <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>​        <!-- 3、单一复选框 -->        <!-- v-model存储的值为true|false -->        <!-- 或者为自定义替换的值 -->        <div>            <input type="checkbox" v-model='sin_val' true-value="选中" false-value="未选中" />            {{ sin_val }}        </div>​        <!-- 4、多复选框 -->        <!-- 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>

6、条件指令

<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>

7、循环指令

<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>

8、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>

 

五、组件

  • 每一个组件都是一个vue实例

  • 每个组件均具有自身的模板template,根组件的模板就是挂载点

  • 每个组件模板只能拥有一个根标签

  • 子组件的数据具有作用域,以达到组件的复用

1、根组件

<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>

2、局部组件

<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>

3、全局组件

<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>

4、父组件传递数据给子组件

  • 通过绑定属性的方式进行数据传递

<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>

5、子组件传递数据给父组件

  • 通过发送事件请求的方式进行数据传递

<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>

6、父子组件实现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>

 

六、Vue-CLI 项目搭建

1、环境搭建

  • 安装node

官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/
  • 安装cnpm

npm install -g cnpm --registry=https://registry.npm.taobao.org
  • 安装脚手架

cnpm install -g @vue/cli      # 重建依赖指令是 cnpm install
  • 清空缓存处理

npm cache clean --force

2、项目的创建

  • 创建项目

vue create 项目名
// 要提前进入目标目录(项目应该创建在哪个目录下)
// 选择自定义方式创建项目,选取Router, Vuex插件
  • 启动/停止项目

npm run serve / ctrl+c
// 要提前进入项目根目录
  • 打包项目

npm run build
// 要在项目根目录下进行打包操作

3、认识项目

  • 项目目录

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>

4、项目功能

  • 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中,设置1天后过期
this.$cookie.set('val', this.val, 60*60*24)
// 获取cookie中val字段值
this.$cookie.get('val')
  • axios

// 安装 axios(ajax)的命令
// npm install axios --save
// 为项目配置全局axios
import Axios from 'axios'
Vue.prototype.$axios = Axios
let _this = this
this.$axios({
    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_templatefrom flask_cors import CORSapp = 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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!