每周总结|每周总结 20210801 vue文档学习
vue学习 箭头函数
function() => {}
js位置 JavaScript代码可以直接嵌在网页的任何地方,不过通常我们都把JavaScript代码放到
中;可以在同一个页面中引入多个.js文件,还可以在页面中多次编写
,浏览器按照顺序依次执行。由于浏览器的安全限制,以file://开头的地址无法执行如联网等JavaScript代码,最终,你还是需要架设一个Web服务器,然后以http://开头的地址来正常执行所有JavaScript代码。
js分号 JavaScript并不强制要求在每个语句的结尾加;
数字判断 唯一能判断NaN的方法是通过
isNaN()
函数要特别注意相等运算符==。JavaScript在设计时,有两种比较运算符:
第一种是==比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是===比较,它不会自动转换数据类型,如果数据类型不一致,返回false,如果一致,再比较。
这不是JavaScript的设计缺陷。浮点数在运算过程中会产生误差,因为计算机无法精确表示无限循环小数。要比较两个浮点数是否相等,只能计算它们之差的绝对值,看是否小于某个阈值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001;
// true
动态语言与静态语言 变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。
动态参数
...
当
eventName
的值为"focus"
时,v-on:[eventName]
将等价于v-on:focus
。v-bind v-bind:属性,单向绑定?
v-on 事件监听,
v-on:click=""
,简写@click=""
2.6.0新增动态参数,可以根据条件响应不同的事件
需要注意的是,动态表达式中更不要有引号和空格,因为对于html的attribute名来说这些符号无效,同时浏览器会将attribute名转为小写,所以也不要有大写字符
防抖与节流 有些函数如mousemove触发的函数会在短时间内连续调用多次,如果要使其在一段事件内只执行一次函数,就需要防抖与节流.
防抖:每隔一段事件才触发一次
节流:连续触发后,每隔一段时间才处理一次
//防抖
function debounce(fn, wait) {
let timeout = null
return function() {
if(timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait);
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))
计算属性 一般来说,模板要求简单的、声明性的,如
{{label}}
,但是有时会过于复杂如:{{ author.books.length > 0 ? 'Yes' : 'No' }}
虽然代码可以工作,但是过于复杂,推荐使用计算属性来声明
{{ publishedBooksMessage }}
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` points to the vm instance
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
计算属性与方法比较:计算属性在响应式依赖改变时才会重新求值,而函数在每次调用时都会重新执行
{{ countBooks1() }}
{{ countBools2 }}
methods:{
countBooks1() {
return books.length
}
},
computed:{
countBooks2() {
return books.length
}
}
计算属性可以设置setter和getter
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
侦听器watch 可以在响应式数据变化的时候执行函数,相比于计算属性,watch可以执行异步操作如访问api,但是开销比计算属性大
watch: {
// whenever question changes, this function will run
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
}
truthiness真值 在js中,除了
false
、0
、""
、null
、undefined
和NaN
之外都为真值。if (true)
if ({})
if ([])
if (42)
if ("foo")
if (new Date())
if (-42)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
:class
:class="{ active: isActive }"
class为isActive
值,当isActive
为nul
时,没有class。此外,
:class
可以与class
属性共存,:class
内也可以有多个值,或者使用数组来提供class
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
:style语法
:style
的对象语法十分直观——看着非常像CSS,但其实是一个JavaScript对象。CSS property名可以用驼峰式(camelCase)或短横线分隔(kebab-case,记得用引号括起来)来命名条件渲染 条件渲染有两种:
v-if
和v-show
。v-if
只有在条件为真时才渲染条件快,可以和v-else-if
和v-else
配合使用。v-show
总是会被渲染,真假值变化体现为css的变化v-for 可以来对应数组,也可以对应对象。
对应数组时,两个参数依次分别表示值和索引;
对应对象时,三个参数依次分别表示值、键和索引。
-
{{ parentMessage }} - {{ index }} - {{ item.message }}
{{ index }}. {{ name }}: {{ value }}
当v-for对应的数据中的数据项改变了顺序,vue不会移动DOM元素来匹配数据,而是使用“就地更新”的策略,如果想要对应的DOM元素改变位置,需要添加
:key
属性数组更新检测 数组变更
以下函数可以触发视图更新
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
数组替换
以下函数可以保留原来数组,且返回新的数组
filter()
concat()
slice()
v-for
中使用计算属性或者方法在组件上使用v-for 因为组件自己独立的作用域,所以在定义组件的时候要使用
props
来传递参数。
const app = Vue.createApp({
data() {
return {
newTodoText: '',
todos: [
{
id: 1,
title: 'Do the dishes'
},
{
id: 2,
title: 'Take out the trash'
},
{
id: 3,
title: 'Mow the lawn'
}
],
nextTodoId: 4
}
},
methods: {
addNewTodo() {
this.todos.push({
id: this.nextTodoId++,
title: this.newTodoText
})
this.newTodoText = ''
}
}
})app.component('todo-item', {
template: `
{{ title }}
`,
props: ['title']
})app.mount('#todo-list-example')
事件处理 若在事件处理中要访问原始的DOM事件,可以用特殊变量$event传入方法
warn(message, event) {
if (event) {
event.preventDefault()
}
}
一个事件可以有多个方法处理,方法间使用逗号分隔
event.preventDefault() 与 event.stopPropagation()
event.preventDefault()
阻止事件的默认动作发送,比如点击勾选框不能切换勾选状态、在input框输入非规定内的字符就无法输入等等。event.stopPropagation()
仍会执行默认动作,但是执行完后事件不再被分派到其他节点。js冒泡与捕获 首先我们需要形成监听器的思想。在不使用任何框架的情况下,我们在js中通过
addEventListener
方法给Dom添加事件监听。这个方法直译就是添加事件监听器。我们对Dom的操作作为事件会从最外面的祖先Dom逐步传递到目标Dom(捕获过程),然后再从目标的Dom原路传出去(冒泡过程)。通常我们只监听冒泡过程。在vue中,当我们添加了事件修饰符capture
后,才会变成捕获监听器。所以vue中的
.stop
修饰符的停止传播就容易理解了,一般来说在冒泡监听时,是有内层的子DOM开始到外层的祖先DOM,设置了.stop
后,在本DOM处理事件后,事件便不再冒泡。而
.self
可以理解为跳过冒泡事件和捕获事件,只有直接作用在该元素上的事件才可以执行。事件修饰符
.stop
执行事件后停止传播.prevent
不执行默认动作,相当于执行event.preventDefault()
.capture
由冒泡监听改为捕获监听.self
跳过冒泡事件和捕获事件,只有直接作用在该元素上的事件才可以执行.once
只执行一次.passive
不会执行event.preventDefault()
.enter
.tab
.delete
(捕获“删除”和“退格”键).esc
.space
.up
.down
.left
.right
Do something
键盘修饰键
.ctrl
.alt
.shift
.meta
.left
.right
.middle
.exact
修饰符.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。
v-model 对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值)
v-model
有三种修饰符.lazy
在“change”时而非“input”时更新.number
将用户的输入值转为数值类型,如果这个值无法被 parseFloat() 解析,则会返回原始的值.trim
自动过滤用户输入的首尾空白字符
new Vue
接收相同的选项,例如data
、computed
、watch
、methods
以及生命周期钩子等。通过component
可以进行全局注册。// 定义一个名为 button-counter 的新全局组件
app.component('button-counter', {
data() {
return {
count: 0
}
},
template: `
`
})
prop
通过
prop
定义属性并向子组件传递数据const app = Vue.createApp({})app.component('blog-post', {
props: ['title'],
template: `{{ title }}`
})app.mount('#blog-post-demo')
监听子组件事件
通过使用
$emit
来传入外部的事件名称,也可以将内部参数传出。
app.component('blog-post', {
props: ['title'],
template: `{{ title }}
`
})
实现组件的v-model双向绑定
为了在组件中可以使用
v-model
,组件需要向外暴露出一个接受的prop
,并且向内规定该数据的getter
和setter
。getter
、setter
可以通过计算属性实现。
app.component('custom-input', {
props: ['modelValue'],
template: `
`,
computed: {
value: {
get() {
return this.modelValue
},
set(value) { this.$emit('update:modelValue', value)
}
}
}
})
简单插槽
组件中在需要插入的位置使用
标签,在使用组件时直接用组件名标签包裹。
Something bad happened.
app.component('alert-box', {
template: `Error!`
})
动态加载组件
使用属性
:is
可以地将简单组件载入到该位置。
const tabs = [
{
name: 'Home',
component: {
template: `Home component`
}
},
{
name: 'Posts',
component: {
template: `Posts component`
}
},
{
name: 'Archive',
component: {
template: `Archive component`
}
}
]const app = Vue.createApp({
data() {
return {
tabs,
currentTab: tabs[0]
}
},
computed: {
currentTabComponent() {
return 'tab-' + this.currentTab.toLowerCase()
}
}
})app.component('tab-home', {
template: `Home component`
})
app.component('tab-posts', {
template: `Posts component`
})
app.component('tab-archive', {
template: `Archive component`
})app.mount('#dynamic-component-demo')
特殊DOM解析注意事项
形如
、
、
等等这些标签对于哪些子标签可以出现在其内部是由严格规定的(比如可以出现在中)。而有些标签如
、和
等只能出现在特定的元素内部。如果在这些特定标签内部使用自定义的组件,可能会导致出错。此时可以使用v-is
属性来帮助解析组件。
深入组件
组件命名
建议使用kebab-case (短横线分隔命名)
局部注册
局部注册需要引用
import ComponentA from './ComponentA.vue'export default {
components: {
ComponentA
}
// ...
}
prop类型
prop
可以设置类型,在设置错误时会在控制台提示用户。
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // 或任何其他构造函数
}
动态传入Prop
在传入值时,由两种方式:
静态赋值vue会视为一个字符串,而v-bind
或缩写:
告诉vue这是一个js表达式。
特别地,当一个对象的所有属性都需要传入时,可以使用不带参数的v-bind
。
post: {
id: 1,
title: 'My Journey with Vue'
}
单向数据流
我们已经知道,prop
中定义外部传入的数据。如果我们希望这些数据成为本地数据,可以供子组件使用,并且在数据更新时,子组件也会更新,与此同时反过来不行(会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解)的话,可以将定义在prop
中的属性定义为一个data property
或者计算属性。
// 定义为data
props: ['initialCounter'],
data() {
return {
counter: this.initialCounter
}
}
// 定义为计算属性
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
prop数据验证
可以定义数据类型、指定默认值和自定义验证规则。
app.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function() {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function(value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
},
// 具有默认值的函数
propG: {
type: Function,
// 与对象或数组默认值不同,这不是一个工厂函数 —— 这是一个用作默认值的函数
default: function() {
return 'Default function'
}
}
}
})
非Prop的Attribute继承
非Prop的Attribute,指的是不定义在prop
中的属性,如class
、id
、style
等等。在外部使用组件时并使用这些属性时,默认会继承给组件内部的根元素;如果根元素有多个或者想要继承到非根元素,可以使用v-bind="$attrs"
($attrs
包括组件props
和emits property
中未包含的所有属性 (例如class
、style
、v-on
监听器等)。)来选定一个DOM元素继承。
事件监听器的继承也同理,会默认继承到组件内部根元素。
需要注意的是,如果要使非根节点继承,需要在组件的选项中设置inheritAttrs: false
。
app.component('date-picker', {
inheritAttrs: false,
template: ``
})
自定义事件
命名推荐使用kebab-case
(短横线连接)的事件名,因为v-on
事件监听器在DOM模板中会被自动转换为全小写。自定义事件可以和prop
属性一样进行验证。
app.component('custom-form', {
emits: {
// 没有验证
click: null,// 验证submit 事件
submit: ({ email, password }) => {
if (email && password) {
return true
} else {
console.warn('Invalid submit event payload!')
return false
}
}
},
methods: {
submitForm() {
this.$emit('submit', { email, password })
}
}
})
v-model参数与多个v-model绑定
在组件中,在prop
中定义的属性,在外部可以用v-model:属性名
的方式来进行多个v-model
绑定。
自定义v-model修饰符
在组件中更可以自定义v-model修饰符。但是需要注意的是,修饰符的具体方法是写在属性的setter函数中,并且修饰符的名称为arg + "Modifiers"
。
{{ myText }}
const app = Vue.createApp({
data() {
return {
myText: ''
}
}
})app.component('my-component', {
props: {
name: String,
nameModifiers: {
default: () => ({})
}
},
methods: {
emitValue(e) {
let value = https://www.it610.com/article/e.target.value
if (this.modelModifiers.capitalize) {
value = value.charAt(0).toUpperCase() + value.slice(1)
}
this.$emit('update:name', value)
}
},
template: ``
})app.mount('#app')
插槽
在组件的模板中可以定义
标签,可以替换为字符串、html代码或其他组件。当
标签中间有内容时,这部分内容会作为默认。
具名插槽
在需要多个插槽的情况下,为了识别不同的插槽,需要给每一个插槽一个名字name
,不带name
的插槽会有一个隐含的名字“default”。在外部使用组件的具名插槽的时候,使用
的v-slot
指示插槽名称。注意必须使用v-slot
时必须在
标签中。
Here might be a page title
A paragraph for the main content.
And another one.
Here's some contact info
若想让外部访问组件内部的数据(比如用在插入内容时需要组件内部数据),可以将组件模板中插槽的属性设置为数据。
{{slotProps.item}}
由于v-slot
的值是作为函数参数作用的,所以可以写成任何能够作为函数定义中的参数的JavaScript表达式。
{{ todo }}
{{ item }}
v-slot
同样可以使用动态参数
具名插槽的缩写
只有在有参数的情况下才可以缩写,使用#
代替v-slot
。
{{ item }}
提供与注入
如果在一个多层嵌套的组件链中,内层的组件要获得外层组件的数据,有两种方法:
【每周总结|每周总结 20210801 vue文档学习】第一种是前面讲过的设置prop
,但是不方便的是这需要在每一层组件都设置prop
,开发上稍微有点麻烦;
第二种是父组件提供数据,子组件注入数据的模式,我们可以使用provide
和inject
对。父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个provide
选项来提供数据,子组件有一个inject
选项来开始使用这个数据。
注入的数据默认是非响应式的,如果想要响应式的数据注入,需要分配一个组合式API computed
属性。
// 父组件提供
app.component('todo-list', {
data() {
return {
todos: ['Feed a cat', 'Buy tickets']
}
},
provide() {
return {
todoLength1: this.todos.length,
todoLength2: Vue.computed(() => this.todos.length) //响应式
}
},
template: `
...
`
})app.component('todo-list-statistics', {
inject: ['todoLength'],
created() {
console.log(`Injected property: ${this.todoLength1}`) // > 注入 property: John Doe
}
})
保活标签keep-alive
在一些场景比如切换标签页中,不停地切换标签页会不断地重新渲染组件。使用保活标签
可以保持这些组件的状态,以避免反复重渲染导致的性能问题。
异步组件
不是很懂,目前也暂时用不到,等第二次阅读时再细究。
模板引用
如果需要在js中访问组件,可以使用ref
为组件或HTML元素指定引用ID。注意,由于$refs
只会在组件渲染完成之后生效,应该避免在模板或计算属性中访问$refs
。
const app = Vue.createApp({})app.component('base-input', {
template: `
`,
methods: {
focusInput() {
this.$refs.input.focus()
}
},
mounted() {
this.focusInput()
}
})
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 7.9号工作总结~司硕
- 最有效的时间管理工具(赢效率手册和总结笔记)
- 九月计划
- 数据库总结语句
- 周总结|周总结 感悟
- 周总结43
- 参加【21天写作挑战赛】,第七期第14天,挑战感受小总结
- 第二阶段day1总结
- 新梦想91期特训班两天一晚学习感想及总结(学生(魏森林))
- 周总结(10.5-10.11)