Python 测开27期 - 柒柒 - Vue笔记

VUE 环境安装

VUE 脚手架工具

  • 用于快速生成 Vue 项目基础架构
  • 安装 vue-cli
    • npm install -g @vue/cli
    • -g 代 表全局安装,如果不加 -g ,会在当前目录安装
  • 验证环境
    • vue --version

VUE项目创建

  • 命令行创建 vue create project_name
  • 命令开启前端项目管理页面vue ui

Vue 项目结构

  • node_module:依赖库
  • public:静态资源
  • src:组件源码
    • assets:资源(图片)
    • components:存放公共组件的地方
    • App.vue:根组件
    • main.js:项目入口
  • package-lock.json:依赖的详细信息
  • package.json:包依赖文件

Vue 组件基本结构

template:模板,基本 HTML

  • script:脚本
    • data:数据
    • methods:方法
  • style:样式
<!--模板,基本 HTML-->
<template>
</template>
<!--script 脚本-->
<script>
    export default {
        // 定义数据
        data: () => ({
        }),
        // 定义方法
        methods: {
        },
    };
</script>
<!--css 样式-->
<style scoped></style>

VS Code 推荐插件

  • VSCode 推荐插件
    • JavaScript (ES6) code snippets:包含 ES6 语法中的 JS 代码段
    • Vetur:VSCode 支持 VUE 的工具
    • Auto Close Tag:自动添加 HTML/XML 结束标签
    • Auto Rename Tag:自动重命名对应的 HTML/XML 标签
    • Highlight Matching Tag:突出显示匹配的开始和结束标签
    • open in browser:预览 html 文件

HTML基本结构

<!-- 文档声明 -->
<!DOCTYPE html>
<!-- 文档主体 -->
<html lang="en">
<head>
    <!-- 设置网页编码格式 -->
    <meta charset="UTF-8">
    <!-- 设置网页显示区域 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 设置网页标题 -->
    <title>Document</title>
    <!-- 1. 引入vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<!-- 正文内容 -->
<body>
    <!-- 2. 定义一个容器,给容器标注 id,方便后面操作 -->
    <div id="app">{{message}}</div>
</body>
</html>
<!-- JS 脚本 -->
<script>
    // 实例化 vue
    var vm = new Vue({
        // 传入对象
        // 指定挂载元素
        el: "#app",
        // 定义数据
        data :{
            message: "Hello World!"
        }
    })
</script>
<!-- CSS 样式表 -->
<style></style>

Vue指令

  • 指令是将一些特殊行为应用到页面 DOM 元素的特殊属性
  • 格式都是以 v- 开始,例如:
    • v-model:双向绑定
    • v-if 和 v-else:元素是否存在
    • v-show:元素是否显示
    • v-on:绑定事件
    • v-bind:绑定属性

data

  • Vue 中的 data 属性专门以对象方式存放数据
  • data 有两种写法
    • Object
    • Function 推荐使用
<!--第一种:Object-->
<script type="text/javascript">
    var app = new Vue({
        el:"app",
        data:{
            isLogin: false
        }
    })
</script>
<!--第二种:Function-->
<script tyepe="text/javascript">
    var app = new Vue({
        el:"app",
        data(){
            return {
                islogin: false
            }
        }
    })
</script>

v-html 插值

  • 文本:Mustache 模板语法
    <span>{{message}}</sapn>
  • HTML 代码
    <span v-html="rawHtml"></span>
  • HTML中使用 JavaScript 表达式
    {{ ok ? 'YES' : 'NO' }}
  • 实例
<html>
    <body>
        <div id="app">
            <!-- 绑定变量 msg -->
            <input type="text" v-model="msg">
            <!-- 显示 msg的值 -->
            <h2>{{msg}}</h2>
            <!-- 使用 v-html 绑定原生HTML代码 -->
            <span v-html="rawHtml"></span>
            <!-- 使用 JavaScript 表达式 -->
            <div>{{ok?'yes':'no'}}</div>
        </div>
    </body>
