< script >标签:需要下载官方vue.js版本,然后通过< script >标签在**.html**文件里引入
NPM:
CDN:直接复制< script src=“https://cdn.jsdelivr.net/npm/vue/dist/vue.js”>< /script >
CLI命令行工具:直接创建 .vue文件
注意点:一旦引入vue,就会暴露一个全局变量 Vue( )。Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $
,以便与用户定义的属性区分开来。
字符串模板与DOM模板:
{
{sometext}}
{
{sometext}}
< p >就是DOM模板,在vue中会先获取DOM内容缓存下来,然后绑定数据,当数据发生变化,利用之前缓存的模板,重新绑定数据并渲染;
< some-tag>就是字符串模板,唯一区别就是js不用获取直接就可以拿到,获取到模板后缓存下来就一样了
为什么要区分字符串模板和DOM模板?就是自定义标签,主要会有如下结构出现:
<table>
<my-tr>my-tr>
<my-tr>my-tr>
<my-tr>my-tr>
table>
因为W3C规定,table中只能有tr,td等不能有其它的,所有DOM获取不到my-tr,而字符串模板就仅仅是个字符串,与规定无关,所以可以随便写,只要最终编译出来的结构符合W3C要求就行
插值:{ { }}
通过使用 v-once 指令,能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上的其它数据绑定:
这个将不会改变: {
{ msg }}
通过v-html可以输出真正的HTML标签(双大括号会将数据解释为普通文本,而非 HTML 代码)
避免用大写命名键名,如:
...
修饰符 .
.prevent:
模板内的表达式应该非常便利,放入太多的逻辑会让模板过重且难以维护,对于任何复杂逻辑,都应当使用计算属性。
计算属性 VS 方法:
Computed reversed message: "{
{ reversedMessage }}"
Reversed message: "{
{ reversedMessage() }}"
计算属性 VS 侦听属性
Watch侦听器,只有当自己的值被改变的时候才会触发watch里的函数执行,否则改变与之无关的数据的值的时候,watch里的函数不会执行
当有一些数据需要随着其它数据变动而变动时,不要滥用侦听属性,更好的做法是使用计算属性而不是命令式的 watch
回调(侦听器watch只有才数据发生改变,执行异步或开销较大的操作的时候使用)
{
{ fullName }}
计算属性的setter
计算属性默认只有 getter ,不过在需要时也可以提供一个 setter :
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
可以传入多个属性来动态切换多个class
绑定的多个属性可以写在一个对象里,不必全内联定义在模板里
三元表达式
数组语法中的对象语法
注意点:在一个自定义组件上使用 class
属性时,这个自定义组件上已经存在的 class 不会被覆盖。
内联样式style
用法与class一样
v-if、v-else-if、v-else同时使用时:
A
B
C
Not A/B/C
添加key值,表示独立唯一性,不会被复用
v-show与v-if用法一样,不一样的是v-show
只是简单地切换元素的 CSS 属性 display
。带有 v-show
的元素始终会被渲染并保留在 DOM 中,而v-if为false时会删除DOM元素
注意点:
v-show
不支持 元素,也不支持
v-else
。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
不推荐同时使用 v-if
和 v-show
。当 v-if
与 v-show
一起使用时,v-show
具有比 v-if
更高的优先级。
v-for 遍历数组:
-
{
{ parentMessage }} - {
{ index }} - {
{ item.message }}
可以用 of
替代 in
作为分隔符,因为它更接近 JavaScript 迭代器的语法:
用 v-for
来遍历一个对象的属性:
-
{
{ value }}
键值对形式:
{
{ name }}: {
{ value }}
用第三个参数作为索引:
{
{ index }}. {
{ name }}: {
{ value }}
给 v-for 提供key值,以便跟踪每一个节点的身份
数组变更检测注意事项:
Vue 不能检测以下数组的变动:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
解决方法:
第1个:有两种解决方法可以实现通过索引值设置一个数组项
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
//也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名
vm.$set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
第二个:通过splice修改数组的长度
vm.items.splice(newLength)
对象变更检测注意事项
Vue 不能检测对象属性的添加或删除:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的,检测不到
解决方法:
可以使用 Vue.set(object, propertyName, value)
方法向嵌套对象添加响应式属性
var vm = new Vue({
data: {
user: {
name: 'Anika'
}
}
})
Vue.set(vm.user, 'age', 27)
//或者vm.$set(vm.userProfile, 'age', 27)
为已有对象创建多个属性:使用 Object.assign(target, ...sources)
或 _.extend()
//Object.assign() 方法将所有的遍历的属性的值从一个或多个源对象复制到目标对象,返回目标对象
vm.user = Object.assign({
}, vm.user, {
age: 27,
favoriteColor: 'Vue Green'
})
显示过滤/排序后结果
v-for可以遍历计算属性/方法
- {
{ n }}
在计算属性不适用的情况下 (例如,在嵌套 v-for
循环中) 可以使用一个方法:
- {
{ n }}
注意事项
不推荐在同一元素上使用 v-if
和 v-for
。当它们处于同一节点,v-for
的优先级比 v-if
更高,这意味着 v-if
将分别重复运行于每个 v-for
循环中。
如果你的目的是有条件地跳过循环的执行,那么可以将 v-if
置于外层元素:
-
{
{ todo }}
No todos left!
由于 ul中只能放置 li元素,如果将组件标签< todo-item>< /todo-item>直接放进 ul中会出现浏览器解析错误。所以这里使用is属性,声明该 li是 todo-item组件。
**事件修饰符:**使用时顺序很重要
.stop
.prevent
.capture
.self
.once
.passive
...
...
按键修饰符:
.enter
.tab
.delete
(捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
// 可以通过全局 config.keyCodes 对象自定义按键修饰符别名
Vue.config.keyCodes.f1 = 112
**系统修饰符:**配合鼠标或者键盘事件实现相应的触发
.ctrl
.alt
.shift
.meta
Do something
.exact
修饰符:是为了限制系统修饰符
v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据
v-model
会忽略所有表单元素的 value
、checked
、selected
特性的初始值而总是将 Vue 实例的数据作为数据来源。所以应该在 data
选项中声明初始值。
v-model
中的属性(如message)需要在三处引用,一是表单< input >,二是其它DOM如< p>中,三是vue实例中
在文本区域插值 () 并不会生效,应用
v-model
来代替。
{
{ message }}
用v-for渲染的动态选项:
Selected: {
{ selected }}
checkbox
的值是boolean
类型
要写type属性确认,用value赋值,id区分
true-value
和false-value
用指定值替换默认的true
或false
,即当选中后,变量toggle
的值不再是true
,而是yes
;当撤销选中后,变量toggle
的值不再是false
,而是no
;
修饰符
.lazy
:添加.lazy修饰符之后,双向数据绑定不起作用,此时当输入框失去焦点后触发change事件双向数据才会同步
.number
:自动将输入值转为数值类型
.trim
:过滤首尾空白字符
命名:两种方式
1、全小写,并且用连字符Vue.component('my-component-name', { /* ... */ })
2、全驼峰形式Vue.component('MyComponentName', { /* ... */ })
只有第一种直接在DOM中使用才有效
局部注册:
局部注册的组件在其子组件中使用:
//ComponentA 在 ComponentB 中可用
var ComponentA = {
/* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
或通过 Babel 和 webpack 使用 ES2015 模块:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
所有的组件都是可复用的vue实例;所以组件与 new Vue
接收相同的选项,例如 data
、computed
、watch
、methods
以及生命周期钩子等。
一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: ''
})
Prop类型:这些属性的名称和值分别是 prop 各自的名称和类型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
类型检查:type
Vue.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
}
}
}
})
父组件向子组件传值:prop
一般默认Vue.component里定义的template部分是子组件,HTML中组件标签为父组件。
prop传值
在不清楚要渲染的具体内容时,使用 v-bind来动态传递 prop是非常有用的。
在传递一个数字、一个布尔值、一个数组、一个对象都要用v-bind来告诉vue,这是一个 JavaScript 表达式而不是一个字符串。
而传入一个对象的所有属性时,可以使用不带参数的v-bind:
监听子组件事件
.native
将原生事件绑定到组件,主要是给自定义的组件添加原生事件。
<base-input @focus.native="onFocus">base-input>
直接给普通的标签加native是无效的;直接给组件添加原生事件也是无效的,因为解析后浏览器不知道要把这个事件添加到哪一个标签上。所以结合起来要想在组件中添加原生事件必须加**.native**
<div id="app">
<button @click.native="clickFn">按钮button>
div>
$listeners
属性,它是一个对象,里面包含了作用在这个组件上所有的监听器,配合 v-on="$listeners"
将所有的事件监听器指向这个组件的某个特定的子元素。类似于继承效果,即子组件继承了父组件的事件https://blog.csdn.net/songxiugongwang/article/details/84001913#commentBox
.sync
在vue2.4以前,父组件向子组件传值用props;子组件不能直接更改父组件传入的值,需要通过 e m i t 触 发 自 定 义 事 件 , 通 知 父 组 件 改 变 后 的 值 。 比 较 繁 琐 , 所 以 ‘ . s y n c ‘ 只 是 对 以 前 的 emit触发自定义事件,通知父组件改变后的值。比较繁琐,所以`.sync`只是对以前的 emit触发自定义事件,通知父组件改变后的值。比较繁琐,所以‘.sync‘只是对以前的emit方式的一种缩写,
this.$emit('update:title', newTitle)
.sync
其实就是在父组件定义了一个update:val
方法,来监听子组件修改值的事件。
当要设置多个prop的时候,可以用一个对象接收:
v-model一般是表单组件,绑定的是value属性,实现双向绑定比较单一;
sync是指父子组件之间的通信,比较灵活;v-model 是 .sync的一种体现。两者的本质都是语法糖,目的都是实现组件与外部数据的双向绑定。
使用事件抛出一个值
使用 $emit
的第二个参数:
在组件中使用v-model
自定义组件的v-model:model
默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event。所以当在自定义组件上使用v-model并不能实现双向绑定,因为自定义的组件并没有默认的value和input事件。
在使用时,我们需要显式的去声明定义这些东西,这时候就需要model,在定义组件的时候,指定prop的值和监听的事件。完整代码示例:
{
{name}}
插槽
插槽作用:在子组件内添加一个< slot>< /slot>插槽,在父组件标签内放的内容就可以显示出来,否则没有插槽的情况下在父组件标签内的一些内容是不起任何作用的
你好
你好
后备内容:即在< slot>< /slot>中添加内容
若是在父组件标签内添加了内容,则后备内容会被覆盖不显示
作用域插槽:即可以让后备内容访问到子组件中才有的数据
需要在< slot>中绑定一个属性,这样后备内容才可以访问到数据,绑定在
元素上的属性被称为插槽 prop
{
{ user.firstName }}
可以给插槽prop命名:
{
{ slotProps.user.firstName }}
解构插槽prop:使用ES6解构来传入具体的插槽 prop
{
{ user.firstName }}
{
{ person.firstName }}
具名插槽:就是给插槽起个名字,
元素有一个特殊的特性:name
。而没有名字的就是默认插槽
父组件在使用具名插槽的时候需要使用,子组件只需要
女人:漂亮、美丽、购物、逛街
男人:帅气、才实
我是一类人,我是默认的插槽
具名插槽的缩写:v-slot:header
可以被重写为 #header
,必须要有参数才能缩写,否则无效;如果使用缩写的话,必须始终以明确插槽名取而代之:
{
{ user.firstName }}
动态切换组件
不具有缓存:
用
可以在组件第一次被创建的时候缓存下来:
异步组件
Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: 'I am async!'
})
}, 1000)
})
推荐做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用:
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
解析DOM模板注意事项
有些 HTML 元素,诸如 需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的: 禁用特性继承:不希望组件的根元素继承特性,可以在组件的选项中设置 注意 $attrs–继承所有的父组件属性(除了prop传递的属性、class 和 style ) inheritAttrs:默认值true,继承所有的父组件属性(除props的传递的属性),比$attrs继承多了class和style 通过 混入对象用来分发组件中可复用的功能,包含任意组件选项 定义一个混入对象: 使用混入对象: mixins: [myMixin] 选项合并:当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并,并在发生冲突时以组件数据优先。 同名钩子函数将合并为一个数组,因此都将被调用。,混入对象的钩子先被调用。组件自身的钩子函数后被调用 注册一个全局指令: 注册一个局部指令: 可以在模板中任何元素上使用新的 钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选): 钩子函数的参数 :一个对象,包含以下属性: 除了 使用这些钩子参数的自定义组件的案例: 结果: name: “demo” 只有当实例被创建时就已经存在于 框架就是必须要按照它框架的要求格式来书写代码,不然执行不了。 Console.log(vm.a)是更新之后的100 console.log(vm.$el.innerHTML)是更新之前的10 可以使用vue提供的$nextTick方法: 可以使用vm.$mount(‘#app’)代替el:’#app’ 不要在箭头函数里使用this,因为箭头函数并没有
、
、 和
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如
、
和 ,只能出现在其它某些特定的元素内部。
template: '...'
).vue
)inheritAttrs: false
Vue.component('my-component', {
inheritAttrs: false,
// ...
})
inheritAttrs: false
选项不会影响 style
和 class
的绑定。inheritAttrs: false
和 $attrs(可以让继承生效)
,就可以手动决定这些特性会被赋予哪个元素Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
`
})
混入
var myMixin = {
created: function () {
this.hello()
},
methods: {
hello: function () {
console.log('hello from mixin!')
}
}
}
// 定义一个使用混入对象的组件
var Component = Vue.extend({
mixins: [myMixin]
})
var component = new Component() // => "hello from mixin!"
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
created: function () {
console.log(this.$data)
// => { message: "goodbye", foo: "abc", bar: "def" }
}
})
var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('组件钩子被调用')
}
})
// => "混入对象的钩子被调用"
// => "组件钩子被调用"
自定义指令 v-
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
v-focus
属性,如下:
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
el
:指令所绑定的元素,可以用来直接操作 DOM 。binding
name
:指令名,不包括 v-
前缀。value
:指令的绑定值,例如:v-my-directive="1 + 1"
中,绑定值为 2
。oldValue
:指令绑定的前一个值,仅在 update
和 componentUpdated
钩子中可用。无论值是否改变都可用。expression
:字符串形式的指令表达式。例如 v-my-directive="1 + 1"
中,表达式为 "1 + 1"
。arg
:传给指令的参数,可选。例如 v-my-directive:foo
中,参数为 "foo"
。modifiers
:一个包含修饰符的对象。例如:v-my-directive.foo.bar
中,修饰符对象为 { foo: true, bar: true }
。vnode
:Vue 编译生成的虚拟节点。移步 VNode API 来了解更多详情。oldVnode
:上一个虚拟节点,仅在 update
和 componentUpdated
钩子中可用。el
之外,其它参数都应该是只读的,切勿进行修改
Vue.directive('demo', {
bind: function (el, binding, vnode) {
var s = JSON.stringify
el.innerHTML =
'name: ' + s(binding.name) + '
' +
'value: ' + s(binding.value) + '
' +
'expression: ' + s(binding.expression) + '
' +
'argument: ' + s(binding.arg) + '
' +
'modifiers: ' + s(binding.modifiers) + '
' +
'vnode keys: ' + Object.keys(vnode).join(', ')
}
})
new Vue({
el: '#hook-arguments-example',
data: {
message: 'hello!'
}
})
value: “hello!”
expression: “message”
argument: “foo”
modifiers: {“a”:true,“b”:true}
vnode keys: tag, data, children, text, elm, ns, context, fnContext, fnOptions, fnScopeId, key, componentOptions, componentInstance, parent, raw, isStatic, isRootInsert, isComment, isCloned, isOnce, asyncFactory, asyncMeta, isAsyncPlaceholder补充
data
中的属性才是响应式的,如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
Object.freeze()
,会阻止修改现有的属性,也意味着响应系统无法再追踪变化。
vm.$nextTick( () =>{
Console.log(vn.$el.innerHTML);
})
this
,this
会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined
或 Uncaught TypeError: this.myMethod is not a function
之类的错误。你可能感兴趣的:(vue笔记,vue,js,前端,框架)