vue基础笔记

332 阅读3分钟

对象属性

var vm = new Vue({
    el: '#app',     // element
    template: ``,   // 模板(组件用法)
    data: {},       // 数据
    methods: {},    // 方法
    filters: {},    // 过滤器(局部/全局)
    directives: {}, // 自定义指令(局部/全局)
    computed: {},   // 计算属性
    watch: {},      // 监视
    components: {}, // 组件(局部/全局)
    props: [], // 接收父组件的参数
    router: {},     // 路由
    
    // 生命周期的8个钩子函数
    beforeCreate() { },
    created() { },  // 创建
    beforeMount() { },
    mounted() { },  // 加载
    beforeUpdate() { },
    updated() { },  // 修改
    beforeDestroy() { },
    destroyed() { },// 销毁
    
    // 当组件在 <keep-alive> 内被切换
    activated() { },
    deactivated() { }
});

基础

插值表达式

{{ 插值表达式 }}  => 为所欲为 

指定

v-text、v-html
v-show、v-if、v-else、v-else-if  // show切换元素display属性  if是真实销毁或创建元素
v-on // 缩写 @
v-bind // 缩写 :
v-model // 双向数据绑定 是:value与@input的结合
v-for :key  // 优先级大于v-if
v-once // 只加载一次
v-cloak // 解决页面闪烁问题
v-slot // 缩写 # 
// 注意:只能使用在template标签上,独占默认插槽除外<aaa v-slot:default="sn">123</aaa>缩写去掉:default

自定义指令 directive

// 全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 被绑定元素插入父节点时调用
  inserted: function (el) {el.focus()},
  // 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
  bind: function () {},
  // 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
  update: function () {},
  // 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  componentUpdated: function () {},
  // 只调用一次,指令与元素解绑时调用。
  unbind: function () {}
})
// --- 指令对象可以换成函数 相当于只有bind和update调用

// 局部自定义指令
directives: {
  focus: {
    // 指令的定义
    inserted: function (el) {
      el.focus()
    }
  }
}

过滤器 filter

// 全局过滤器
Vue.filter("toUpper", function (value) {
    return value.toUpperCase();
});

// 局部过滤器
filters: {
    toUpper(value) {
        return value.toUpperCase();
    }
}

// 使用
{{ value | toUpper }}

操作DOM ref

<input ref="myInput">
    
vm.$refs.myInput // 获取到input的dom节点

计算属性 computed

// computed是使用方法与data一样,写法与methods类型 但获取值时必带返回值
computed: {
    // 仅读取
    aDouble: function () {
        return this.a * 2
    },
    
    // 读取和设置
    aPlus: {
        get: function () {
            return this.a + 1
        },
        set: function (v) {
            this.a = v - 1
         }
    }
}

监视 watch

// watch 可以侦听 data、props、computed、$emit
watch:{
    name(newValue,oldValue){},
    // 深度监视
    'a.b'function(){},
     a: {
          handler: function (newValue,oldValue) {},
          deep: true
     }
}

组件 component

简单使用

// 全局组件
Vue.component("content-a", {
    template: `<div>{{count}}</div>`,
    data() {
        return {
            count: 1
        };
    }
})

// 局部组件
components:{
    'contentA': {
        template: `<div>{{count}}</div>`,
    	data() {
        	return {
            	count: 1
        	};
    	}
    }
}

// 嵌套组件就是组件里还有component

组件之间的通信

  1. 父子传值
// 父组件
<son abc='123' :def='name'></son>
// 子组件
props: ['abc','def']  // props的用法与data用法一致
  1. 子父传值
// 子组件
this.$emit('abc',参数1...)
// 父组件
<son @abc='fn'></son>
methods:{
    fn(参数1...){}
}
  1. 非父子传值(兄弟传值)
// eventBus
// 原理就是new一个新的Vue实例当容器
const eventBus = new Vue()
export default eventBus

// 发送方
eventBus.$emit('事件名',参数1...)
// 创建事件方
eventBus.$on('事件名'function(参数1...){}) // 一般用在钩子函数里注册 这样发送方触发就会执行使用

// vuex 第二种传值就是

插槽slot

匿名插槽

<context-a>匿名插槽的内容</context-a> 

components:{
    contextA:{
        // 当插槽的内容不传是 默认显示slot中间的内容
        template:`
			<div> 
				<slot><slot>
				123
				<slot>后备内容<slot> 
			</div>`
    }
}

具名插槽

<context-a>
    // 废弃方法 替换为v-slot
    <div slot="aaa">aaa的具名插槽<div>
    // v-slot指令
    <template v-slot:aaa>aaa的具名插槽</template>
    <template #aaa>aaa的具名插槽</template> 
</context-a> 

components:{
    contextA:{
        template:`
			<div> 
				<slot name="aaa"><slot>
			</div>`
    }
}

作用域插槽

// 作用域插槽就是插槽向view中传值
<context-a>
    // 匿名作用域插槽
    <div slot-scope="obj">{{obj.a}}{{obj.b}}<div> // 具名叫slot就OK slot-scope以被淘汰 v-slot替换
    <template #default=aaa>{{obj.a}}{{obj.b}}</template> // 具名default换成插槽名
</context-a> 

components:{
    contextA:{
        template:`
			<div> 
				<slot a='1' :b='1+1'><slot>
			</div>`
    }
}

单页面应用 SPA

优点

  1. 速度快,切换模块不需要经过网络请求,用户体验好,因为前端操作几乎感受不到网络的延迟
  2. 完全**组件化开发 ,由于只有一个页面,所以原来属于一个个页面的工作被归类为一个个组件**.

