①Vue官网可下载vue.js(或vue.min.js等各种版本),在.html
文件中引入并直接使用。
②开发中使用vue-cli脚手架来搭建项目,本文只记录用vue-cli脚手架的Vue技巧。
③下载vue-devtool扩展工具安装于浏览器扩展中,供Vue调试。
①安装Node。
②设置淘宝镜像源。
npm config set registry https://registry.npm.taobao.org
③安装vue-cli脚手架,检查vue-cli版本。
npm install -g @vue/cli
vue -V
④进入想要创建项目的路径,选择创建的Vue版本。
vue create `项目名`
⑤执行项目
cd `项目名`
npm run serve
⑥输出Vue隐藏配置文件(修改配置无效)。
vue inspect > output.js
⑦手动创建vue.config.js文件,修改Vue的配置 (例如关闭语法检查,默认入口文件路径,配置代理服务器等)
module.exports = {
// 项目打包部署时,不生成 .js.map 文件
productionSourceMap: false,
// 关闭 eslint 语法检查
lintOnSave: false,
// 配置代理服务器
devServer: {
proxy: {
'/api': {
target: 'http://39.98.123.211',
}
}
}
}
⑦项目打包,代码加密,生成最终部署上线的.html
,.js
,.css
文件。其中.js.map
文件是映射加密代码与原代码。可设置不生成.js.map
文件。
npm run build
①public文件夹存放网页、图表等静态资源。
②src/main.js文件是项目程序的入口文件。
import Vue from 'vue';
import App from './App.vue';
// 阻止vue在启动时产生的提示
Vue.config.productionTip = false;
// 创建Vue实例
new Vue({
render: h => h(App),
}).$mount('#app')
③src/App.vue文件是app组件,是所有其他组件的父组件,也是vm的子组件。
④src/assets文件夹存放一些图片、视频等静态资源。
⑤src/components文件夹存放静态组件、全局组件。.vue
文件包含HTML、JS、CSS三种语言,分别用、、划分区域。VSCode输入
<template>
template>
<script>
// 此处写组件的配置对象
export default {
}
script>
<style lang="less" scoped>
/* 此处写组件样式 */
style>
⑥必须有一个根节点。(Vue3.0中不用)
⑦中scoped
属性限定样式作用域,防止组件中样式名的重复。app组件中通常不写scoped
,存放公共样式。
⑧中lang
属性指定样式语言,如果使用Less语言,需要安装Less-loader,注意版本与webpack对应。
npm i less-loader@7
①Vue插件可以导入全局设置,导入已经封装好的第三方插件和组件。
②在src/plugins文件夹内编写自己的插件。插件对外暴露一个包含install()
方法的对象,install()
方法参数1是Vue实例,参数2是可选的配置对象。
// plugin.js插件文件
export default {
install(Vue, options) {
// 设置全局过滤器
Vue.filter('funName', function(args) {});
// 设置全局自定义指令函数
Vue.directive(`anyname`, {
bing(element, binding) {},
inserted(element, binding) {},
update(element, binding) {}
});
Vue.directive(`anyname`, fun(element, binding) {});
// 设置全局组件
const component = Vue.extend({});
Vue.component('组件名', component);
// 设置全局mixin
import {fun} from './mixin.js';
Vue.mixin(fun);
}
}
①Vue.use()
方法安装插件,自动执行install()
方法。
// main.js文件
import plugin from './plugin.js';
// 安装Vue插件
Vue.use(plugin, options);
①Vue的配置对象包含:el 关联元素和其中的data 数据,methods 函数,computed 计算属性,watch 侦听属性,filters 过滤器,directives 自定义指令,props 传参,mixin 混合。配置对象中的内容都可在vm/vc上获取到。
②Vue的配置对象还包含一些特殊函数,Vue会在特定情况下会自动调用这些函数。例如生命周期函数,render()
函数等。
①el
储存关联元素,可以用CSS选择器,或用JS获取节点。
②一个页面应用只有一个vm,只有vm实例需要制定关联app元素,其他所有组件都是vm的子组件。
new Vue({
el: '#app'
});
①data
储存数据,是一个对象,也可以是一个返回对象的函数 (组件和Vue3.0中必须是函数形式)。
②data
中的数据是响应式的,模板中使用数据无需加this
,其他配置项中使用数据需要加this
。
new Vue({
// 对象写法
data: {key: value}
// 函数写法
data() {
return {key: value};
}
});
①methods
储存各种函数,包括事件回调函数和异步函数,其中的this
指向vm/vc。
②原生DOM事件回调函数会传入浏览器event事件对象。
new Vue({
methods: {
fun(args, event){}
}
});
①computed
储存计算属性,计算属性是操作data
或VueX中已有数据得到的新数据。
②计算属性包含getter。当依赖数据变化或初次读取计算属性时都会执行get()
方法。该方法具有缓存机制,多个相同变量不会多次执行get()
。get()
方法的this
是vm/vc本身。
③计算属性也可以包含setter,但不必要。当计算属性被修改时执行set()
方法。set()
方法的this
是vm/vc本身。
③计算属性一定要有返回值,当计算属性对象只有getter,没有setter时可以进行简写。
new Vue({
// 完整写法
computed: {
key: {
get() {return this.value;}
set(newValue) {this.value = newValue;}
}
}
// 简写
computed: {
key() {return this.value;}
}
});
①watch
储存侦听属性,监视data
或computed
中的数据是否发生变化。
②侦听属性包含handler()
方法。当侦听的属性发生变化时,会调用该方法,传入修改前后的值。
③immediate
属性控制模板初始化是否调用handler()
方法。
④deep
属性控制是否深度侦听多级结构中所有变量。
⑤侦听多级结构中的某个变量,侦听属性需要写成字符串形式'obj.key'
。
⑥不需要deep
和immediate
属性时可以进行简写。
⑦计算属性能实现的功能,侦听属性也能实现。计算属性不能实现延迟计算或者异步操作的需求,而侦听属性可以。不需要这些需求的时候,计算属性更简洁方便。
new Vue({
// 完整写法
watch: {
'obj.key': {
handler(newValue, oldValue) {},
immediate: true,
deep: true,
}
}
// 简写
watch:{
key(newValue, oldValue) {}
}
});
①filters
储存过滤函数,用于给数据进行加工,例如将时间以一定的格式显示在网页上。
②过滤器函数的参数1是插值语法|
前的变量,参数2为其他参数,最终返回处理后的结果。
③过滤器可以串联使用。
④写在vm/vc中的过滤器函数是局部的,只有当前的vm/vc能使用。全局过滤器需要在vm初始化前使用Vue.filter()
。
⑤过滤器也可以应用在v-bind
上 (几乎不用)。
new Vue({
filters: {
formater(value, args) {
return '加工后的结果';
}
}
});
①directives
储存自定义指令函数,自定义指令在使用时需要加上v-
。
②自定义指令可以写成对象或函数形式,需要亲自操作DOM。
③函数形式写法的参数1是指令所在DOM节点,参数2是使用指令的vm/vc实例。指令函数在成功绑定元素(元素还不一定在页面上)和模板被重新解析时会被调用。
④对象形式写法是完整写法,包含bind()
,inserted()
,update()
三个函数,在特定情况下被调用。
⑤指令名不建议用驼峰命名。当指令名带有-
时,对应的函数名或对象变量名写法应该用字符串形式。
⑥指令函数的this
是全局对象window
。
⑦写在vm/vc中的自定义指令是局部的,只有当前的vm/vc能使用。全局自定义指令需要在vm初始化前使用Vue.directive()
。
new Vue({
directives: {
// 函数写法
anyname(element, binding) {
element.innerText = binding.value; // 最关心的属性
}
// 对象写法
anyname: {
bing(element, binding)) {}, // 当成功绑定元素时
inserted(element, binding)) {}, // 当元素被放于页面时
update(element, binding)) {}, // 当元素被重新解析时
componentUpdated(element, binding) {},
unbind(element, binding) {}
}
}
});
①props
接受父组件给子组件传入的参数,在父组件模板中的子组件标签添加的属性为变量名,属性值作为传入的具体参数。
②props
对象写法可以规定限制接受参数的类型 (不匹配时Vue报错)、默认值、必要性。
③父组件传入子组件的参数不可以进行修改。
④props
中的参数优先于data
被接受,如果要修改传入的参数,可以通过data
临时变量储存再进行修改。
<Son :arg1="value1" :arg2="value2" />
new Vue({
// 数组简写
props: ['arg1', 'arg2'];
// 对象简写,限定类型
props: {
arg1: Number,
arg2: String
}
// 完整写法,限定类型,规定必要
props: {
arg1: {
type: Number,
default: 66
}
arg2: {
type: String,
required: true
}
}
});
①vm/vc中有相同功能的函数和配置可以写入src/mixin文件夹并对外暴露,进行复用代码。
// mixin.js文件
export const fun1 = {
methods: {},
data: {},
mounted() {}
}
②mixin
用数组储存引入mixin.js
文件中的函数或参数,可以直接使用。
③当mixin
中变量与data
出现数据冲突时,以data
中的为主。
③回调函数例如mounted()
,当出现冲突时,采取都执行的方式,先执行mixins
中的函数。
④写在vm/vc中的mixin
是局部的,只有当前的vm/vc能使用。全局mixin
需要在vm初始化前使用Vue.mixin()
。
// .vue文件
import {fun1, fun2} from './mixin.js';
new Vue({
mixins: [fun1, fun2]
});
①Vue完成模板解析并把初始的真实DOM元素放入页面后才调用mounted()
挂载完成回调函数。
②mounted()
回调函数的this
指向vm/vc。
new Vue({
mounted() {}
});
①render()
函数的参数1是createElement()
函数,调用createElement()
能够创建HTML结构。render()
函数返回被创建的HTML结构作为模板。
②一般写成箭头函数的形式。
new Vue({
render(createElement) {
return createElement('h1', 'h1中的文本内容');
}
// 一般写成
render: h => h(App)
});
①{{}}
中可以放vm/vc中的任何定义的内容(不用加this
)或JS表达式,动态渲染页面。
②|
后面写过滤器函数名,给变量进行格式化加工操作。
<template>
<div id="app">
<h1>{{key}}h1> // 插入属性名
<span>{{fun()}}span> // 插入函数并调用执行
<h1>{{value | filter1(args) | filter2(args)}}h1>
div>
template>
<script>
export default {
el: '#app',
data: {key: '动态显示数据'},
methods: {
fun() {return '动态显示数据';},
filter1() {}
filter2() {}
}
};
script>
①v-bind
单向绑定元素属性的值,其属性值可以变成vm/vc中的任何内容(不用加this
)或JS表达式。简写为:
。
②v-model
双向绑定元素属性的值,其属性值可以变成vm/vc中的任何内容(不用加this
)或JS表达式。也可以实现父子组件的数据同步。
③v-on
给指定元素绑定事件函数,可以传入参数和浏览器event事件。简写为@
。
④v-text
可以将标签节点中的内容替换为属性值的文本,就算文本中有标签也不会被浏览器解析。
⑤v-html
可以将标签节点中的内容替换为属性值的文本,但是标签符号会被HTML解析。
⑥v-cloak
配合CSS中[v-cloak]{display: none;}
语句,可以在Vue未接管元素时,隐藏元素。
⑦v-once
只在初始模板解析时解析插值语法,之后为静态页面不再变化。可以优化性能。
⑧v-pre
标记的元素可以跳过Vue的模板解析。可以优化性能。
<a v-bind:href="url">超链接a>
<input type="text" v-model="value">
<button @click="fun(args, $event)">按钮button>
<div v-text="txt">这里写了也没用div>
<div v-html="">div会被解析div>
<div v-cloak v-once v-pre>div>
①.prevent
阻止元素默认事件。
②.stop
阻止事件冒泡。
③.once
事件只触发一次。
④.capture
事件触发在捕获阶段。
⑤.self
只有event.target
是当前操作元素时才触发事件。(注意:冒泡阶段中event.target
永远是触发事件的那个元素)。
⑥.passive
事件的默认行为立即执行,不用等待事件回调函数执行完。注意:元素触发事件后,首先执行事件回调函数,再执行默认行为。例如wheel
鼠标滚轮事件,当滚轮事件触发后,先执行事件函数后,才滚动滚动条。.passive
能改变这种行为,常用于移动端。
⑦修饰符可以连续写,按顺序修饰。
<a href="url" @click.prevent="fun($event)">超链接a>
<button @click.stop.once.capture="fun($event)">按钮button>
<div @click.self.passive="fun($event)">按钮div>
①.enter
确认回车键是否被按下。
②.delete
确认退格键或删除键是否被按下。
③.esc
确认退出键是否被按下。
④.space
确认空格键是否被按下。
⑤.tab
确认Tab键是否被按下,只能绑在keydown
上。
⑥.up
,.down
,.left
,.right
确认上下左右键是否被按下。
⑦其他按键被检测按下,可以同样使用其按键名event.key
,或根据按键值event.keyCode
。Vue.config.keyCodes.自定义
可以自定义按键名,一般不用。(Vue3.0中已经被移除)
⑧.ctrl
,.meta
,.alt
,.shift
按键配合keydown
则检测是否被按下,配合keyup
检测是否有组合键按下。(注意:.meta
是系统键)
<input type="text" @keyup.enter="fun($event)">
<input type="text" @keydown.caps-lock="fun($event)">
<input type="text" @keydown.ctrl.s="fun($event)">
①固定的基本样式写在class
中,动态变化的样式写在:class
由Vue管理。
②:class
为变量或数组时,样式个数和名字不确定,并会与class
中的样式合并,所有样式一起组合显示。
③:class
为对象时,样式个数和名字确定,可以分别指定样式的显示与不显示。
④:style
可以指定内联样式。其中的样式用对象封装,并且属性值为CSS样式属性。注意一些带-
的CSS样式属性需要改成驼峰命名。
<template>
<div id="root">
// 绑定样式1,样式名为变量
<div class="basic" :class="css">div>
// 绑定样式2,样式名为数组
<div class="basic" :class="cssArr">div>
// 绑定样式3,样式名为对象
<div class="basic" :class="cssObj">div>
// 内联样式1,样式名为对象
<div :style="styleObj">div>
// 内联样式2,样式名为数组
<div :style="styleArr">div>
div>
template>
<script>
export default {
el: '#root',
data: {
css: 'css1',
cssArr: ['css2', 'css3', 'css4'],
cssObj: {
'css5': true,
'css6': false
},
styleObj: {fontSize: '40px'},
styleArr: [{backgroundColor: 'red'}, {color: 'black'}]
}
}
script>
①v-show
值为true
时显示相应元素。值计算后为false
时,相当于元素应用了display:none
。但是元素的节点结构依然存在,频繁切换时建议用v-show
。
②v-if
,v-else-if
和v-else
值为true
时显示相应元素。当其属性值计算后为false
时,元素连网页节点都一起消失。v-else
不用加条件。
③配合v-if
使用打包多个相同判断条件,不破坏原有网络节点结构。
<div v-show="false">div>
<div v-if="null === undefined">div>
<div v-else-if="fun()">div>
<div v-else>div>
<template v-if="true">
<div>div>
<div>div>
template>
①v-for
用于循环创建指定个数的列表项,可以用of
或in
遍历。
②使用v-for
时一定要有:key
属性,给每个列表项唯一的编号。
③遍历数组或字符串时,依次返回其元素value
和索引index
。
④遍历对象时,依次返回对象键值value
和键名key
。
⑤遍历指定次数时,依次返回从1
开始的递增序列和索引。
<ul>
<li v-for="(value, index) of/in arr/str" :key="id">li>
<li v-for="(value, key) of/in obj" :key="id">li>
<li v-for="(num, index) of/in 10" :key="id">li>
ul>
①,
<form @submit="提交后的ajax函数">
<input type="text" v-model.trim="收集变量"/>
<input type="password" v-model="收集变量"/>
<input type="number" v-model.number="收集变量"/>
<input type="radio" v-model="收集变量" value="value"/>
<input type="checkbox" v-model="收集变量" value="用数组收集"/>
<select v-model="收集变量">
<option value="下拉框内容">option>
select>
<textarea v-model.lazy="收集变量">textarea>
<button>提交button>
form>
①给模板中的标签添加ref
属性,可以获取到该标签的DOM节点。
②若给组件标签添加ref
属性,则获取的是整个组件实例对象。
③vm.$refs
中储存添加ref
属性的DOM节点。
<h1 ref="anyname"></h1>
<component ref="anyname" />
this.$refs.anyname;
①vm.$mount()
用于指定vm/vc的关联元素,同初始化中的el
。
②vm.$watch()
用于指定vm/vc侦听变量。参数1是被侦听的变量,用字符串表示,参数2是侦听配置对象。当侦听配置对象不需要deep
和immediate
属性时,可以简写 (不能用箭头函数)。
③vm.$set()
用于后期给vm/vc添加新响应式数据。注意不能直接在data
中添加心属性,应往后级对象中添加。也可以用于修改data
中数组内容。vm.$delete()
删除一个响应式数据。
④vm.$destroy()
用于销毁创建的vm/vc,页面保持最后销毁前的样式。
⑤vm.$emit()
用于触发自身被绑定的自定义事件函数。
⑥vm.$off()
用于解绑自身被绑定的自定义事件函数。
⑦vm.$on()
用于绑定自定义事件函数,vm.$once()
表示绑定的自定义事件函数只触发一次。
⑧vm.$nextTick()
用于在下一次DOM更新结束后执行回调函数。
⑨$attrs
用于收集父组件给子组件传递的props
没有接受的参数,结合v-bind
可以进一步传递。
⑩$listeners
用于收集父组件给子组件传递的所有自定义事件,结合v-on
可以进一步传递。
⑪$parent
用于访问父组件的信息。
⑫$children
用于访问子组件的信息。
vm.$mount('#anyname');
vm.$watch('anykey', {handler() {}, deep: true}); vm.$watch('anykey', fun(){});
vm.$set(targetObj, 'propertyName', value); vm.$delete(targetObj, 'propertyName');
vm.$destroy();
vm.$emit('anyname', value1, value2);
vm.$off(['anyname', 'other']);
vm.$on('anyname'); vm.$once('anyname');
vm.$nextTick(() => {});
<Son v-bind="$attrs"></Son>
<Son v-on="$listeners"></Son>
①组件本质是一个名为VueComponent
的构造函数,由Vue.extend()
生成。
②在使用组件标签时,Vue帮我们执行了new VueComponent({});
。
③每次调用Vue.extend()
返回的都是一个全新的VueComponent
。
④组件中的this
指向VueComponent
实例。
⑤Vue管理的组件都储存在vm.$children
属性上。
⑥VueComponent.prototype.__protot__ === Vue.prototype
。所以组件实例对象可以访问到Vue原型上的方法。
const component = Vue.extend({
template: ``,
data() {return {key: value};},
});
①name
给组件添加组件名,一般组件名与文件名一致,首字母大写的驼峰。
②组件的data
必须写成函数形式。
③子组件需要在父组件中的components
注册,此时组件是局部的。
④在模板中加入组件标签,标签名即组件名。组件标签可以是自闭和标签也可以是标签对。
<template>
<component/>
</template>
<script>
import component from './component';
new Vue({
components: {component}
});
</script>
①父组件将变量或函数传递给子组件,子组件用props
接受,同时$attrs
也可以做到参数传递。
②此方式可以级联,实现祖先组件→后代组件。
①父组件的模板中,可以给子组件绑定一个自定义事件函数,事件函数写在methods
中。
②父组件给子组件添加的自定义事件函数会被子组件的$listeners
属性收集。
③使用ref
获取子组件实例,再用mounted()
在父组件挂载完毕时给子组件绑定自定义事件更加灵活。
④自定义事件可以设置事件修饰符。
⑤给子组件绑定原生DOM事件需要加上.native
事件修饰符 (Vue3.0中移除了该事件修饰符,自定义事件需要用emits
配置接受)。
⑥.sync
事件修饰符,当父组件给子组件传递的参数在子组件中变化时,父组件的数据也能同步变化。
// 父组件文件
<Son @anyname.once="fun" @click.native="fun" :num.sync="arg" />
export default {
methods: {
fun(value) {}
}
}
// 用ref绑定
<Son ref="son"/>
export default {
methods: {
fun(value) {}
}
mounted() {
this.$refs.son.$on('fun', this.anyname);
this.$refs.son.$once('fun', this.anyname);
}
}
①子组件中用$emit()
触发父组件给子组件绑定的自定义事件,参数1为事件函数名,参数2为其他参数。
②子组件中用$off()
解绑父组件给子组件绑定的多个自定义事件。
③当父组件用.sync
修饰符时,触发自定义事件,父组件中的参数也会同步变化。
// 子组件文件
<button @click="doSomething"><button/>
export default {
methods: {
doSomething() {
this.$emit('fun', this.value);
// 啥也不传解绑所有自定义事件函数
this.$off(['fun', 'other']);
this.$emit('update:arg', this.value);
}
}
}
①借助一个所有组件都能访问到的实例对象 (Vue.prototype),并赋予$on()
,$off()
,$emit()
方法和自定义事件函数,可以实现任意组件间的通信。
②初始化Vue时,借助beforeCreate()
生命周期函数,在Vue.prototype.$bus
中连接vm自身实例即可安装全局事件总线。(很奇怪,因为原型无限套娃了!)
③使用这种方式还可以将统一的API请求接口注册到所有vm/vc上。
// main.js文件
import * as API from "@/api";
new Vue({
// 安装全局事件总线
beforeCreate() {
Vue.prototype.$bus = this;
Vue.prototype.$API = API;
}
});
④在接收参数的组件mounted
中,用this.$bus.$on()
方法添加一个自定义事件函数。
⑤在发送参数的组件methods
中,用this.$bus.$emit()
方法触发事件总线中的自定义事件函数。
⑥在接收参数的组件销毁前,记得用this.$bus.$off()
手动解绑事件总线中的自定义函数。
// .vue文件
// 接收参数组件
export default {
methods: {
fun (value) {}
}
mounted: {
this.$bus.$on('fun')
}
beforeDestroy() {
this.$bus.$off('fun')
}
}
// 发送参数组件
export default {
methods: {
this.$bus.$emit('fun', this.value)
}
}
①pubsub-js第三方库提供了消息订阅与发布的API,可适用于任意框架中。
npm i pubsub-js
②接受参数的组件订阅消息,subscribe()
方法订阅消息名与回调函数。
③回调函数最好写在组件的methods
中,函数的参数1是消息名(用不到),参数2是接受的参数。
④unsubscribe()
方法取消订阅消息,取消方法类似定时器。
import pubsub from 'pubsub-js';
this.pubid = pubsub.subscribe('anyname', (msgName, data) => {});
pubsub.unsubscribe(this.pubid);
⑤发送参数的组件发布消息,publish()
方法发布消息名与参数,需要与订阅消息的统一。
pubsub.publish('anyname', this.data);
①父组件中子组件标签使用标签对的形式,标签对内传入的自定义模板会被插入子组件插槽处。
②子组件中插槽用name
属性给插槽命名,可以在子组件中设置多个插槽。
③
④多个元素需要放入同一个插槽可以用打包。
⑤scope
属性接受,接受的多个参数被打包成一个对象。
⑥指定插入子组件哪个插槽,用slot
属性指定插槽名,Vue3.0中建议使用v-slot
属性。
// 父组件
<Son>
<div slot="1"></div>
// 打包多个
<template v-slot:2 scope="{info}">
<div v-for="(data, id) in info" :key="id"></div>
</template>
</Son>
// 子组件
<slot name="1">不被使用时显示</slot>
<slot name="2" :info="info">不被使用时显示</slot>
①多个组件共享读写同一个数据时,可以借助VueX插件管理共享数据。
②安装VueX,并使用插件。注意Vue2.0只能用VueX3.0,Vue3.0只能用VueX4.0。
③src/store/文件夹存放VueX所有配置与数据。
④只有安装了VueX插件,创建vm的时候才可以传入store配置对象,所有vm/vc都可以访问$store
属性。
npm i vuex@3
// main.js文件
import store from './store';
new Vue({
store,
});
①store是VueX仓库的实例,包含actions
,mutations
,state
,getters
四个部分。
②actions
用于响应vm/vc中触发的数据操作。actions
中编写数据操作前的预处理函数,例如做出一些判断,想服务器发送请求。预处理函数名小写,参数1是context
,可以调用store的方法,参数2是value
,接受vm/vc传入的参数。
③actions
中预处理函数逻辑太长太复杂,可以编写多个预处理函数,通过context
参数互相调用使用dispatch()
方法。
④mutations
用于操作仓库数据。mutations
中编写数据操作函数,数据操作函数名大写,参数1是state
,参数2是value
,接受预处理函数传入的参数。
⑤state
存储共享数据。
⑥getters
用于加工state
中的共享数据,类似计算属性,为vm/vc读取数据作简化。getters
中编写数据加工函数,参数1为state
,需要返回加工后的数据。
// store/index.js文件
import Vue from 'vue';
import VueX from 'vuex';
Vue.use(VueX);
const actions = {
// 预处理函数
anyname(context, value) {
context.commit('ANYNAME', value);
}
};
const mutations = {
// 数据操作函数
ANYNAME(state, value) {
state.data += value;
}
};
const state = {
// 数据
data: value
};
const getters = {
// 加工数据
data(state) {
return state.data + 1;
}
};
// 创建store实例
export default new VueX.Store({
actions,
mutations,
state,
getters,
});
①vm/vc用this.$store.dispatch()
方法将需要操作的参数传给actions
中定义好的预处理函数。参数1是预处理函数名,参数2是其他参数。
②vm/vc用this.$store.commit()
方法直接将需要操作的参数传给mutations
中定义好的数据操作函数。参数1是数据操作函数名,参数2是其他参数。
③vm/vc可以通过this.$store.state
读取VueX中的state
数据。
④vm/vc可以通过this.$store.getters
读取VueX中的getters
数据。
// .vue文件
export default {
methods: {
fun() {
this.$store.dispatch('anyname', this.value);
this.$store.commit('ANYNAME', this.value);
console.log(this.$store.state.data);
console.log(this.$store.getters.data);
},
},
}
①VueX一般使用模块化编写。模块化actions
,mutations
,state
和getters
写在一个配置对象中,导入到VueX的modules
中。
②模块配置对象中需要开启命名空间namespaced
。
// store/index.js文件
import store1 from "src/store/other.js"
export default new VueX.Store({
modules: {
other,
}
});
// 模块化仓库文件
export default {
namespaced: true,
state,
actions,
mutations,
getters,
};
①vm/vc可以在computed
中,通过mapState()
和mapGetters()
方法自动将VueX中的数据生成计算属性函数。当计算属性名与VueX中的数据同名时可以数组简写。
②vm/vc可以在methods
中,通过mapMutations()
和mapActions()
方法自动调用commit()
方法和dispatch()
方法。当函数名与VueX中函数名相同时可以数组简写。(注意!函数参数需要从模板中传入)
③以上四个方法读写VueX中的数据,参数1是模块化的仓库名。当使用原生函数时,数据路径需要添加仓库名。
// .vue文件
export default {
computed: {
...mapState('other', {data:'data'}),
...mapState('other', ['data']),
...mapGetters('other', {data:'data'}),
...mapGetters('other', ['data']),
},
methods: {
...mapActions('other', {fun: 'anyname'}),
...mapActions('other', ['anyname']),
...mapMutations('other', {fun: 'ANYNAME'}),
...mapMutations('other', ['ANYNAME']),
this.$store.dispatch('other/anyname', this.value);
this.$store.commit('other/ANYNAME', this.value);
},
}
①VueX 数据存在内存中,在页面刷新后数据丢失。本地存储数据存在磁盘中,页面刷新数据还在。
①只有添加v-show
或v-if
的元素可以添加离开与进入动画。用CSS制作进入动画,离开动画的样式。
②进入动画样式名后增加-enter-active
,离开动画的样式名需要增加-leave-active
,设置动画执行的参数。
/* 动画方式 */
@keyframes anim{
from{}
to{}
}
.anyname-enter-active{
animation: anim 2s linear;
}
.anyname-leave-active{
animation: anim 2s linear reverse;
}
①用CSS制作进入的过渡效果,.anyname-enter
中写进入起点的样式 (Vue3.0中为.anyname-enter-from
),.anyname-enter-to
中写进入终点的样式。
②用CSS制作离开的过渡效果,.anyname-leave
中写离开起点的样式 (Vue3.0中为.anyname-leave-from
),.anyname-leave-to
中写离开终点的样式。
③过渡参数写在.anyname-enter-active
和.anyname-leave-active
中。
/* 过渡方式 */
.anyname-enter, .anyname-leave-to{
transform: translateX(0);
}
.anyname-leave, .anyname-enter-to{
transform: translateX(100%);
}
.anyname-enter-active, .anyname-leave-active{
transition: 2s linear;
}
①
②appear
属性为true
,页面刷新,元素首次就播放进入动画/过渡。
③name
属性中自定义动画/过渡的样式名.
④key
属性。
<transition name="anyname" appear>
<div></div>
</transition>
<transition-group name="anyname">
<li key="1"></li>
<li key="2"></li>
</transition-group>
①Animate.css第三方动画提供了设计好的动画。
npm install animate.css --save
// main.js文件
import 'animate.css';
// 使用动画
<transition
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__heartBeat"
>
</transition>
①vue-cli配置代理服务器,在vue.config.js中写入以下代码即可开启代理服务器。
②方式一:只能给固定端口服务器发送请求,不支持向其他服务器发送请求。代理服务器会优先返回public文件夹内的文件,若不存在,则向指定服务器发送请求。
③方式二:可以给任意多个服务器发送请求。可以指定请求前缀保,注意需要加上pathRewrite
属性重写URL。
④ws
默认值为true
,用于支持websocket,可忽略该参数。
⑤changeOrigin
默认值为true
,用于控制请求头中的HOST值,与本地端口相同还是与请求服务器相同,可忽略该参数。
// vue.config.js文件
module.exports = {
// 开启代理服务器(方式一)
devServer: {
proxy: 'http://localhost:5000'
},
// 开启代理服务器(方式二)
devServer: {
proxy: {
'/api': {
target: 'http://localhost:5000',
pathRewrite: {'^/api': ''},
ws: true,
changeOrigin: true
},
'/other': {
target: 'http://localhost:5001'
}
}
}
}
①移动端常用UI组件库:Vant,Cube UI,Mint UI。
②PC端常用UI组件库:Element UI,IView UI,Ant Design。
③Element UI不要全引入样式,借助babel-plugin-component按需引入。在babel.config.js和src/main.js中添加配置。
// 安装element-ui
npm i element-ui
// 按需引入组件
npm install babel-plugin-component -D
// 在babel.config.js中添加
presets: [
'@vue/cli-plugin-babel/preset',
["@babel/preset-env", { "modules": false }]
],
plugins: [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
// main.js文件
import {Button, MessageBox} from 'element-ui';
// 注册全局组件
Vue.component(Button.name, Button);
// 挂载到原型
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
Vue 里面data属性之所以不能写成对象的格式,是因为对象是对地址的引用,而不是独立存在的。如果一个.vue 文件有多个子组件共同接收一个变量的话,改变其中一个子组件内此变量的值,会影响其他组件的这个变量的值。如果写成函数的话,那么他们有一个作用域的概念在里面,相互隔阂,不受影响
Getter 数据代理
①Vue用Object.defineProperty()
中的getter与setter代理数据,进行双向绑定。
②Vue创建实例时的data
被加工并保存在vm._data
属性中,data
对象中的每一个属性都被添加到vm/vc上并且增添get()
和set()
方法。读取或修改data
对象中的属性时会触发对应get()
和set()
方法。
Object.defineProperty(obj, key, {
value: value, // 数据内容
configurable: true, // 是否可配置
enumerable: true, // 是否可枚举
writable: true, // 是否可改写
get() {return value;}, // 属性值被读取时执行
set(args) {value = args;} // 属性值被修改时执行
})
Setter 数据监视
①data
对象中的属性监视功能不能直接用Object.defineProperty()
中的get()
和set()
方法定义,会出现死循环。Vue通过构造函数来为data
对象中的属性添加get()
和set()
方法。
②data
对象中多层结构的对象属性也全都递归被添加get()
和set()
方法进行监视。
③多层结构如果是数组,并不是通过getter与setter进行监视,所以不能用索引去修改数组的内容。需要用过push()
,pop()
,shift()
,unshift()
,sort()
,splice()
,reverse()
方法来证明原数组被修改。这7个数组方法经过Vue的包装,添加了重新解析页面的操作等,达到监视的目的。
④data
对象中初始化后添加的新属性不会自动添加添加get()
和set()
方法,需要调用vm.$set()
或Vue.set()
方法添加。注意不能直接给data
对象添加属性,应往后级对象中添加。也可用于修改数组某个元素。
⑤使用其他数组方法,产生新数组时,可以通过替换原数组方式修改数组,不影响数据监视。
function Observer(obj) {
const keys = Object.keys(obj);
keys.forEach((k) => {
Object.defineProperty(this, k, {
get() {
return obj[k];
},
set(value) {
obj[k] = value;
/* 并更新页面显示 */
}
})
});
}
const obs = new Observer(data);
vm._data = data = obs;
// 后加入新属性
Vue.set(vm.obj, 'newProperty', value);
// 数组的数据监视
vm.$set(vm.arr, 1, value);
this.arr = this.arr.filter(() => {});
①创建Vue实例。
②初始化:生命周期,事件,但数据代理未开始。
③调用beforeCreate()
生命函数。此时仍然无法访问到data
中的数据和methods
中的方法。
④初始化:数据监测、数据代理。
⑤调用created()
生命函数。此时可以访问到data
中的数据和methods
中的方法。
⑥是否定义了el
关联元素,若无关联元素则不再进行下面的流程,等待vm.$mount(el)
被调用。
⑦是否确定了template
模板,若无模板则使用el
关联元素本身及其内容为模板,若有模板则使用定义的模板替换el
元素本身。
⑧此时Vue开始解析模板,生成虚拟DOM存于内存,页面还不能显示解析好的内容。
⑨调用beforeMount()
生命函数。此时页面呈现的是未经Vue编译的模板DOM结构,所有对模板DOM的操作最终不起作用。
⑩Vue将虚拟DOM挂载在页面上,并备份在vm.$el
中。
⑪调用mounted()
生命函数。此时页面呈现经过Vue编译后的模板DOM结构,并且可以进行开启定时器,发送网络请求,订阅消息,绑定自定事件等其他初始化操作。
⑫页面挂载完毕后,每次需要更新页面前,会调用beforeUpdate()
生命函数,此时数据是新的,页面还是旧的。
⑬更新前后,新旧虚拟DOM进行比较,生成新的页面。更新完后,会调用updated()
生命函数,此时页面与数据都是新的。
⑭等待vm.$destroy()
被调用时,vm被销毁,页面保持最后的销毁前的样式。
⑮销毁前会调用beforeDestroy()
生命函数,一般在此时关闭定时器,取消订阅,解绑所有自定义事件等操作。销毁后会调用destroyed()
生命函数。
key
是虚拟DOM中的标识。当新的虚拟DOM生成后,通过key
与之前的虚拟DOM进行diff
算法对比。对比时先比较key
是否相同,新的虚拟DOM中有些key
不存在于之前的虚拟DOM时,更新。key
相同时比较标签内的内容是否相同,内容相同则可以复用,内容不同则更新。