#学习Vue 和 Firebase
Vue.js 官网中文文档 (v2) Vue-cli github Vue-cli (Vue.js 开发的标准工具)
v-bind
,可以使用 :
简写v-on
,使用@
简写,如 @click="methodName"
v-model
(未深入)因为版本更新,这块跟视频的差别很大,当前使用 版本 vue --version
@vue/cli 4.3.1
vue-cli
安装:
npm install -g @vue/cli
快速原型开发 vue serve
,默认入口可以是 main.js、index.js、App.vue 或 app.vue 中的一个
创建一个项目
vue create yourProject
运行
cd yourProjectPath
npm run serve
# 相当于
node_modules/.bin/vue-cli-service serve
查错
npm run lint
以上命令注册在项目的 package.json
的scripts
项中
创建项目时可以设定配置,加入相应的组件
保存预设配置
安装plugins
如安装 vue-plugin-vuetify
对应到 package.json
的 devDependencies
项目
vue add vuetify
构建web component
用法
vue build -h
-t, --target <target> Build target (app | lib | wc | wc-async, default: app)
-n, --name <name> name for lib or web-component mode (default: entry filename)
-d, --dest <dir> output directory (default: dist)
-h, --help output usage information
如将online.vue
构建为online-status
的 web component
vue build online.vue --target wc --name online-status
使用 web component
如使用之前构建的 online-status
<meta charset="utf-8">
<title>online-status demo</title>
<script src="https://unpkg.com/vue"></script>
<script src="./online-status.js"></script>
...
<online-status status="online"></online-status>
...
vue ui
图形化工具
vue-cli 的 web图形化 界面
- ES6
- async
- promise
- await
2020.07.24
npm run
命令,因为项目的package.json
文件可以找到这些命令 "scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
}
npm run serve
> vue-tobe@0.1.0 serve /Users/falcon/projects/js/vue-firebase/day6/vue-tube
> vue-cli-service serve
INFO Starting development server...
ERROR Error: No valid exports main found for '/Users/falcon/projects/js/vue-firebase/day6/vue-tube/node_modules/colorette'
Error: No valid exports main found for '/Users/falcon/projects/js/vue-firebase/day6/vue-tube/node_modules/colorette'
解决方法有两个:
1. `npm i colorette@1.2.0` # 必须带版本号才管用
2. 升级 `node.js`
`homebrew`安装的 `node.js` 有时并不是最新的版本,就算使用homebrew升级也升不到官方最新版本。`N`是node内置的版本管理器,使用`npm install -g n`安装,然后执行 `sudo n latest` 可升到最新版本。
2020.07.30
安装nvm ,node版本管理工具。 项目用法和文档
brew install nvm
nvm ls-remote #远程所有node版本
nvm ls #本地所有安装的node版本
nvm install 版本 #如果版本写node,会安装最新版本的node并自动切换,如果填写lts,会安装lts版本,如果填写具体版本号,会安装指定版本
nvm alias default node #使用最新版本
nvm alias default 'lts/*' #使用 `lts/*` 版本
nvm alias default 12.18.3 #使用 `12.18.3`版本
nvm use #会使用~/.nvmrc 指定的 node 版本
nvm use 12.18.3 #使用12.18.3版本
nvm use node/stable/unstable #切换最新版本/稳定版本/lts
nvm uninstall 8 #删除8.x版本
nvm uninstall unstable #删除unstable版本
ps: 使用nvm管理node版本后,全局安装模块时不需要用sudo
2020.08.08
vue文档学习
$
如:var vm = new Vue(
el:'#app',
data:{
name:"falcon"
}
)
console.log('实例属性')
console.log(vm.$el)
console.log(vm.$data)
console.log (vm.$el === document.getElementById('app')) // => true
// 这个回调将在 `vm.wage` 改变后调用
vm.$watch('wage', function(newVal, oldVal) {
console.log(this, `wage change from ${oldVal} to ${newVal}`)
}
);
如:
created: () => console.log(this.a)
vm.$watch('wage', (newVal, oldVal) => console.log(this,`wage change from ${oldVal} to ${newVal}`)) //这个this会向上查找不是vue实例,而是window
因为箭头函数并没有 this
,this
会作为变量一直向上级词法作用域查找,直至找到为止,经常导致 Uncaught TypeError: Cannot read property of undefined
或 Uncaught TypeError: this.myMethod is not a function
之类的错误
不改变值
<span v-once>这个值不会改变: wage: {{wage}}</span>
输出原始html
<span v-html="rawHtml"></span>
动态绑定属性/事件
好像这个动态绑定的属性和事件名不能用驼峰写法?会自动转化成小写的data属性
<a v-bind:[attr]="url"> 动态绑定属性 </a>
<a v-on:[eventname]="doSomething"> 动态绑定事件 </a>
computed: { //计算属性
reversedName: function () {
return this.name.split('').reverse().join('')
}
},
计算属性是基于它们的响应式依赖进行 缓存 的,只有相关的响应式依赖发生变化时才会重新计算。 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
尽量使用计算属性而不是命令式的
watch
回调
运行 vm.label2 = "test"
时,setter
会被调用
computed:{
label2: {
get() { //getter
return this.name + this.age + '@' + Date.now()
},
set() { //setter
console.log('Changed @' + Date.now())
this.name += ' hack';
}
}
}
watch: {
...
}
vue项目的bin目录位于 node_modules/.bin/
运行npm run serve
相当于 node_modules/.bin/vue-cli-service serve
vue.js为什么在component的template的root标签中不能使用v-for?
如果后续安装 vue-router
插件,App.vue
会被覆盖
Netlify
免费部署参考视频: Deploy Websites In Seconds With Netlify
部署了github page:https://amazing-goldstine-c1bf0b.netlify.app/
2020.08.10
组件Header.vue:
<template>
<h1 class="header">header</h1>
...
</template>
引入Header的组件
import Header from '../components/Header.vue'
<template>
<div id="app">
<Header class="custom-header">
...
</div>
</tempate>
最后会被渲染为:
<h1 class="header custom-header">header</h1>
v-bind:style
的对象语法十分直观——看着非常像 CSS,但其实是一个 JavaScript 对象
。CSS property 名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用引号括起来) 来命名<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
如果不设置key时,loginType
变化时,input 内的输入值会保留,仅placeholer会被替换
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。
语法:
<li v-for="item in items" :key="item.message">
{{ item.message }}
</li>
支持第二个参数:索引
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
语法:
<li v-for="value in object">
{{ value }}
</li>
第二个参数name表示对象属性名
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>
第三个参数index表示索引
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>
<ul v-for="set in sets">
<li v-for="n in even(set)">{{ n }}</li>
</ul>
data: {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
<my-component
v-for="(item, index) in items"
v-bind:item="item"
v-bind:index="index"
v-bind:key="item.id"
></my-component>
<li
is="todo-item"
v-for="(todo, index) in todos"
v-bind:key="todo.id"
v-bind:title="todo.title"
v-on:remove="todos.splice(index, 1)"
></li>
在内联语句处理器中访问原始的 DOM 事件。
可以用特殊变量 $event
把它传入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
访问原生事件对象
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) {
event.preventDefault()
}
alert(message)
}
}
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>
<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
任意有效按键名转换为 kebab-case 来作为修饰符。如: page-down
<input v-on:keyup.page-down="onPageDown">
在 Mac 系统键盘上,meta 对应 command 键 (⌘)。在 Windows 系统键盘 meta 对应 Windows 徽标键 (⊞)。
<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>
v-model
在内部为不同的输入元素使用不同的 property
并抛出不同的事件:
v-model
来代替。 <textarea v-model="message" placeholder="add multiple lines"></textarea>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: {{ checkedNames }}</span>
new Vue({
el: '...',
data: {
checkedNames: []
}
})
2020.08.11
checkName是一个数组 ,值为input里的value
- 如果 v-model 表达式的初始值未能匹配任何选项,<select> 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发 change 事件。因此,更推荐像下面这样提供一个值为空的禁用选项。
```html
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
有时我们可能想把值绑定到 Vue 实例的一个动态 property 上,这时可以用 v-bind 实现,并且这个 property 的值可以不是字符串。
<input type="radio" v-model="pick" v-bind:value="a">
选中时 vm.pick == vm.a
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
这里的 true-value 和 false-value attribute 并不会影响输入控件的 value attribute,因为浏览器在提交表单时并不会包含未被选中的复选框。如果要确保表单中这两个值中的一个能够被提交,(即“yes”或“no”),请换用单选按钮。
<select v-model="selected">
<!-- 内联对象字面量 -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
// 当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
修饰符
lazy
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg">
number
<!--自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符:-->
<input v-model.number="age" type="number">
trim
<!--自动过滤用户输入的首尾空白字符-->
<input v-model.trim="msg">
在组件上使用 v-model
创建一个custom-input
组件,注意其中的
Vue.component('custom-input', {
props: ['value'],
template: `
<input
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
`
})
现在 v-model 就应该可以在这个组件上完美地工作起来了:
<custom-input v-model="searchText"></custom-input>
创建一个自定义一个插槽组件,注意 <slot>
元素
Vue.component('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error!</strong>
<slot></slot>
</div>
`
})
用法:
<alert-box>
Something bad happened.
</alert-box>
处会被插入的文字替换
<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>
参考代码:https://hi.cellmean.com/p/a11cde485cc1
有些 HTML 元素,诸如
<ul>
、<ol>
、<table>
和<select>
,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如<li>
、<tr>
和<option>
,只能出现在其它某些特定的元素内部。
不能这样写,因为要能出现在 table
元素下的元素有限制
<table>
<blog-post-row></blog-post-row>
</table>
可以使用 is
替换
<table>
<tr is="blog-post-row"></tr>
</table>
需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:
字符串 (例如:template: '...')
单文件组件 (.vue)
<script type="text/x-template">
组件名大小写
支持 kebab-case 和 PascalCase命名方式
注意:直接在 DOM (即非字符串的模板) 中使用时只有
kebab-case
是有效的。
组件注册
Vue.component('my-component-name', {
// ... 选项 ...
})
var ComponentA = { /* ... */ }
实例或子组件使用时需要添加 components
属性
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
import ComponentA from './ComponentA'
import ComponentC from './ComponentC'
export default {
components: {
ComponentA,
ComponentC
},
// ...
}
需要 webpack (或在内部使用了 webpack 的 Vue CLI 3+) 支持
Prop 的大小写 (camelCase vs kebab-case)
如果在prop中使用 camelCase
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
在HTML中必须改成kebab-case ,
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="hello!"></blog-post>
如果你使用字符串模板,那么这个限制就不存在了。
可以使用对象形式
的写法指定名称和类型
props: {
title: String,
likes: Number,
isPublished: Boolean,
commentIds: Array,
author: Object,
callback: Function,
contactsPromise: Promise // or any other constructor
}
静态:
作为字符串传入
<blog-post title="My journey with Vue"></blog-post>
注意:这里的Prop posTitle
,在html页使用时会转成 post-title
, 除非在 字符串模板
使用才没有这种限制。
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<blog-post post-title="hello!"></blog-post>
Vue的字符串模板指的是在Vue实例中的template属性所对应的字符串
动态:
<!-- 动态赋予一个变量的值 -->
<blog-post v-bind:title="post.title"></blog-post>
<!-- 动态赋予一个复杂表达式的值 -->
<blog-post
v-bind:title="post.title + ' by ' + post.author.name"
></blog-post>
<!-- 即便 `42` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:likes="42"></blog-post>
<!-- 包含该 prop 没有值的情况在内,都意味着 `true`。-->
<blog-post is-published></blog-post>
<!-- 即便 `false` 是静态的,我们仍然需要 `v-bind` 来告诉 Vue -->
<!-- 这是一个 JavaScript 表达式而不是一个字符串。-->
<blog-post v-bind:is-published="false"></blog-post>
<!-- 用一个变量进行动态赋值。-->
<blog-post v-bind:is-published="post.isPublished"></blog-post>
可以使用不带参数的 v-bind (取代 v-bind:prop-name)。例如,对于一个给定的对象 post:
<blog-post v-bind="post"></blog-post>
等价于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的状态。
为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:
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 会在一个组件实例创建之前进行验证,所以实例的 property (如 data、computed 等) 在 default 或 validator 函数中是不可用的。
当验证失败时,(开发环境构建版本的) Vue 将会产生一个控制台的警告。
如父级这样调用组件:
<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input>
这里的 data-date-picker
属性不是一个prop,而是attribute时,这样写之后这个属性会添加到组件的根元素
上。
对于绝大多数 attribute 来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type="text" 就会替换掉 type="date" 并把它破坏!庆幸的是,class 和 style attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:
如果你不希望组件的根元素继承 attribute,你可以在组件的选项中设置
inheritAttrs: false
。
注意 inheritAttrs: false 选项不会影响 style 和 class 的绑定。
inheritAttrs
该 property 包含了传递给一个组件的 attribute 名和 attribute 值,例如:
{
required: true,
placeholder: 'Enter your username'
}
配合 inheritAttrs: false
使用
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
template: `
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
`
})
调用 :
<base-input
v-model="username"
required
placeholder="Enter your username"
></base-input>
这个模式允许你在使用基础组件的时候更像是使用原始的 HTML 元素,而不会担心哪个元素是真正的根元素:
2020.08.15
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
用法:
<base-checkbox v-model="lovingVue"></base-checkbox>
<base-input v-on:focus.native="onFocus"></base-input>
vue 提供了一个 $listeners property,它是一个对象,里面包含了作用在这个组件上的所有监听器。例如:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
有了这个 $listeners property,你就可以配合 v-on="$listeners" 将所有的事件监听器指向这个组件的某个特定的子元素。
我们推荐以 update:myPropName
的模式触发事件
子组件触发事件 :
this.$emit('update:title', newTitle)
父组件监听事件并触发更新
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
这种模式可以简写成
<text-document v-bind:title.sync="doc.title"></text-document>
将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑
下面这样会把 doc 对象中的每一个 property (如 title) 都作为一个独立的 prop 传进去,然后各自添加用于更新的 v-on 监听器。
<text-document v-bind.sync="doc"></text-document>
将 v-bind.sync 用在一个字面量的对象上,例如 v-bind.sync=”{ title: doc.title }”,是无法正常工作的,因为在解析一个像这样的复杂表达式的时候,有很多边缘情况需要考虑
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
</navigation-link>
如果url是插槽内部 <navigation-link>
的属性变量,外面是访问不到的,这里会显示 undefined
如在一个 submit-button
的组件中
<button type="submit">
<slot>Submit</slot>
</button>
调用时不带内容
<submit-button></submit-button>
渲染结果:
<button type="submit">
Submit
</button>
<slot>
元素有一个特殊的 attribute:name。这个 attribute 可以用来定义额外的插槽:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
一个不带 name 的 <slot>
出口会带有隐含的名字 “default
”。
在向具名插槽提供内容的时候,我们可以在一个
<template>
元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
最终渲染为:
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
注意 v-slot 只能添加在
<template>
上
动态切换组件时 如:
<component v-bind:is="currentTabComponent"></component>
重新切换到原来的组件,会重新创建组件,原来组件的状态会丢失,可以使用 <keep-alive>
标签缓存原来组件
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent"></component>
</keep-alive>
Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:
Vue.component('async-example', function (resolve, reject) {
setTimeout(function () {
// 向 `resolve` 回调传递组件定义
resolve({
template: '<div>I am async!</div>'
})
}, 1000)
})
一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用,参考使用了 vuex 插件的 路由加载 About 的方式
这段特殊注释不是多余的 : /* webpackChunkName: "about" */
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
这里的异步组件工厂函数也可以返回一个如下格式的对象:
const AsyncComponent = () => ({
// 需要加载的组件 (应该是一个 `Promise` 对象)
component: import('./MyComponent.vue'),
// 异步组件加载时使用的组件
loading: LoadingComponent,
// 加载失败时使用的组件
error: ErrorComponent,
// 展示加载时组件的延时时间。默认值是 200 (毫秒)
delay: 200,
// 如果提供了超时时间且组件加载也超时了,
// 则使用加载失败时使用的组件。默认值是:`Infinity`
timeout: 3000
})
2020.08.18
子组件可以通过$root
属性访问根实例
// 获取根组件的数据
this.$root.foo
// 写入根组件的数据
this.$root.foo = 2
// 访问根组件的计算属性
this.$root.bar
// 调用根组件的方法
this.$root.baz()
在绝大多数情况下,推荐使用 Vuex 来管理应用的状态。
2020.08.20
如果需要在javascript直接访问子组件时,可以在使用子组件时加入 ref
属性,如:
<base-input ref="usernameInput"></base-input>
可以使用 this.$refs.usernameInput
来访问这个 <base-input>
实例
在父级元素中提供 provide
:
provide: function () {
return {
getMap: this.getMap
}
}
在子元素实例使用 inject
接收指定的我们想要添加在这个实例上的 property:
inject: ['getMap']
依赖注入所提供的 property 是非响应式的,你想要共享的这个 property 是你的应用特有的,而不是通用化的,或者如果你想在祖先组件中更新所提供的数据,那么这意味着你可能需要换用一个像 Vuex 这样真正的状态管理方案了。
组件是可以在它们自己的模板中调用自身的。不过它们只能通过 name 选项来做这件事:
name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'
类似上述的组件将会导致“max stack size exceeded
”错误,所以请确保递归调用是条件性的 (例如使用一个最终会得到 false 的 v-if)。
我们先把两个组件称为 A 和 B。模块系统发现它需要 A,但是首先 A 依赖 B,但是 B 又依赖 A,但是 A 又依赖 B,如此往复。这变成了一个循环,不知道如何不经过其中一个组件而完全解析出另一个组件。为了解决这个问题,我们需要给模块系统一个点,在那里“A 反正是需要 B 的,但是我们不需要先解析 B。”
<tree-folder>
组件设为了那个点。我们知道那个产生悖论的子组件是 <tree-folder-contents>
组件,所以我们会等到生命周期钩子 beforeCreate
时去注册它:
beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
}
或者 webpack
异步 import
components: {
TreeFolderContents: () => import('./tree-folder-contents.vue')
}
inline-template
属性,内联模板需要定义在 Vue 所属的 DOM 元素内。
<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>
x-template
需要定义在 Vue 所属的 DOM 元素外。
<script type="text/x-template" id="hello-world-template">
<p>Hello hello hello</p>
</script>
Vue.component('hello-world', {
template: '#hello-world-template'
})
有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,可以在根元素上添加 v-once attribute 以确保这些内容只计算一次然后缓存起来
Vue.component('terms-of-service', {
template: `
<div v-once>
<h1>Terms of Service</h1>
... a lot of static content ...
</div>
`
})
Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。
2020.08.25
当前建立的firebase项目为 udemy-ninja-smoothies
firebase api信息
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "AIzaSyAY6uN7BCWS4licC7Yeyn_i9qE6Ceji-rs",
authDomain: "udemy-ninja-smoothies-fab0d.firebaseapp.com",
databaseURL: "https://udemy-ninja-smoothies-fab0d.firebaseio.com",
projectId: "udemy-ninja-smoothies-fab0d",
storageBucket: "udemy-ninja-smoothies-fab0d.appspot.com",
messagingSenderId: "968931780652",
appId: "1:968931780652:web:6678a7f3690b7d6330c989",
measurementId: "G-K0S8B25CWF"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
firebase.analytics();
2020.08.27
npm install -g firebase-tools
请打开终端窗口,转到 Web 应用的根目录,或为 Web 应用创建根目录
登录 Google
firebase login
启动项目 从该应用的根目录中运行此命令:
firebase init
npm run build
部署到 Firebase 托管
firebase deploy
Project Console: https://console.firebase.google.com/project/udemy-ninja-smoothies-fab0d/overview
Hosting URL: https://udemy-ninja-smoothies-fab0d.web.app
2020.08.29-2020.08.30
新内容添加时自动滚动到元素最底端,如聊天记录,用法
import Vue from 'vue'
import VueChatScroll from 'vue-chat-scroll'
Vue.use(VueChatScroll)
2020.08.31
google apis console(包括google map)
创建 google map API密钥
ENABLE APIS AND SERVICES
按钮,搜索或点击 Maps JavaScript API
的方块,在出现的按钮点击启用API与服务 > 凭据
,在出现的右上方标签位置点 +创建凭据
,选择API密钥
弹出图层:
在您的应用中使用此密钥的方法是:用 key=API_KEY 参数传递此密钥。
AIzaSyBSaj2YcxYDzAnGV_OomO5CCMkj9-HRC1k
您的 API 密钥
引入:
<script defer
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>
相关用法和文档 https://cloud.google.com/maps-platform
很遗憾,作者不再维护了。
可替代 fineuploader
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。