</html>
<script>
    vm = new Vue({
        el: "#app",
        data(){
            return{
                msg: '',
                rawHtml: get_rawHtml(),
                ok: 1,
            }
        }
    })

    function get_rawHtml(){
        rawHtml = "<span style='color:red'>插值函数</span>"
        return rawHtml
    }
</script>

v-model 双向绑定

  • 作用: 实现标签中数据的双向绑定
  • 实质:监听元素,根据元素的不同选取不同的 property 抛出不同的事件
  • 适用的表单元素:<input><textarea><select>

v-model 修饰符

  • .lazy:用于在事件之后进行同步
  • .number:将用户的输入值转换为数值类型
  • .trim:自动过滤用户输入的首部和尾部的空白字符
<html>
    <body>
        <div id="app">
            <!-- 在事件之后进行同步 -->
            <input type="text" v-model.lazy="lazy">
            <h2>{{lazy}}</h2>
            <!-- 把用户输入转为数值 -->
            <input type="text" v-model.number="number">
            <h2>{{typeof number}}</h2>
            <!-- 自动过滤首尾的空格 -->
            <input type="text" v-model.trim="trim">
            <h2>{{trim}}</h2>
        </div>
    </body>
</html>
<script>
    vm = new Vue({
        el: "#app",
        data(){
            return{
                lazy: '',
                number: '',
                trim: ''
            }
        }
    })

    function get_rawHtml(){
        rawHtml = "<span style='color:red'>插值函数</span><br><span style='color:red'>插值函数</span>"
        return rawHtml
    }
</script>

v-if 条件渲染

  • v-else 指令表示 v-if 的 else 部分
  • v-else 元素需要在 v-if 或者 v-else-if 的元素后面
<html>
<body>
    <div id="app">
        <!-- v-if 既可以是变量也可以是表达式,但他的结果必须为布尔值 -->
        <h1 v-if="isShow == 1">isShow is true</h1>
        <h1 v-else-if="isShow == 0">isShow is false</h1>
        <h1 v-else="isShow != 1 && isShow != 0">undefined</h1>
        <!-- 使用 template 切换多个元素 -->
        <template v-if="isShow == 1">
            <h1>isShow is true</h1>
            <h1>isShow is true</h1>
        </template>
        <template v-else="isShow != 1 && isShow != 0">
            <h1>undefined</h1>
            <h1>undefined</h1>
        </template>
    </div>
</body>
</html>
<script>
    vm = new Vue({
        el: '#app',
        data: {
            isShow: 1,
        }
    })
</script>

v-show 元素是否显示

  • 修改 display 的属性值
<html>
  <body>
    <div id="app">
      <!-- 修改 display 的属性值 -->
        <div v-show="isShow">true 可以显示</div>
        <div v-show="isShow">false 不可以显示</div>
    </div>
  </body>
</html>
<script>
  var vm = new Vue({
    el: "#app",
    data: {
          isShow: true
    },
  });
</script>

v-if 和 v-show 区别

  • v-if 通过操纵 dom 元素来进行切换显示
    • 表达式的值为 true 时,元素存在于 dom 树中
    • 表达式的值为 false 时,元素从 dom 树中移除
  • v-show 只控制 dom 元素的 display 属性
    • 渲染 HTML 元素,符合条件时显示,不符合条件 display 为 none ,元素还在 dom 树

v-on 事件处理

  • 作用:绑定事件监听器

  • 表达式:方法或者内联语句

  • 简写:@

    <!--v-on 指令写法-->
    <input type='button' v-on:click='num++'>
    <!--简写形式-->
    <input type='button' @click='num++'>
    <!--v-on 绑定函数名称-->
    <input type='button' @click='func'>
    <!--v-on 绑定函数调用-->
    <input type='button' @click='func()'>
    
  • 实例

