对象属性
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
组件之间的通信
- 父子传值
// 父组件
<son abc='123' :def='name'></son>
// 子组件
props: ['abc','def'] // props的用法与data用法一致
- 子父传值
// 子组件
this.$emit('abc',参数1...)
// 父组件
<son @abc='fn'></son>
methods:{
fn(参数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
优点
- 速度快,
切换模块不需要经过网络请求,用户体验好,因为前端操作几乎感受不到网络的延迟 - 完全**
组件化开发 ,由于只有一个页面,所以原来属于一个个页面的工作被归类为一个个组件**.
缺点
首屏加载慢->按需加载不刷新页面 之请求js模块不利于SEO->SSR服务端渲染- 开发难度高(框架) 相对于传统模式,有一些学习成本和应用成本
路由 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.模块名.数据名
}
}
})