指令
v-once:执行一次性地插值,当数据改变时,插值处的内容不会更新
v-html:双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html
v-text:更新元素的 textContent
。如果要更新部分的 textContent
,需要使用 {{ Mustache }}
插值
v-pre:跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译
v-cloak:这个指令保持在元素上直到关联实例结束编译。和 CSS 规则如 [v-cloak] { display: none }
一起用时,这个指令可以隐藏未编译的 Mustache 标签直到实例准备完毕
1 | [v-cloak] { |
计算属性是一个属性不需要函数调用方式进行使用,简写的默认为get方法,一般计算属性没有set方法,只读属性。
计算属性会进行缓存,多次使用计算属性之后调用一次
事件修饰符
.stop:停止冒泡
.prevent:阻止默认事件
.capture:添加事件监听器时使用事件捕获模式,内部元素触发的事件先在此处理,然后才交由内部元素进行处理
.self 只当在 event.target 是当前元素自身时触发处理函数
.once:点击事件将只会触发一次
按键修饰符
.enter .tab .delete
(捕获“删除”和“退格”键
.esc .space .up .down .left .right
config.keyCodes
对象自定义按键修饰符别名 Vue.config.keyCodes.f1 = 112
系统修饰键
.ctrl .alt .shift .meta(Mac下是 Command键,Windows 下是窗口键)
数据双向绑定 v-model
v-model
会忽略所有表单元素的 value
、checked
、selected
attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data
选项中声明初始值。
- text 和 textarea 元素使用
value
property 和input
事件; - checkbox 和 radio 使用
checked
property 和change
事件; - select 字段将
value
作为 prop 并将change
作为事件
修饰符:
.lazy 在默认情况下,v-model
在每次 input
事件触发后将输入框的值与数据进行同步,添加 lazy
修饰符,从而转为在 change
事件_之后_进行同步
数据在失去焦点或者回车才会更新
.number 将用户的输入值转为数值类型 无法被 parseFloat()
解析,则会返回原始的值
.trim 自动过滤用户输入的首尾空白字符
组件
组件data为什么是个函数?
函数每次执行后返回一个新的对象,组件之间的数据不会相互影响
is 属性挂在元素,可以规避HTML的限制。如 table标签只允许是 tr,td,th等表格元素,所以在table内直接使用组件是无效的。
父传子:props
组件里什么接受那些属性,props可以设置类型限制,提供一些默认值(react则还需使用prop-types库)
数据单向传递,子组件不能直接修改父组件数据
子传父:自定义事件
$emit,$on
不要v-model直接绑定props的属性到子组件
父子组件访问方式
1、使用$children 或者$refs reference引用
父访问子(子链)
ref 用来为子组件设置索引 , 可通过 this.$refs.comA.msg 来访问指定的实例
2、使用$parent $root
子访问父亲(父链)
非父子组件通信
1.0、$dispatch,$broadcast 前者用于向上级(只要是它的父级【一级或多级】)派发事件,后者 是由上级向下级广播事件,一旦发出事件,任何组件都能接收到,而且会在第一次接收到后停止冒泡,除非返回true
1 | $dispatch :由下往上广播 |
2.0、bus(中央事件总线,相当于一个中介,帮助组件间传递消息)
1 | var bus= new Vue (); |
slot插槽的使用
组件内部需要在某个位置显示外部传入的具体内容,使用slot标签进行占位,同时slot内部可以设置默认内容(直接在内部定义子元素,也可以是组件),外部传入内容会替换默认内容
具名插槽:slot标签上添加name属性,设置插槽具体名称,使用的时候标签添加slot属性并设置对应的名称
编译作用域:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
作用域插槽
1、父组件替换插槽的标签,内容由子组件提供
1 | <span> |
组件的高级用法
1 | 1、递归组件 |
其他
1 | $nextTick |
自定义指令
1 | 内置指令 |
Virtual Dom
1 | vNode对象 Vue.js源码定义: |
Render函数
1 | 要在合适的场景使用Render函数,否则只会怎加负担 |
插件
1 | MyPlugin.install = function (Vue, options ){ |
runtime-only ->代码里面不可以有任何template
runtime-compiler->代码含有template,compiler可以编译template
el和template的关系:当el和template同时出现的时候,template中的代码会替代el挂载的DOM元素
1、runtime-compiler 和 runtime-only 的运行原理(运行过程)?
runtime-compiler:template->ast(abstract syntax tree)->render->virtual dom->UI
runtime-only:性能更高、代码量更少:render->virtual dom->UI
2、npm install vue-loader vue-template-compiler –save-dev中的vue-template-compiler的作用是什么?
vue-template-compiler将vue中的template转换成render
3、Runtime-Compiler和Runtime-only的选择使用情况?
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only
vue-cli 3创建项目
vue create 项目名称
vue-router
使用:导入vue和vue-router
1、通过vue.use(插件)安装插件
2、创建VueRouter对象
3、配置routes映射关系,导处router
4、main.js把router对象挂载在vue实例上
路由的默认值和修改history模式:
使用redirect重定向,配置创建VueRouter对象时候传入第二个参数mode为history或者为hash
1 | <router-link to="/home">Go to home</router-link> |
编程式导航
在 Vue 实例内部,你可以通过 $router
访问路由实例。因此你可以调用 this.$router.push
router.push、 router.replace 和 router.go 跟 window.history.pushState、 window.history.replaceState 和 window.history.go好像, 实际上它们确实是效仿 window.history API 的
1 | // 字符串 |
如果提供了 path
,params
会被忽略
router配置对象
1 | //未解耦 |
命名视图
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes
配置中给某个路由设置名称。
1 | //动态路由匹配 path: '/user/:userId', |
要链接到一个命名路由,可以给 router-link
的 to
属性传一个对象
1 | <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> |
其实写router-link或者编程式导航是否传递数据跟路由匹配应该区分开来,路径匹配是路由路径匹配,也就是不用动态路由也可以进行传参数,动态路由只是一种匹配模式
嵌套路由
1、创建对应子组件,在路由映射配置对应子路由
2、在组建内部使用
传递参两种方式params和query
params类型:
1、配置路由格式:/router/:id
传递方式:path后面跟上对应的值
传递后路径类似于:/router/123,router/abc
2、动态路由匹配
配置路由格式:/router/:id
const router = new VueRouter({
routes: [
{
path: ‘/user/:userId’,
name: ‘user’,
component: User
}
]
})
传递方式:
如果提供了 path
,params
被忽略
传递后路径类似于:/router/123,router/abc
query类型:
配置路由格式:/router 普通配置格式
传递方式:使用query的key作为传递 :to={ path: ‘register’, query: { plan: ‘private’ }}
传递后路径:
/register?plan=private
完整的导航解析流程
1 |
|
路由元数据:定义路由的时候可以配置 meta
字段
routes
配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录
例如,根据上面的路由配置,/foo/bar
这个 URL 将会匹配父路由记录以及子路由记录。
一个路由匹配到的所有路由记录会暴露为 $route
对象 (还有在导航守卫中的路由对象) 的 $route.matched
数组。因此,我们需要遍历 $route.matched
来检查路由记录中的 meta
字段。
1 | router.beforeEach((to, from, next) => { |
过渡
1 | //可以动态设置 动画效果 |
Vuex
由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性 (opens new window)中返回某个状态:
1 | // 创建一个 Counter 组件 |
每当 store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM
- 应用层级的状态应该集中到单个 store 对象中。
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
- 异步逻辑都应该封装到 action 里面。
只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。
对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:
1 | ├── index.html |
由来?
组件之间通信成了必不可少的开发需求,完成非关系型组件数据共享
父传子->props
子传父亲->$emit
兄弟节点->eventBus->公共$emit
$on和$emit的事件必须是在一个公共的实例上才能触发
新建eventBus.js
1 | import Vue from 'vue' |
组件1监听
1 | import eventBus from './eventBus' |
组件2触发
1 | import eventBus from './eventBus' |
Vue.set() —>响应式 dep->watch观察者模式
delete、[]、不是响应式
Vue.delete()—>响应式 :不是响应式设置为响应式
既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
- 最好提前在你的 store 中初始化好所有所需属性。
- 当需要在对象上添加新属性时,你应该
使用
Vue.set(obj, 'newProp', 123)
[ this.$set(this.obj, ‘newprop’, 123) ]或者以新对象替换老对象。例如,利用对象展开运算符 (opens new window)我们可以这样写:
1
state.obj = { ...state.obj, newProp: 123 }
State
1 | Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中(需调用 Vue.use(Vuex)): |
Getters
1 | 有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数: |
Mutation
1 | 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。 |
Action
1 | Action 类似于 mutation,不同在于: |
modules
1 | const moduleA = { |
总结:
state:共享的状态
修改state状态:要使用 Vue.set(), 或 对象替换{ …state.obj, newProp: 123 }
getters
对state中数据 统计,过滤,派生
mutation
只有这里直接操作 state 数据,并都是同步事务。store.commit() 触发方法
action
弥补mutation不能是异步的不足,store.dispatch()分发action事务
其他-拓展
父子组件传值方式
除了 props, v-model, $emit/$on
ref: 父组件可以通过引用获取调用子组件属性或方法
$children
:获取到一个包含**所有子组件(不包含孙子组件)**的VueComponent
对象数组,可以直接拿到子组件中所有数据和方法等
$parent
:获取到一个父节点的VueComponent
对象,同样包含父节点中所有数据和方法等$attrs
:包含父作用域里除 class 和 style 除外的非 props 属性集合。通过
this.$attrs获取父作用域中所有符合条件的属性集合,然后还要继续传给子组件内部的其他组件,就可以通过
v-bind=”$attrs” 将父组件属性传递给内部子组件
$listeners
:包含父作用域里.native
除外的监听事件集合。如果还要继续传给子组件内部的其他组件,就可以通过v-on="$linteners"
使用方式是相同的。将父组件方法传递给内部子组件$root: 访问根组件中的属性或方法,是根组件,不是父组件。$root只对根组件有用
.sync
类似于v-model语法糖,也是通过 $emit/$on 实现
Parent.vue:
1
2
3
4
5
6
7
8
9
10
11
12
<template>
<child :page.sync="page"></child>
</template>
<script>
export default {
data(){
return {
page:1
}
}
}Child.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<script>
export default {
props:["page"],
computed(){
// 当我们在子组件里修改 currentPage 时,父组件的 page 也会随之改变
currentPage {
get(){
return this.page
},
set(newVal){
this.$emit("update:page", newVal)
}
}
}
}
</script>provide/inject
在父级注入,然后可以在该父级任意子孙级组件引用
父级注入:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 父组件
export default{
// 方法一 不能获取 methods 中的方法
provide:{
name:"oldCode",
age: this.data中的属性
},
// 方法二 不能获取 data 中的属性
provide(){
return {
name:"oldCode",
someMethod:this.someMethod // methods 中的方法
}
},
methods:{
someMethod(){
console.log("这是注入的方法")
}
}
}后代组件引用:
1
2
3
4
5
6
7export default{
inject:["name","someMethod"],
mounted(){
console.log(this.name)
this.someMethod()
}
}
$event
1 | 使用场景 |
v-model v2版本
多选日期组件写法1
1 | <!-- |
多选日期组件写法2
1 | <!-- |
组件使用
1 | 写法一调用 |
- 本文作者: 王不留行
- 本文链接: https://wyf195075595.github.io/2022/06/17/programming/vue/基础语法2.0/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!