<body>
    <div id="app">
        <div>{{num}}</div>
        <!-- 使用 v-on 进行事件处理   v-on:事件名 -->
        <button v-on:click="add1">点击加1</button>
        <!-- 使用 @ 调用事件   @事件名 -->
        <button @click="add2(2)">点击加2</button>
    </div>
</body>
</html>
<script>
       vm = new Vue({
        el: '#app',
        data: {
            num: 1,
        },
        methods: {
            add1: function(){
                this.num++
            } ,
            add2: function(param){
                this.num += param
                console.log(this.num)
            }
        }
    }) 
</script>

v-bind 属性绑定

  • 语法

    • v-bind:herf 绑定herf
    • v-bind:style 绑定style
    <!-- 完整语法 -->
    <a v-bind:href="url"></a>
    <!-- 缩写 -->
    <a :href="url"></a>
    
  • 实例

<body>
    <div id="app">
        <!-- 指定样式
        通过 css 指定,width 宽 height 高
        border 边框 solid 实线 #000 黑色 -->
        <div style="width: 100px;height: 100px;border: 1px solid #000;" v-bind:style="bgcolor"></div>
        <!-- 绑定超链接 -->
        <a :href="baidu">访问百度</a>
    </div>
</body>
</html>
<script>
    vm = new Vue({
        el: '#app',
        data: {
            bgcolor:{
                // 设置背景色
                backgroundColor: 'orange',
                // 优先使用绑定的样式
                width: '500px'
            },
            // 绑定超链接为百度首页
            baidu: 'https://www.baidu.com'
        }
    })
</script>

v-for 列表渲染

  • v-for 指令可以基于一个数组来渲染一个列表
  • v-for 指令还可以通过一个对象的属性来迭代数据
<body>
	<div id="app">
		<!-- 遍历数组 -->
		<div v-for="item in list">{{item}}</div>
		<!-- 遍历数组,并提取索引 -->
		<!-- 第一个参数为列表中的值,第二个参数为索引 -->
		<li v-for="(item,index) in list">
			{{index}} -- {{item}}
		</li>
		<!-- 迭代对象,提取对象的值 -->
		<li v-for="item of items">{{item}}</li>
		<!-- 迭代对象的值和键
		第一个参数是value,第二个参数是key,第三个参数是索引 -->
		<li v-for="(item,key,index) of items">
			{{item}} : {{key}} : {{index}}
		</li>
	</div>
</body>
</html>
<script>
    vm = new Vue({
        el: '#app',
        data: {
            list : [1,2,3],
            items : {
                one : '第一组',
                two : '第二组',
                three : '第三组'
            }
        }
    })
</script>

VUE 生命周期

  • 在基础初始化完成之后,数据和事件配置之前调用 beforeCreate()
  • 初始化全部完成,实例创建完成后立即调用 created()
  • 挂载之前调用 beforeMount()
  • 页面挂载后调用 mounted()
  • 数据有更新,页面渲染之前调用 beforeUpdate()
  • 数据有更新,页面渲染完毕后调用 updated()
  • 实例销毁前调用 beforeDestroy()
  • 实例销毁后调用 destroyed()
<html>
<body>
    <div id="app"></div>
</body>
</html>
<script>
    vm = new Vue({
        el : '#app',
        template : '<div @click="fun_click">{{msg}}</div>',
        data : {
            msg : 'Hello World'
        },
        methods : {        
            fun_click : function(){
                console.log('点击事件fun_click')
                this.msg = "Hello Kevin"
            }
        },
        beforeCreate(){
            console.log('基础初始化完成后,数据和事件配置之前调用')
            console.log('beforeCreate')
        },
        created(){
            console.log('实例已创建')
            console.log('created')
        },
        beforeMount(){
            console.log('挂载模版前')
            console.log('beforeMount')
        },
        mounted(){
            console.log('挂载模版完成')
            console.log(this.msg)
            console.log('mounted')
        },
        beforeUpdate(){
            console.log('数据更新前')
            console.log(this.msg)
            console.log('beforeUpdate')
        },
        updated(){
            console.log('数据更新完成')
            console.log(this.msg)
            console.log('updated')
        },
    })
