前两年跟尚硅谷张老师还有自己买了点资料学的vue框架,也是好久没用了,避免忘记,记录一下吧
自定义指令
- Vue.directive自定义指令 可以定义在全局API里,全局API并不在Vue实例的构造器里,比如注册一个全局指令v-focus,该指令的功能是在页面加载时,元素获得焦点。
<body>
<div id="app">
<input type="text" v-focu />
</div>
</body>
<script type="text/javascript">
Vue.directive('focu',{
inserted:function(el){
el.focus()
}
});
var vm=new Vue({
el:"#app",
directives:{
focus:{
inserted:function(el){
el.focus()
}
}
}
})
</script>
- 自定义指令的钩子函数 1、bind:在该元素绑定指令时调用且仅调用一次,用于初始化。 2、inserted:元素插入父节点时调用(可能仍在虚拟Dom节点中)。 3、update:模版更新时调用。 4、componentUpdated:被绑定元素所在模版完成一次更新周期时调用。 5、unbind:只调用一次,指令与元素解绑时调用。
- 赋予以下参数: 1、el:指令所绑定的元素,可以用来直接操作DOM. 2、binding:一个对象,包含以下属性: name:指令名,不包含v-前缀。 value:指令的绑定值。 oldValue:指令绑定的前一个值。仅在update和componentUpdate钩子中可用。无论值是否改变都可用。 expression:绑定值的字符串形式。 arg:传给指令的参数。 modifiers:一个包含修饰符的对象。 3、vnode:Vue编译生成的虚拟节点。 4、oldVnode:上一个虚拟节点,仅在update和componentupdated钩子中可用。
<body>
<div id="app">
<button @click="changeBig">changeBig</button>
<button @click="changeSmall">changeSmall</button>
<div v-galaxy="changeSize">你好,再见。</div>
</div>
</body>
<script type="text/javascript">
Vue.directive("galaxy",function(el,binding){
el.style='font-size:'+binding.value+'px';
});
var vm=new Vue({
el:"#app",
data:{
changeSize:14
},
methods:{
changeBig:function(){
this.changeSize+=4
},
changeSmall:function(){
this.changeSize-=4
}
}
})
</script>
组件
-
全局注册组件 所谓全局注册就是在构造器的外部用Vue.component进行注册,全局注册后,任何Vue实例都可以使用。
-
局部注册组件 所谓局部注册就是在可以在实例中注册组件,注册后,该组件只能在当前实例中使用。
-
组件的data选项 组件的data必须是函数,然后将数据通过return返回。
<body>
<div id="app">
<ele><ele/>
</div>
</body>
<script>
Vue.component("ele",{
template:"<p>{{msg}}</p>",
data:function(){
return{
msg:'美好事物'
}
}
})
var vm=new Vue({
el:"#app"
})
</script>
如果返回出来的对象引用了外部的一个对象,这个对象是共享的,任何一方修改都会同步。
<body>
<div id="app">
<p>{{num}}</p>
<button @click="add()">增加</button>
<button onclick="vm.$destroy()">销毁</button>
</div>
</body>
<script type="text/javascript" src="js/js/vue.js" ></script>
<script>
var vm=new Vue({//创建Vue对象
el:"#app",
data:{
num:40
},
methods:{
add:function(){
this.num++;
}
},
// template:`<p>选项模版</p>`
beforeCreate:function(){
console.log("实例创建之前");
console.log(this.num);
console.log(this.$el);
},
created:function(){
console.log("实例创建完成");
console.log(this.num);
console.log(this.$el);
},
beforeMount:function(){
console.log("实例挂载开始之前");
console.log(this.num);
console.log(this.$el);
}
});
</script>
vue双向绑定
- 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
- 所有添加的属性都包含getter/setter
- 在getter/setter内部去操作data中对应的属性数据
- 如果数据丢失了双向绑定,可以使用vue.$setter语法糖来更新数据
组件通信
传值,没啥好说的 1.父子组件props和emit 父子组件间通信的基本方式 属性值的2大类型: 一般: 父组件-->子组件 函数: 子组件-->父组件 隔层组件间传递: 必须逐层传递(麻烦) 兄弟组件间: 必须借助父组件(麻烦) 2.ref 链:父组件要给子组件传值,在子组件上定义一个 ref 属性,这样通过父组件的 $refs 属性获取子组件的值 3.事件总线bus:就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件 先创建全局空Vue实例
import Vue from 'vue';
export default sunBus= new Vue()
然后具体页面使用$emit发布事件 - 传递值
import sunBus from './sunBus'
sunBus.$emit('send',‘data’)
最后具体页面使用$on订阅事件 - 接收组件值
import sunBus from './sunBus'
sunBus.$on('send', res => {
console.log(res)
}
5.vuex
vue过渡动画
利用vue去操控css的transition/animation动画
<transition name="vue">
<p v-if="show">hello</p>
</transition>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.vue-enter, .vue-leave-to {
opacity: 0
}
</style>
vue指令
- v-text/v-html: 指定标签体 v-text : 当作纯文本 v-html : 将value作为html标签来解析
- v-if v-else v-show: 显示/隐藏元素 v-if : 如果vlaue为true, 当前标签会输出在页面中 v-else : 与v-if一起使用, 如果value为false, 将当前标签输出到页面中 v-show: 就会在标签中添加display样式, 如果vlaue为true, display=block, 否则是none
- v-for : 遍历
遍历数组 : v-for="(person, index) in persons"
遍历对象 : v-for="value in person" $key - v-on : 绑定事件监听 v-on:事件名, 可以缩写为: @事件名 监视具体的按键: @keyup.keyCode @keyup.enter 停止事件的冒泡和阻止事件默认行为: @click.stop @click.prevent 隐含对象: $event
- v-bind : 强制绑定解析表达式
html标签属性是不支持表达式的, 就可以使用v-bind 可以缩写为: :id='name' :class :class="a" :class="{classA : isA, classB : isB}" :class="[classA, classB]" :style :style="{color : color}" - v-model 双向数据绑定 自动收集用户输入数据
- ref : 标识某个标签 ref='xxx' 读取得到标签对象: this.$refs.xxx
vue-router
- 使用vue-router 1. 创建路由器: router/index.js
new VueRouter({
routes: [
{ // 一般路由
path: '/about',
component: about
},
{ // 自动跳转路由
path: '/',
redirect: '/about'
}
]
})
- 创建路由文件
//该文件用于创建整个应用的router
//首先,需要引用vue-router
import VueRouter from "vue-router";
import Vue from 'vue';
//引入路由组件
import MyLogin from '../components/login/MyLogin.vue'
import MyHome from '../components/home/Home.vue'
import MyHello from '../components/MyHello.vue'
Vue.use(VueRouter)
//创建并暴露一个VueRouter
export default new VueRouter({
routes: [
{
path: '/',
component: MyLogin,
},
{
path: '/MyHello',
component: MyHello,
},
{
path: '/MyHome',
component: MyHome,
}
],
})
//main.js文件引入创建的路由文件
import router from "./router/index";
new Vue({
render: h => h(App),
router
}).$mount('#app')
- 使用路由组件标签:
<router-link to="/xxx">hhh</router-link>
<router-view /> <!-- 站位显示 -->
- 嵌套路由
{
path: 'message',
component: message,
children: [
{
path: '/home/news',
component: news
}
]
}
- 向路由组件传递数据
params: <router-link to="/home/news/abc/123">
props: <router-view msg='abc'>
- 缓存路由组件
<keep-alive>
<router-view></router-view>
</keep-alive>
-
路由的编程式导航
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面) this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面) this.$router.back(): 请求(返回)上一个记录路由
vuex
概念就不赘述了,简单说就是对应用中组件的状态进行集中式的管理
- 下载: npm install vuex --save
- 新建文件store.js
import Vuex from 'vuex'
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules
})
- main.js中引入
import store from './store.js'
new Vue({
store
})
vuex的核心概念
- state
//vuex管理的状态对象
const state = {
value: initValue
}
- mutations
/*包含多个直接更新state的方法的对象
只能包含同步的代码, 不能写异步代码*/
const mutations = {
yar (state, data) {
// 更新state的某个属性
}
}
- actions
/*包含多个事件回调函数的对象
可以包含异步代码(定时器, ajax)*/
const actions = {
nub ({commit, state}, datb) {
commit('yar', datc)
}
}
- getters
//包含多个计算属性(get)的对象
const getters = {
sun (state) {
return ...
}
}
-
modules 包含多个module 一个module是一个store的配置对象 与一个组件(包含有共享数据)对应
-
组件中使用
import {mapGetters, mapActions} from 'vuex'
export default {
computed: mapGetters(['sun'])
methods: mapActions(['nub'])
}
{{sun}} @click="nub(data)"
- 映射store
import store from './store'
new Vue({
store
})
- store对象 1.所有用vuex管理的组件中都多了一个属性$store, 它就是一个store对象 2.属性: state: 注册的state对象 getters: 注册的getters对象 3.方法: dispatch(actionName, data): 分发action
vuex数据丢失问题
store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值。 关于刷新页面state数据丢失问题,可以使用本地存储,也可以使用vuex-persistedstate 插件 (数据持久化) 安装插件:npm install vuex-persistedstate --save
import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
plugins: [createPersistedState()]
})
该插件默认持久化所有state,当然也可以指定需要持久化的state
import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
plugins: [createPersistedState({
storage: window.sessionStorage,
reducer(data) {
return {
// 设置只储存state中的myData
myData: data.myData
}
}
})]
axios
- 安装命令:npm install axios --save
- 引入
import axios from 'axios'
Vue.prototype.$axios = axios
- 请求
axios.post('/login', {
userName: this.name,
password: this.password
}).then((res) => {//成功
console.log(res)
if (res.data.message === "ok") {
this.$router.replace('/MyHello');//成功跳转
} else {
alert(res.data.message)
}
}).catch(error =>//失败
console.log(error)
)
vue2跨域
- 在vue.config.js文件配置(没有就自己创建,注意名称)
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
// lintOnSave: false,
devServer: {
proxy: 'http://localhost:4000' // 配置跨域代理的服务器地址
// before: require("./mock/mockServe") //引入mock.js
},
transpileDependencies: true
})
Slot分发内容
- slot用法 1、单个SLOT:在子组件内使用特殊的元素就可以为这个子组件开启一个插槽(slot),在父组件莫办理,编写在子组件标签内的所有内容将代替子组件的标签及它的内容。 2、具名SLOT:元素可以用一个特殊的特性name来进一步配置如何分发内容。多个插槽可以有不同的名字,具名插槽将匹配内容片段中对应slot特征的元素,具名slot可以与单个slot共存。
<body>
<!--单个与具名slot-->
<div id="app">
<h1 slot="header">你好</h1>
<comp1>
<template slot-scope="test">
<p>你猜啊?</p>
<p>{{test.msg}}</p>
<div slot="footer">底部</div>
</template>
</comp1>
</div>
<template id="myId">
<div>
<slot name="header"></slot>
<slot name="footer"></slot>
<slot msg="asdfhkjli"></slot>
<slot>
<p>见到你很高兴,</p>
</slot>
</div>
</template>
</body>
<script>
Vue.component('comp1',{
template:"#myId"
})
var vm=new Vue({
el:"#app",
})
</script>