缺点

  1. 首屏加载慢->按需加载 不刷新页面 之请求js模块
  2. 不利于SEO->SSR服务端渲染
  3. 开发难度高(框架) 相对于传统模式,有一些学习成本和应用成本

路由 vue-router

简单使用

<div id="app">
    // 声明式导航 
    // 编译后的结构相当于 <a herf="#/ys/勇士">勇士</a>
    <router-link to="/ys/勇士">勇士</router-link>
	// 路由匹配到的组件将渲染到这里
	<router-view></router-view>
</div>

var router = new VueRouter({
    routes: [
       // 动态路由使用  /:参数名   this.$route.params.参数名
       { path: '/ys/:name', component: { template: `<div>{{this.$route.params.name}}</div>` } }
    ]
});

new Vue({
    data:{},
    methods:{},
    // 挂载路由
    router
})

to属性的赋值

<!-- 常规跳转 -->
<router-link to="/sport">体育</router-link> 
<!-- 变量 -->
<router-link :to="path">体育</router-link> 
<!-- 根据对象name跳转 -->
<router-link :to="{name:'abcdefg'}">体育</router-link>
<!-- 根据对象path跳转 -->
<router-link :to="{path:'/sport'}">体育</router-link>
<!-- 带参数的跳转 -->
<router-link :to="{name:'abcdefg',params:{a:1}}">体育</router-link>

路由模式

// 默认是hash模式  通过#锚点来改变组件的 hashchange事件

// history模式
new VueRouter({
    mode: 'history',
    routes:[...]
})

编程式导航

// 跳转
this.$router.push({
    path: "/news"
});
// 简写
this.$router.push('/news')
// 替换
this.$router.replace('/news')
// 前进/后退
this.$router.go(数字)

嵌套路由

routes: [{
    path: "/",
    redirect: "hot"  // 重定向
}, {
    path: "/hot",
    component: { template: `<div>热点</div>` }
}, 
{
    path: "/music",
    component: {
       template: `
		<div>
			<router-link tag="li" to="/music/gd">古典</router-link>
			<router-view></router-view>
		</div>`,
     },
    // 二级路由
    children: [
        {
            path: "",
            component: { template: `<div>你喜欢什么音乐?</div>` }
        },
        {
            path: 'gd',
            component: { template: `<div>我爱古典音乐</div>` }
        }
    ]
}]

路由守卫

全局守卫

// 全局前置守卫
router.beforeEach((to, from, next) => {})

// 全局解析守卫
//和前置守卫类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用
router.beforeResolve

// 全局后置钩子
router.afterEach((to, from) => {})

独享守卫

// beforeEnter
routes: [
    {
        path: '/foo',
        component: Foo,
        beforeEnter: (to, from, next) => {
            // ...
        }
    }
]

组件内守卫

const Foo = {
    template: `...`,
    beforeRouteEnter (to, from, next) {
        // 在渲染该组件的对应路由被 confirm 前调用
        // 不!能!获取组件实例 `this`
        // 因为当守卫执行前,组件实例还没被创建
    },
    beforeRouteUpdate (to, from, next) {
        // 在当前路由改变,但是该组件被复用时调用
        // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
        // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
        // 可以访问组件实例 `this`
    },
    beforeRouteLeave (to, from, next) {
        // 导航离开该组件的对应路由时调用
        // 可以访问组件实例 `this`
    }
}

脚手架 vue-cli

# vue-cli脚手架的全局安装
npm i -g @vue/cli  ## 全局安装脚手架  默认安装的最新版本 3.0+
npm i -g @vue/cli-init  # 安装桥接工具 将 2.0+ 的功能补齐到目前的脚手架上
# vue-cli 2.0 创建项目
$ vue init webpack-simple 项目名 // webpack-simple 为模板名称 固定写法
# 切换到当前目录
$ cd 项目名 
$ npm install
# 在开发模式下 启动运行项目
$ npm run dev
# 3.0下创建项目
$ vue create 项目名 // create(创建) 为关键字
# 切换到当前目录
$ cd 项目名 
# 在开发模式下 启动运行项目
$ npm run serve

状态管理 vuex

五个属性:

  • state:存储数据,存储状态;在根实例中注册了store 后,用 this.$store.state 来访问;对应vue里面的data;存放数据方式为响应式,vue组件从store中读取数据,如数据发生变化,组件也会对应的更新。
  • getter:可以认为是 store 的计算属性,它的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
  • mutation:更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
  • action:包含任意异步操作,通过提交 mutation 间接更变状态。
  • module:将 store 分割成模块,每个模块都具有state、mutation、action、getter、甚至是嵌套子模块。
// ========== main.js
import store from './store'
new Vue({
    store
})
// ========== store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
    // 1. state  相当于data
    state: {count:10},
    // 2. getters  相当于computeds
    getters: {},
    // 3. mutations  相当于methods
    // this.$store.commit("方法名",...)
    mutations: {
        addCount: (state, 参数)=>{
            state.count += 参数
        }
    }
    // 4. actions 处理异步方法
    // this.$store.dispatch('异步方法名',...)
    actions: {
        asyncAddCount: (context, 参数)=>{
            setTimeout(()=>{
                context.commit('addCount', 参数)
            },1000)
        }
	},
    modules:{
        m1: {
            namespaced:true// state,getters,mutations,actions都存在
            // 使用 this.$store.state.模块名.数据名
        }
    }
})