Vue3安装、创建到使用
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-infov-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: {// 计算属性的 getterreversedMessage: 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: {// getterget: function () {return this.name + ' ' + this.url},// setterset: 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 指令绑定到的元素。这可用于直接操作 DOMbinding 是一个对象,包含以下属性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.textel.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);// 定义点击事件 myFnfunction 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) // 1const plusOne = computed(() => count.value + 1)console.log(plusOne.value) // 2plusOne.value++ // 错误const obj = reactive({ count: 0 })obj.count++ // 1//传入[数组]会转成proxy对象const arr= reactive([1, 2, 3])console.log(arr[0]) // 1const count = ref(1)watchEffect(() => console.log(count.value))count.value++const stop = watchEffect(() => {})// 当不再需要此侦听器时:stop()const state = reactive({ count: 0 })watch(() => state.count,(count, prevCount) => {/* ... */})}
}
© 著作权归作者所有,转载或内容合作请联系作者
喜欢的朋友记得点赞、收藏、关注哦!!!