vue安装
npm install vue@next
# 全局安装 vue-cli
npm install -g @vue/cli
#更新插件 项目中运行
vue upgrade --next
vue create 命令
vue create [options] <app-name>
options 选项可以是:
-p, --preset <presetName>: 忽略提示符并使用已保存的或远程的预设选项
-d, --default: 忽略提示符并使用默认预设选项
-i, --inlinePreset <json>: 忽略提示符并使用内联的 JSON 字符串预设选项
-m, --packageManager <command>: 在安装依赖时使用指定的 npm 客户端
-r, --registry <url>: 在安装依赖时使用指定的 npm registry
-g, --git [message]: 强制 / 跳过 git 初始化,并可选的指定初始化提交信息
-n, --no-git: 跳过 git 初始化
-f, --force: 覆写目标目录可能存在的配置
-c, --clone: 使用 git clone 获取远程预设选项
-x, --proxy: 使用指定的代理创建项目
-b, --bare: 创建项目时省略默认组件中的新手指导信息
-h, --help: 输出使用帮助信息
创建vue3项目
vue create vue3-app或vue ui
目录
build 项目构建(webpack)相关代码
config 配置目录,包括端口号等。我们初学可以使用默认的。
node_modules npm 加载的项目依赖模块
src 这里是我们要开发的目录,基本上要做的事情都在这个目录里。里面包含了几个目录及文件:
assets: 放置一些图片,如logo等。
components: 目录里面放了一个组件文件,可以不用。
App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录。
main.js: 项目的核心文件。
index.css: 样式文件。
static 静态资源目录,如图片、字体等。
public 公共资源目录。
test 初始测试目录,可删除
.xxxx文件 这些是一些配置文件,包括语法配置,git配置等。
index.html 首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
package.json 项目配置文件。
README.md 项目的说明文档,markdown 格式
dist 使用 npm run build 命令打包后会生成该目录。
起步
<div id="hello-vue" class="demo">
{{ message }}
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const HelloVueApp = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(HelloVueApp).mount('#hello-vue')
</script>
//使用 mount('#hello-vue') 将 Vue 应用 HelloVueApp 挂载到 <div id="hello-vue"></div> 中
Vue3 模板语法
文本 <span>{{...}}</span>
Html <span v-html="rawHtml"></span>
属性 <div v-bind:id="dynamicId"></div>
表达式
<div id="app">
{{5+5}}<br>
{{ ok ? 'YES' : 'NO' }}<br>
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id">ABC</div>
</div>
<script>
const app = {
data() {
return {
ok: true,
message: 'ABC!!',
id: 1
}
}
}
Vue.createApp(app).mount('#app')
</script>
指令 v-if v-for
参数 v-bind @click @[event] :href
v-model <input v-model="msg"> input、select、textarea、checkbox、radio
Vue3 条件语句
条件判断 v-if v-else v-else-if v-show
Vue3 循环语句
v-for
迭代对象 <li v-for="(value, key, index) in object">{{ value }}</li>
迭代整数 <li v-for="n in 10">{{ n }}</li>
显示过滤/排序后的结果
输出数组中的偶数 <li v-for="n in evenNumbers">{{ n }}</li>
v-for/v-if 联合使用
<template v-for="(site,index) in sites" :site="site" :index="index" :key="site.id">
<!-- 索引为 1 的设为默认值,索引值从0 开始-->
<option v-if = "index == 1" :value="site.name" selected>{{site.name}}</option>
<option v-else :value="site.name">{{site.name}}</option>
</template>
在组件上使用 v-for
<my-component v-for="item in items" :key="item.id"></my-component>
Vue3 组件
<my-component-name></my-component-name>
组件的复用
全局组件 app.vue中注册组件
局部组件 components: {
'component-a': ComponentA,
'component-b': ComponentB
}
Prop
子组件用来接受父组件传递过来的数据的一个自定义属性
父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop"
<div id="app">
<site-name title="Baidu"></site-name>
<site-name title="Taobao"></site-name>
</div>
<script>
const app = Vue.createApp({})
app.component('site-name', {
props: ['title'],
template: `<h4>{{ title }}</h4>`
})
app.mount('#app')
</script>
显示
Baidu
Taobao
动态 Prop
<div id="app">
<site-info
v-for="site in sites"
:id="site.id"
:title="site.title"
></site-info>
</div>
<script>
const Site = {
data() {
return {
sites: [
{ id: 1, title: 'Baidu' },
{ id: 2, title: 'Taobao' }
]
}
}
}
const app = Vue.createApp(Site)
app.component('site-info', {
props: ['id','title'],
template: `<h4>{{ id }} - {{ title }}</h4>`
})
app.mount('#app')
</script>
显示
1 - Baidu
2 - Taobao
Prop 验证
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
}
}
}
})
type 可以是下面原生构造器
String、Number、Boolean、Array、Object、Date、Function、Symbol
type 也可以是一个自定义构造器,使用 instanceof 检测
Vue3 计算属性
//computed
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
<script>
const app = {
data() {
return {
message: 'ABC!!'
}
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
}
</script>
computed vs methods
computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。而使用 methods ,在重新渲染的时候,函数总会重新调用执行
methods: {
reversedMessage2: function () {
return this.message.split('').reverse().join('')
}
}
可以说使用 computed 性能会更好,但是如果你不希望缓存,你可以使用 methods 属性
computed setter
var vm = new Vue({
el: '#app',
data: {
name: 'Baidu',
url: 'https://www.Baidu.com'
},
computed: {
site: {
// getter
get: function () {
return this.name + ' ' + this.url
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.name = names[0]
this.url = names[names.length - 1]
}
}
}
})
vm.site = '淘宝 http://www.Taobao.com';
setter 会被调用时, vm.name 和 vm.url 也会被对应更新
Vue3 监听属性 watch
千米与米之间的换算
<div id = "app">
千米 : <input type = "text" v-model = "kilometers">
米 : <input type = "text" v-model = "meters">
</div>
<p id="info"></p>
<script>
const app = {
data() {
return {
kilometers : 0,
meters:0
}
},
watch : {
kilometers:function(val) {
this.kilometers = val;
this.meters = this.kilometers * 1000
},
meters : function (val) {
this.kilometers = val/ 1000;
this.meters = val;
}
}
}
vm = Vue.createApp(app).mount('#app')
</script>
watch 对象创建了 data 对象的两个监控方法: kilometers 和 meters。
当我们再输入框输入数据时,watch 会实时监听数据变化并改变自身的值
异步加载中使用 watch
data() {
return {
question: '',
answer: '每个问题结尾需要输入 ? 号。'
}
},
watch: {
// 每当问题改变时,此功能将运行,以 ? 号结尾,兼容中英文 ?
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1 || newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
},
methods: {
getAnswer() {
this.answer = '加载中...'
axios
.get('url')
.then(response => {
this.answer = response.data.answer
})
.catch(error => {
this.answer = '错误! 无法访问 API。 ' + error
})
}
}
Vue3 样式绑定
:class
<div class="static" :class="{ 'active' : isActive, 'text-danger' : hasError }"></div>
当 isActive 或者 hasError 变化时,class 属性值也将相应地更新。例如,如果 active 的值为 true,class 列表将变为 "static active text-danger"
直接绑定数据里的一个对象
<style>
.static {
width: 100px;
height: 100px;
}
.active {
background: green;
}
.text-danger {
background: red;
}
</style>
<div id="app">
<div class="static" :class="classObject"></div>
</div>
<script>
const app = {
data() {
return {
classObject: {
'active': false,
'text-danger': true
}
}
}
}
Vue.createApp(app).mount('#app')
</script>
//红色
绑定一个返回对象的计算属性
data() {
return {
isActive: true,
error: null
}
},
computed: {
classObject() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
//绿色
数组语法
<div class="static" :class="[activeClass, errorClass]"></div>
data() {
return {
activeClass: 'active',
errorClass: 'text-danger'
}
}
三元表达式
<div class="static" :class="[isActive ? activeClass : '', errorClass]"></div>
组件上使用 class 属性
<my-component :class="{ active: isActive }"></my-component>
组件有多个根元素,可以使用 $attrs 组件属性执行此操作
template: `
<p :class="$attrs.class">I like ok!</p>
<span>这是一个子组件</span>
`
template 中 ` 是反引号
:style(内联样式)
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">ABC</div>
样式对象
<div :style="styleObject">ABC</div>
data() {
return {
styleObject: {
color: "red",
fontSize: "30px"
}
}
}
style="color: red; font-size: 30px;"
数组
<div :style="[baseStyles, overridingStyles]">ABC</div>
data() {
return {
baseStyles: {
color: 'green',
fontSize: '30px'
},
overridingStyles: {
'font-weight': 'bold'
}
}
}
多重值 <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex
Vue3 事件处理
v-on缩写@
可以执行多个方法,由逗号运算符分隔
<button @click="one($event), two($event)">点我</button>
事件修饰符
.stop - 阻止冒泡
.prevent - 阻止默认事件
.capture - 阻止捕获
.self - 只监听触发该元素的事件
.once - 只触发一次
.left - 左键事件
.right - 右键事件
.middle - 中间滚轮事件
<!-- 阻止单击事件冒泡 -->
<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>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
<!-- click 事件只能点击一次 -->
<a v-on:click.once="doThis"></a>
按键修饰符
<input v-on:keyup.13="submit">
只有在 keyCode 是 13 时调用 vm.submit()
最常用的按键别名 <input @keyup.enter="submit">
全部的按键别名:
.enter
.tab
.delete (捕获 "删除" 和 "退格" 键)
.esc
.space
.up
.down
.left
.right
系统修饰键:
.ctrl
.alt
.shift
.meta
鼠标按钮修饰符:
.left
.right
.middle
.exact 修饰符
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
Vue3 表单
v-model
表单 <input>、<textarea> 及 <select> 等元素上创建双向数据绑定
v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:
1. text 和 textarea 元素使用 value 属性和 input 事件;
2. checkbox 和 radio 使用 checked 属性和 change 事件;
3. select 字段将 value 作为属性并将 change 作为事件。
select multiple 多选时会绑定到一个数组
复选框 (Checkbox) <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
单选框 (Radio) <input type="radio" v-model="pick" :value="a" />
选择框选项 (Select) obj
<select v-model="selected">
<!-- 内联对象字面量 -->
<option :value="{ number: 123 }">123</option>
</select>
// 当被选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
修饰符
.lazy
转变为在 change 事件中同步
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
.number
将用户的输入值转为 Number 类型
<input v-model.number="age" type="number">
.trim
自动过滤用户输入的首尾空格
<input v-model.trim="msg">
Vue3 自定义指令
钩子函数
指令定义函数提供了几个钩子函数(可选):
created : 在绑定元素的属性或事件监听器被应用之前调用。
beforeMount : 指令第一次绑定到元素并且在挂载父组件之前调用。。
mounted : 在绑定元素的父组件被挂载后调用。。
beforeUpdate: 在更新包含组件的 VNode 之前调用。。
updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
beforeUnmount: 当指令与在绑定元素父组件卸载之前时,只调用一次。
unmounted: 当指令与元素解除绑定且父组件已卸载时,只调用一次。
例
// 注册
app.directive('my-directive', {
// 指令是具有一组生命周期的钩子:
// 在绑定元素的 attribute 或事件监听器被应用之前调用
created() {},
// 在绑定元素的父组件挂载之前调用
beforeMount() {},
// 绑定元素的父组件被挂载时调用
mounted() {},
// 在包含组件的 VNode 更新之前调用
beforeUpdate() {},
// 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
updated() {},
// 在绑定元素的父组件卸载之前调用
beforeUnmount() {},
// 卸载绑定元素的父组件时调用
unmounted() {}
})
// 注册 (功能指令)
app.directive('my-directive', () => {
// 这将被作为 `mounted` 和 `updated` 调用
})
// getter, 如果已注册,则返回指令定义
const myDirective = app.directive('my-directive')
钩子函数参数
el 指令绑定到的元素。这可用于直接操作 DOM
binding 是一个对象,包含以下属性
instance:使用指令的组件实例。
value:传递给指令的值。例如,在 v-my-directive="1 + 1" 中,该值为 2。
oldValue:先前的值,仅在 beforeUpdate 和 updated 中可用。值是否已更改都可用。
arg:参数传递给指令 (如果有)。例如在 v-my-directive:foo 中,arg 为 "foo"。
modifiers:包含修饰符 (如果有) 的对象。例如在 v-my-directive.foo.bar 中,修饰符对象为 {foo: true,bar: true}。
dir:一个对象,在注册指令时作为参数传递。例如,在以下指令中:
<div id="app">
<div v-dire="{ name: 'baidu', url: 'www.baidu.com' }"></div>
</div>
<script>
const app = Vue.createApp({})
app.directive('dire', (el, binding, vnode) => {
console.log(binding.value.name) // => "baidu"
console.log(binding.value.url) // => "www.baidu.com"
el.innerHTML = JSON.stringify(binding.value)
})
app.mount('#app')
</script>
简写函数
<script>
app.directive('dire', function (el, binding) {
// 设置指令的背景颜色
el.style.backgroundColor = binding.value.color
})
</script>
接受所有合法的 JavaScript 表达式
<div id="app">
<div v-dire="{ color: 'green', text: 'hello App!' }"></div>
</div>
<script>
Vue.directive('dire', function (el, binding) {
// 简写方式设置文本及背景颜色
el.innerHTML = binding.value.text
el.style.backgroundColor = binding.value.color
})
new Vue({
el: '#app'
})
</script>
Vue3 混入mixins
// mixins提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能
// mixins: 可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。
// vuex:用来做状态管理的,里面定义的变量在每个组件中均可以使用和修改,在任一组件中修改此变量的值之后,其他组件中此变量的值也会随之修改。
// 定义混入对象
const myMixin = {
methods: {
foo() {
console.log('foo')
},
conflicting() {
console.log('from mixin')
}
}
}
const app = Vue.createApp({
mixins: [myMixin],
methods: {
bar() {
console.log('bar')
},
conflicting() {
console.log('from self')
}
}
})
const vm = app.mount('#app')
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
Vue3 组合式 API(Composition API)
1.setup 组件
setup() 函数在组件创建 created() 之前执行
setup() 函数接收两个参数 props 和 context
props是响应式的,当传入新的 prop 时,它将被更新。
context是一个普通的 JavaScript 对象,它是一个上下文对象,暴露了其它可能在 setup 中有用的值。
<template>
<div>
<p>计数器实例: {{ count }}</p>
<input @click="myFn" type="button" value="点我加 1">
</div>
</template>
<script>
import {ref, onMounted} from 'vue';
export default {
setup(props, context){
// 透传 Attributes(非响应式的对象,等价于 $attrs)
console.log(context.attrs)
// 插槽(非响应式的对象,等价于 $slots)
console.log(context.slots)
// 触发事件(函数,等价于 $emit)
console.log(context.emit)
// 暴露公共属性(函数)
console.log(context.expose)
//定义初始值为0的变量,要使用ref方法赋值,直接赋值的话变量改变不会更新 UI
// ref() 函数可以根据给定的值来创建一个响应式的数据对象,返回值是一个对象,且只包含一个 .value 属性。
// 在 setup() 函数内,由 ref() 创建的响应式数据返回的是对象,所以需要用 .value 来访问
let count = ref(0);
// 定义点击事件 myFn
function myFn(){
console.log(count);
count.value += 1;
}
// 组件被挂载时,我们用 onMounted 钩子记录一些消息
onMounted(() => console.log('component mounted!'));
// 外部使用组合API中定义的变量或方法,在模板中可用。
return {count,myFn} // 返回的函数与方法的行为相同
}
}
</script>
2.Vue 组合式 API 生命周期钩子
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onErrorCaptured } from 'vue';
export default {
setup() {
// 载入之前调用
onBeforeMount(() => {})
// 载入之后调用
onMounted(() => {})
// 更新之前调用
onBeforeUpdate(() => {})
// 更新之后调用
onUpdated(() => {})
// 卸载之前调用
onBeforeUnmount(() => {})
// 卸载之后调用
onUnmounted(() => {})
// 生命周期钩子抛出错误时调用
onErrorCaptured(() => {})
}
};
3.响应式 API:核心
import { ref, reactive, computed, readonly, watchEffect, watch } from 'vue';
export default {
setup() {
const count = ref(1)
console.log(count.value) // 1
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 2
plusOne.value++ // 错误
const obj = reactive({ count: 0 })
obj.count++ // 1
//传入[数组]会转成proxy对象
const arr= reactive([1, 2, 3])
console.log(arr[0]) // 1
const count = ref(1)
watchEffect(() => console.log(count.value))
count.value++
const stop = watchEffect(() => {})
// 当不再需要此侦听器时:
stop()
const state = reactive({ count: 0 })
watch(() => state.count,
(count, prevCount) => {
/* ... */
})
}
}
©
著作权归作者所有,转载或内容合作请联系作者
喜欢的朋友记得点赞、收藏、关注哦!!!