vue2

90 阅读5分钟

前两年跟尚硅谷张老师还有自己买了点资料学的vue框架,也是好久没用了,避免忘记,记录一下吧

自定义指令

  1. 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. 自定义指令的钩子函数 1、bind:在该元素绑定指令时调用且仅调用一次,用于初始化。 2、inserted:元素插入父节点时调用(可能仍在虚拟Dom节点中)。 3、update:模版更新时调用。 4、componentUpdated:被绑定元素所在模版完成一次更新周期时调用。 5、unbind:只调用一次,指令与元素解绑时调用。
  2. 赋予以下参数: 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>

组件

  1. 全局注册组件 所谓全局注册就是在构造器的外部用Vue.component进行注册,全局注册后,任何Vue实例都可以使用。

  2. 局部注册组件 所谓局部注册就是在可以在实例中注册组件,注册后,该组件只能在当前实例中使用。

  3. 组件的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双向绑定

  1. 通过Object.defineProperty()给vm添加与data对象的属性对应的属性描述符
  2. 所有添加的属性都包含getter/setter
  3. 在getter/setter内部去操作data中对应的属性数据
  4. 如果数据丢失了双向绑定,可以使用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'
              }
            ]
          })
  1. 创建路由文件
//该文件用于创建整个应用的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')
  1. 使用路由组件标签:
   <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
  1. 新建文件store.js
import Vuex from 'vuex'
	export default new Vuex.Store({
		state,
		mutations,
		actions,
		getters,
		modules
	})
  1. main.js中引入
import store from './store.js'
	new Vue({
		store
	})

vuex的核心概念

  1. state
	//vuex管理的状态对象
	const state = {
		value: initValue
	}
  1. mutations
	/*包含多个直接更新state的方法的对象
	只能包含同步的代码, 不能写异步代码*/
	const mutations = {
		yar (state, data) { 
			// 更新state的某个属性
		}
	}
  1. actions
	/*包含多个事件回调函数的对象
	可以包含异步代码(定时器, ajax)*/
	const actions = {
		nub ({commit, state}, datb) {
			commit('yar', datc)
		}
	}
  1. getters
	//包含多个计算属性(get)的对象
	const getters = {
		sun (state) {
			return ...
		}
	}
  1. modules 包含多个module 一个module是一个store的配置对象 与一个组件(包含有共享数据)对应

  2. 组件中使用

	import {mapGetters, mapActions} from 'vuex'
	export default {
		computed: mapGetters(['sun'])
		methods: mapActions(['nub'])
	}
	{{sun}} @click="nub(data)"
  1. 映射store
	import store from './store'
	new Vue({
		store
	})
  1. 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>