</script>

Vue 页面组件库

  • 常用组件
    • Element UI
    • Vuetify
    • iView

官方文档:
vuetify官网
UI组件地址

Vuetify 页面布局

  • v-app:应用程序的根节点
  • v-main:正文内容区域
  • v-app-bar:放在应用顶部
  • v-navigation-drawer:可以放置在应用的左边或右边,并且可以配置在 v-app-bar 的旁边或下面
  • v-footer:放在应用底部

Vuetify 组件使用

按钮

<template>
  <!-- 设置对齐方式 -->
  <v-row align="center" justify="space-around">
    <!-- 普通样式按钮 -->
    <v-btn>Normal</v-btn>
    <!-- 重要样式按钮 -->
    <v-btn color="primary">Primary</v-btn>
    <!-- 错误样式按钮 -->
    <v-btn color="error">Error</v-btn>
    <!-- 不可用样式按钮 -->
    <v-btn disabled>Disabled</v-btn>
  </v-row>
</template>

数据表格

抽屉导航


Vue 路由 - Router

简介

  • Vue.js 官方提供的路由管理器
  • 包含的主要功能有:
    • 支持 HTML5 历史模式或 hash 模式
    • 支持嵌套路由
    • 支持路由参数
    • 支持编程时导航
    • 支持命名路由

Vue Router 使用

  • <router-link>:支持用户在具有路由功能的应用中点击导航
    • to:指定目标地址
  • <router-view/>:显示与 url 对应的组件
// router 路径下的 index.js

const routes = [
  // path 代表路由地址
  // name 表示这个路由的名称
  // component 表示这个路由和哪个页面关联
  {
    path: '/',
    name: 'Home',
    component: HomeView
  },
]

路由使用步骤

  1. 创建vue页面
  2. 打开router 路径下的 index.js,注册路由
  3. 在需要调用的页面,使用<router-link to="路由地址">New</router-link>

嵌套路由

  • 概念
    • 通过路由规则的层级嵌套在页面中展示复杂的组件结构关系
  • 特点
    • 父级路由中存在子级路由
  • 应用场景:
    • 点击父级路由链接显示模板内容
    • 模板内容中又有子级路由链接
    • 点击子级路由链接显示子级模板内容
  • 用法:
  • 父级路由填充位
  • 通过路由规则的 children 属性,设置子路由
  • 子路由写法
    • 相对路径:子路由path
    • 绝对路径:/父路由path/子路由path
// index.js 路由管理文件
// routes 是路由规则数组
routes: [
    { 
      path: "/layout", 
      component: Layout,
      // 通过 children 属性为 /layout 添加子路由规则,使用相对路径
      children:[
          { path: "login", component: Login },
          { path: "register", component: Register },
      ]
      // 使用绝对路径添加子路由
      // children:[
      //     { path: "/layout/login", component: Login },
      //     { path: "/layout/register", component: Register },
      // ]

    }
]

重定向路由

  • 路由重定向:用户访问地址 A 的时候,强制用户跳转到 B 地址
  • 通过路由规则的 redirect 属性,设置路由的重定向
const routes = [
  {
    // path设置为 / 表示页面最初始的地址
    path: '/', 
    name: 'Home', 
    component: Home,
    //redirect表示要被重定向的新地址,设置为一个路由即可
    redirect:'/layout'
  },
  {
    path:'/layout',
    name:'Layout',
    component: Layout,
  }
]

路由-编程式导航

  • 声明式导航:通过点击链接的方式实现的导航
    • vue 组件中的 <router-link to="/user"></router-link>
  • 编程式导航:调用 JavaScript 的 api 方法实现导航
    • this.$router.push();
    • this.$router.go();
// 字符串(路径名称)
this.$router.push('/register')
// 对象
this.$router.push({ path: '/register'})
// 命名的路由(传递参数)
this.$router.push({ name: 'register', query: { userId:123, name:'admin'}})
// 带查询参数
this.$router.push({ path: '/register?userId=123&name=admin' })
// 后退一页
this.$router.go(-1)
// 前进一页
this.$router.go(1)

