Vue 知识点总结
概述
用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue
被设计为可以自底向上逐层应用。Vue
的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
Vue.js优点
- 体积小:压缩后33K
- 运行效率高:基于虚拟
DOM
预先通过JavaScript进行各种预算,把最终的Dom
操作计算出来,并没有真实的操作DOM
JavaScript
组成(DOM
和BOM
)
BOM(Browser Object Model)
是指浏览器对象模型,它使JavaScript
有能力与浏览器进行“对话”。window
是他的一个对象
DOM (Document Object Model)
是指文档对象模型,通过它,可以访问HTML
文档的所有元素。Documnet
是它的一个对象。
- 双向数据绑定:开发者只需要关注业务逻辑上面。
- 有很多稳定的
Vue
的组件框架
使用
- 每个
Vue
应用都是通过用Vue
函数创建一个新的 Vue 实例开始的:
var vm = new Vue({
// 选项
})
组件框架学习
简单使用:引入Js
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
测试使用
- 引入
js
<!DOCTYPE html>
<html>
<head>
<script src="./js/vue.js"></script>
</head>
<body>
<h2>Vue 学习</h2>
</body>
<script>
var data = { a: 1 }
var param = new Vue({
data: data
})
param.a = data.a
console.log('当前 a 的值为:' + param.a)
</script>
</html>
实例生命周期钩子
Vue
实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM
并在数据变化时更新 DOM
等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
created
:当Vue
的一个实例被创建后执行。生命周期钩子的this
上下文指向调用它的Vue
实例。
<script>
var vm = new Vue({
data: {
a: 23
},
created: function showA() {
// `this` 指向 vm 实例
alert('当前 a 的值为:' + this.a)
}
})
</script>
mounted
:mounted
不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在mounted
内部使用vm.$nextTick
mounted: function () {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}
路由 router 使用
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import HomePage from '@/components/HomePage'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/hello',
name: 'HelloWorld',
component: HelloWorld
},
{
path: '/',
name: 'HomePage',
component: HomePage
}
]
})
- 在
main.js
中注册定义的router
import Vue from 'vue'
import App from './App'
import router from './router'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
Vue脚手架(vue-cli)搭建和目录结构详解
环境搭建
- 安装
Node
、Npm
(国内可以使用Cnpm
)、Webpack
- 安装
vue
:npm install vue-cli -g
构建项目
-
vue init webpack 项目名称
-
vue init webpack
下载速度慢解决方法详见博客:https://blog.csdn.net/qq_37248504/article/details/107169812 -
新建项目的步骤可以选择默认操作,构建的项目结构如下:
Vue 组件
插槽
插槽就是Vue
实现的一套内容分发的API,将<slot></slot>
元素作为承载分发内容的出口。插槽内可以是任意内容。
<!DOCTYPE html>
<html>
<head>
<script src="./js/vue.js"></script>
</head>
<body>
<h2>Vue 学习</h2>
<div id="app">
<child-component>插槽测试</child-component>
</div>
</body>
<script>
Vue.component("child-component", {
template: `
<div>Hello,World! <slot></slot> </div>
`,
});
let vm = new Vue({
el: "#app",
data: {},
});
</script>
</html>
- 上面的代码
<child-component>插槽测试</child-component>
如果在template
中不加入插槽(<slot></slot>
),那么插槽测试这写内容是不会显示的。
父子页面定义
- 主页面中定义子页面
<template>
<div class="app">
<div class="left" >
<ChildPage ref="child" @childEventOne="methodOne" @childEventTwo="methodTwo"></ChildPage>
</div>
<div class="right">
</div>
</div>
</template>
- 引入子页面注册子组件
// 引入子页面
import ChildPage from './ChildPage.vue'
export default {
components: {
// 注册子组件
ChildPage
}
}
父调用子页面的方法(父使用子的数据)
- 使用
$refs
的方式获取子组件中的方法和数据
methods:{
// 调用子组件中的方法
methodThree(){
this.$refs.child.childMethodOne()
// 获取 子组件中的数据
var data = this.$refs.child.data
}
}
子向父页面传参
- 使用事件机制(
$emit
)
methods:{
test(){
// 调用 父组件中的 childEventTwo方法,方法参数是 0,1
this.$emit('childEventTwo', 0, 1)
}
}
- 父页面收到参数后,可以对数据赋值操作
父页面向子页面传递数据
- 父组件通过
prop
给子组件下发数据,子组件通过$emit
触发事件给父组件发送消息,即prop
向下传递,事件向上传递。 - 父页面
<template>
<div class="parent">
<ChildOne :code="code"
:username="username"></ChildOne>
<child-two :code="code"
:username="username"></child-two>
</div>
</template>
<script>
import ChildOne from './vue-child-one.vue'
import ChildTwo from './vue-child-two.vue'
export default {
name: 'QianduanxuexiVueParent',
components: {
ChildTwo,
ChildOne
},
data () {
return {
code: 'A10001',
username: 'A10002'
}
}
}
</script>
- 子页面
<template>
<div class="child">
<p>父组件中的数据:{{code}} _{{username}}</p>
</div>
</template>
<script>
export default {
name: 'childPage',
props: {
code: String,
username: String
},
data () {
return {
}
}
}
</script>
Axios使用(发送请求)
- 安装
axios
,分装Post Get
请求代码如下面所示。 - 注意:
Post
请求发送的时候,参数可以使用表单的方式提交,后端可以通过request.getParameterMap()
方式获取,参数也可以使用JSON
格式传到后台,后台读取相关参数。 - 上面说到的这两个主要关注点在请求头的
Context-Type
参数上,如下所示
// json格式请求头
const headerJSON = {
'Content-Type': 'application/json'
}
// FormData格式请求头
const headerFormData = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
- 发送
Post
请求相关代码
// 1->common.js中引入axios
import axios from 'axios'
import QS from 'qs'
// 引入Cookie
import Cookies from 'js-cookie'
axios.defaults.timeout = 180000 // 超时时间
// 表单提交方式还是 JSON格式提交
var flag = true
// http request 拦截器
axios.interceptors.request.use(
config => {
// 注意使用的时候需要引入cookie方法,推荐js-cookie
let token = Cookies.get('token')
// 登录接口不需要Token
if (config.url.indexOf('/system/login') > 0) {
return config
}
// 如果是post请求 请求体自动加上token
if (config.method === 'post') {
if (token) {
console.log(config.headers)
config.headers = {
'Content-Type': flag ? 'application/json' : 'application/x-www-form-urlencoded',
// 后端生成的Token,携带Token后请求变成非简单请求
Authorization: token
}
}
} else if (config.method === 'get') {
config.headers = {}
if (token) {
config.headers = {
'Content-Type': flag ? 'application/json' : 'application/x-www-form-urlencoded',
Authorization: token
}
}
}
return config
},
error => {
// return Promise.reject(err)
console.log(error)
}
)
// 2->对get请求传递过来的参数处理
function paramsToUrl (url, params) {
if (!params) return url
for (var key in params) {
if (params[key] && params[key] !== 'undefined') {
if (url.indexOf('?') !== -1) {
url += '&' + '' + key + '=' + params[key] || '' + ''
} else {
url += '?' + '' + key + '=' + params[key] || '' + ''
}
}
}
return url
}
// 3->在common.js中封装公用方法-----封装请求的方法
export function requireData (url, params, type, item, paramsType) {
flag = paramsType
if (!url) return false
switch (item) {
case 'back':
url = axios.defaults.baseM1URL + url
break
case 'before':
url = axios.defaults.baseM2URL + url
break
case 'taskcenter':
url = axios.defaults.baseM3URL + url
break
case 'core':
url = axios.defaults.baseM4URL + url
break
}
if (type === 'get') {
url = paramsToUrl(url, params)
return new Promise((resolve, reject) => {
axios
.get(url, params)
.then(res => {
resolve(res.data)
})
.catch(err => {
reject(err)
})
})
} else if (type === 'post') {
// json格式请求头
const headerJSON = {
'Content-Type': 'application/json'
}
// FormData格式请求头
const headerFormData = {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
return new Promise((resolve, reject) => {
axios.post(url, paramsType ? params : QS.stringify(params), {
headers: paramsType ? headerJSON : headerFormData
}).then(res => {
resolve(res.data)
}).catch(err => {
reject(err.data)
})
})
}
}
vue 多模块安装
- 例如
vue-demo
引入vue-demo-one
模块
npm install K:\qianduanxuexi\vue-demo-one
- 相应的
vue-demo
的pack.json
中会引入相关依赖
- 这个时候只需要,
build vue-demo-one
项目就能生效。
Vue 注册全局的 js
backutils.js
:要注册的工具类js
import Cookies from 'js-cookie'
export default{
// 当前登录的用户
user: JSON.parse(Cookies.get('user')),
// 从 Cookie 中获取用户信息
getCurrentUser () {
return JSON.parse(Cookies.get('user'))
},
// 清除 Cookie 中的缓存
clearCache () {
Cookies.remove('user')
Cookies.remove('token')
}
}
main.js
中引入注册
// 引入全局的 backutils.js
import backutils from './utils/backutils'
// 引入全局的 backutils.js
Vue.prototype.$backutils = backutils
- 使用:直接在
js
中这样取
this.$backutils.user.id
Vue 侦听器
- 监听
param
的值,值发生变化的时候输出内容
export default {
name: 'childPage',
props: {
code: String,
username: String,
param: String
},
data () {
return {
}
},
watch: {
param: {
handler (newVal, oldVal) {
console.log(newVal + '_____' + oldVal)
}
}
}
}
</script>
Vue 项目构建 dist 文件目录
css
文件夹:项目要用到的css
文件,webpack
打包的时候,会把所有的css
样式打包到这里js
文件夹:app.js
是项目中各个页面的逻辑代码,进行了压缩。*.map
是一个信息文件,里面存储着位置信息,转换后代码的每一个位置
Vue 全局注册组件
- 定义组件
<template>
<div>
<el-input placeholder="请输入内容" v-model="calculateInputValue" ></el-input>
</div>
</template>
<script>
export default{
name: 'InputOne',
props: {
test: String
},
data: function () {
return {
// test: ''
inputvalue: '123'
}
},
computed: {
calculateInputValue () {
return JSON.stringify(this.test)
}
}
}
</script>
- 创建公共的
common-component.js
,注册组件
import InputOne from './componentone/InputOne.vue'
// 注册全局的组件
export default (Vue) => {
Vue.component('InputOne', InputOne)
}
- 在
main.js
中引入js
,注册到vue
中
// 注册全局的组件
import ComponentJs from './components/common-component'
Vue.use(ComponentJs)
Computed 方法传参
<tr v-for="(item,index) in arr" v-if="myfilter(index)">
</tr>
export default {
name: 'Achievement',
data () {
return {
...
}
},
methods: {
...
},
computed: {
myfilter() {
return function(index){
return this.arr[index].username.match(this.name)!==null;
}
}
}
}
Vue this 对象
在Vue所有的生命周期钩子方法(如created
,mounted
, updated
以及destroyed
)里使用this
,this
指向调用它的Vue
实例,即(new Vue
)
- 可以从vue 实例中拿到想要的东西,例如拿到父级实例
this.$parent
vue .sync
vue
修饰符sync
的功能是:当一个子组件改变了一个 prop
的值时,这个变化也会同步到父组件中所绑定。
<ChildOne :code="code"
:username="username"
:param="param"
:childOneText.sync="childOneText">
</ChildOne>
// 更新 childOneText
this.$emit('update:childOneText', '1243')
Vue v-for 两层循环
<template>
<div>
<h1>Vue 测试界面 1</h1>
<div>
<table class="testone">
<tr v-for="(data,index) in getTh"
:key="index">
<td>{{data.title}} </td>
<li v-for="item in data.child"
:key="item">{{item.text}}</li>
</tr>
</table>
</div>
</div>
</template>
<script>
export default {
data () {
return {
property: 'value'
}
},
computed: {
getTh () {
let arr = [
{ title: 'one', index: 1, child: [{ text: 'a' }] },
{ title: 'two', index: 2, child: [{ text: 'b' }, { text: 'c' }] },
{ title: 'three', index: 3, child: [{ text: 'b' }, { text: 'c' }] },
{ title: 'four', index: 4, child: [{ text: 'b' }, { text: 'c' }] }
]
return arr
}
}
}
</script>
<style scoped>
.testone {
border: 1px solid black;
}
</style>
vue 子组件使用父组件中方法
- 直接使用
this.$parent
that.$parent.testOne()
- 使用
this.$emit()
- 父组件把方法传入子组件中,在子组件里直接调用这个方法
<ChildOne :code="code"
:username="username"
:param="param"
:childOneText.sync="childOneText"
:testThree="testThree">
</ChildOne>
props: {
code: String,
username: String,
param: String,
childOneText: String,
testThree: {
type: Function,
default: null
}
}
childMethod () {
if (this.testThree) {
this.testThree()
}
}
Vue 修改组件中的样式
/* 方式1 */
.v-eltree /deep/ .el-tree{
margin-top: 100px;
}
/* 方式2 */
.v-eltree >>> .el-tree {
margin-top: 100px;
}