axios 访问api

get 请求

参数拼接在 url

	created(){
		const axios = require('axios');
		// axios.get 发出 get 请求
		// 请求参数拼接在url中
		// .then 接收响应 (快捷键 thenc)
		axios.get(
			'https://httpbin.ceshiren.com/get?id=123'
		).then((result) => {
			console.log('get 请求,通过拼接url的形式传递参数')
			console.log(result)
			// 赋值 msg
			this.msg = result.data
		}).catch((err) => {
			console.log(err)
		});
	}

通过 params 形式传递参数

axios.get(
	'https://httpbin.ceshiren.com/get',
	{
		params: {id: 123}
	}
).then((result) => {
	console.log('通过 params 形式传递参数的 get 请求')
	console.log(result)
	// 赋值 msg
	// this.msg = result.data
}).catch((err) => {
	console.log(err)
});

post 请求

json 格式请求体

// post 请求,json 格式请求体
// 默认使用 json 格式
axios.post(
		'https://httpbin.ceshiren.com/post',
		{
			name: 'kevin',
			age: 28
		}
	).then((result) => {
		console.log('post 请求,JSON 格式')
		console.log(result)
		// 赋值 msg
		// this.msg = result.data
	}).catch((err) => {
		console.log(err)
	});
}

表单格式请求体

// post 请求,传递表单格式请求体
// 先下载 form-data,安装命令:npm install form-data --save
// 导入依赖
const FormData = require('form-data');
// 构造表单实例
const form = new FormData();
// 将一组数据添加到表单
form.append('name','kevin')
// 发送post请求
axios.post(
	'https://httpbin.ceshiren.com/post',
	form,
	{'content-type':'application/x-www-form-urlencoded'}
).then((result) => {
	console.log('post 请求,表单格式')
	console.log(result)
}).catch((err) => {
	console.log(err)
});

api 架构优化

1. 封装全局配置模块 http.js

  • 在 src 目录创建新目录 api ,在 api 目录下新建文件 http.js
// 完成 http 请求的基本配置
// 导入 axios
import axios from "axios";

// 创建 axios 实例
var instance = axios.create({
    // 请求头
    headers:{
        'Content-Type':'application/json',
    },
    // 基础 url
    baseURL:'https://httpbin.ceshiren.com',
    // 超时时间
    timeout: 2500
})

// 导出 axios 实例
export default instance

2. 封装各模块接口

  • 封装
// 从 http.js 中导入 axios
import axios from "./http"

const moduleA = {
	// get 请求
	getMethod(){
		return axios({
			// 请求方法
			method: 'GET',
			// 请求路由
			url: '/get'
		})
	}
}

// 导出
export default moduleA
  • 调用
<script>
	import moduleA from '../api/moduleA'

	export default{
		created(){
			moduleA.getMethod().then((result) => {
				console.log(result)
			}).catch((err) => {
				console.log(err)
			});
		}
	}
</script>

3. 整合模块接口 api.js

  • 在 api 目录下新建文件 api.js
// 导入单独接口模块
import moduleA from "./moduleA";
import moduleB from "./moduleB";

// 把单独接口模块整合到api中
const api = {
    moduleA,
    moduleB
}

// 导出api
export default api
  • 在main.js中导入api,将api挂在到vue实例上
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import router from './router'
import api from './api/api'

// 挂载api
Vue.prototype.$api = api
Vue.config.productionTip = false

new Vue({
  vuetify,
  router,
  render: h => h(App)
}).$mount('#app')
  • 调用api
<template>
	<div>api 架构优化 demo</div>
</template>
<script>
	export default{
		// 通过 api调用
		created(){
			this.$api.moduleA.getMethod().then((result) => {
				console.log(result)
			}).catch((err) => {
				console.log(err)
			});
		}
	}
</script>