Vue3
Vue3 简介
Vue.js是一套构建用户界面的渐进式框架,只关注视图层,采用自底向上增量开发,通过尽可能简单的API来实现响应式的数据绑定和组合。
第一个Vue实例:
<script src="https://unpkg.com/vue@next"></script>
<body>
<div id="hello-vue" class="demo">
{{message}}
</div>
<script>
const HelloVueApp = {
data() {
return {
message:'Hello Vue!!'
}
},
}
Vue.createApp(HelloVueApp).mount('#hello-vue');
</script>
</body>
Vue3 安装
在使用Vue时,一般直接使用<script>标签引入:
<script src="https://unpkg.com/vue@next"></script>
Vue-cli安装
# 全局安装 vue-cli
$ cnpm install -g @vue/cli
# 安装完后查看版本
$ vue --version
@vue/cli 4.5.11
安装 @vue/cli-int:
$ cnpm i -g @vue/cli-init
创建项目,进行一些配置:
$ vue init webpack runoob-vue3-test
# 这里需要进行一些配置,默认回车即可
? Project name runoob-vue3-test
? Project description A Vue.js project
? Author runoob <test@runoob.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Set up unit tests Yes
? Pick a test runner jest
? Setup e2e tests with Nightwatch? Yes
? Should we run `npm install` for you after the project has been created? (recommended) npm
vue-cli · Generated "runoob-vue3-test".
# Installing project dependencies ..
# ========================
...
进入项目,安装并运行:
$ cd runoob-vue3-test
$ cnpm run dev
Vite安装(推荐)
Vite是一个web开发构建工具。
使用Vite快速构建Vue项目的语法格式:
npm init @vitejs/app <project-name>
创建项目:
$ cnpm init @vitejs/app runoob-vue3-test2
运行项目:
$ cd runoob-vue3-test2
$ cnpm install
$ cnpm run dev
> runoob-vue3-test2@0.0.0 dev/Users/tianqixin/runoob-test/vue3/runoob-vue3-test2
> vite
[vite] Optimizable dependencies detected:
vue
Dev server running at:
> Local: http://localhost:3000/
Vue3 目录结构
使用Vite创建项目后的目录结构:
- node_modules:npm 加载的项目依赖模块
- public:公共资源目录
- src:这里是我们要开发的目录,基本上要做的事情都在这个目录里
- assets: 放置一些图片,如logo等
- components: 目录里面放了一个组件文件,可以不用
- App.vue: 项目入口文件,我们也可以直接将组件写这里,而不使用 components 目录
- main.js: 项目的核心文件
- index.css: 样式文件
- .xxxx文件:这些是一些配置文件,包括语法配置,git配置等
- index.html:首页入口文件,你可以添加一些 meta 信息或统计代码啥的
- package.json:项目配置文件
Vue3 起步
刚开始学习Vue,一般就只写简单的单页面,不考虑整个项目时,不需要用很复杂的创建项目的步骤来开始Vue,直接在需要使用的页面中引入即可:
<script src="https://unpkg.com/vue@next"></script>
Vue3中的应用通过createApp函数来创建,传递给createAPP的选项用于配置根组件。
const app = Vue.createApp({ ... })
使用mount()函数挂载应用,根组件被用作渲染的起点。
Vue.createApp(HelloVueApp).mount('#hello-vue')
createApp({ … })内部,填写自定义的数据和方法:
const app = Vue.createApp({
data() {
return { count: 4 }
},
methods: {
increment() {
this.count++
}
}
})
data选项返回一个对象,对象是自己定义的一些数据。
methods选项中书写自定义的方法。
Vue3 模板语法
Vue的核心是允许采用简洁的模板语法来声明式的将数据渲染进DOM的系统。在应用状态改变时,Vue能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上。
Vue使用基于HTML的模板语法,使开发者能声明式的将DOM绑定至底层Vue实例的数据。
插值
- 文本
数据绑定最常见的形式,使用{{…}} (双大括号)的文本插值
<div id="app">
<p>{{message}} </p>
</div>
因为Vue的数据绑定是可以实时更改的,所以一旦message的数据改变时,整个页面上用到message的地方都会产生变化,可以通过v-once指令来执行一次性地插值,这样当数据改变时,此处的内容不会变化。
<p v-once>{{message}} </p>
- html
使用v-html指令可以输出html代码:
<span v-html="rawHtml"></span>
浏览器会解析rawHtml数据的内容,并将解析后的结果呈现在页面上。
<div v-bind:class="{'class1': use}">
v-bind:class 指令
</div>
- 表达式
Vue.js完全支持JavaScript表达式,无论是在指令中还是在{{…}}中都可以使用表达式。
指令
在Vue.js中,指令是带有v-前缀的特殊属性,指令用于在表达式地值改变时,将某些行为应用到DOM上。
<a v-bind:href="url">CSDN</a>
- 修饰符
修饰符是以. 指明地特殊后缀,用于指出一个指令应该以特殊方式绑定。
<form v-on:submit.prevent="onSubmit"></form>
.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
用户输入
在input输入框中使用v-model指令来实现双向数据绑定。
<input v-model="message">
v-model 指令用来在 input、select、textarea、checkbox、radio 等表单控件元素上创建双向数据绑定,根据表单上的值,自动更新绑定的元素的值。
对于按钮的事件我们可以使用 v-on指令 监听事件,并对用户的输入进行响应。
缩写
v-bind缩写:
<a v-bind:href="url"></a>(完整语法)
<a :href="url"></a>(缩写)
v-on缩写:
<a v-on:click="doSomething"></a>(完整语法)
<a @click="doSomething"></a>(缩写)
Vue3 条件语句
- v-if指令
v-if指令用于条件判断,当表达式为true时才会显示
<p v-if="seen">现在你看到我了</p>
这是一个元素的例子,如果要同时操作多个元素,可以将元素包裹在<template>标签中
- v-else指令
用 v-else 指令给 v-if 添加一个 “else” 块,类似于if {…} else {…} 语句 - v-else-if指令
v-else-if 即 v-if 的 else-if 块,可以链式的使用多次,类似于 if{…}else if{…}
【注】v-else 、v-else-if 必须跟在 v-if 或者 v-else-if之后。
- v-show指令
使用v-show指令来根据条件展示元素。
<h1 v-show="ok">Hello!</h1>
data() {
return {
ok: true
}
}
Vue3 循环语句
循环:v-for指令 语法:(item,index) in items
第二个参数可省略:
<li v-for="item in items">
{{item.text}}
</li>
第二个参数为当前项地索引值:
<li v-for="(item,index) in items">
{{index}}--{{item.text}}
</li>
v-for指令也可以用来迭代对象的属性,语法为v-for="(value,key,index) in object" ,后两个参数根据需要选择。
v-for指令迭代整数,语法为v-for="n in 10" 。
显示过滤/排序后的结果
<ul>
<li v-for="n in evenNumbers">{{ n }}</li>
</ul>
computed: {
evenNumbers() {
return this.numbers.filter(number => number % 2 === 0)
}
}
在组件上使用v-for
语法:
<my-component
v-for="(item, index) in items"
:item="item"
:index="index"
:key="item.id"
></my-component>
Vue3 组件
组件(Component):是Vue.js最强大的功能之一,组件可以扩展HTML元素,封装可重用的代码,几乎任意类型的应用的界面都可以抽象为一个组件树。
全局组件
-
注册一个全局组件的语法格式为: app.component('my-component-name', {...}) ,其中my-component-name 为注册的组件名,... 部分为配置选项。 -
组件被注册后,调用组件的语法为:<my-component-name></my-component-name> -
一个简单的组件注册实例
<div id="app">
<csdn></csdn>
</div>
<script>
const app = Vue.createApp({});
app.component("csdn", {
template: "<h1>自定义组件</h1>",
});
app.mount("#app");
</script>
全局组件被注册后,可以在“全局”中被使用任意多次。
局部组件
- 先通过普通的JS对象来定义组件,语法:
const ComponentA = {...} - 然后再components选项中定义想要使用的组件:
const app = Vue.createApp({
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
var csdn = {
template: "<h1>自定义组件</h1>",
};
const app = Vue.createApp({
components: {
'csdn': csdn,
},
});
Prop
prop是子组件用来接受父组件传递过来的数据的一个自定义属性,父组件的数据需要通过props把数据传给子组件,子组件需要显式地用props选项声明’prop’:
<div id="app">
<site-name title="Google"></site-name>
<site-name title="Baidu"></site-name>
<site-name title="FireFox"></site-name>
</div>
<script>
const app = Vue.createApp({});
app.component('site-name',{
props:['title'],
template:' <h4>{{title}} </h4>'
})
app.mount('#app');
</script>
一个组件可以拥有任意数量地prop,任何值都可以传递给任何prop。
Prop也可以是动态的,使用v-bind指令动态绑定数据,父组件数据变化时,子组件数据同时改变。
组件可以为props指定验证要求。type,required,default,validator ,例如:
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
}
Vue3 计算属性
计算属性:computed,计算属性在处理一些复杂逻辑时是很有用的。
反转字符串的计算属性:
computed:{
reversedMessage:function(){
return this.message.split('').reverse().join('')
}
}
可以使用methods属性来代替computed属性,两者的效果是一样的。但是,computed是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值,而methods在重新渲染时,函数总会重新调用执行。
相比较而言,computed的性能会更好,但是如果不希望缓存可以使用methods属性。
computed属性默认的只有getter方法,如果需要也可以自己提供一个setter方法:
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]
}
}
//调用setter方法
vm.site = '菜鸟教程 https://www.runoob.com';
Vue3 监听属性
监听属性watch,通过watch可以响应数据的变化。
vm.$watch('counter', function(nval, oval) {
alert('计数器值的变化 :' + oval + ' 变为 ' + nval + '!');
});
函数得两个参数:第一个是变化后的值,第二个是变化前的值。
异步数据的加载,通过watch选项提供了一个更通用的方法来响应数据的变化。
Vue3 样式绑定
内部样式绑定属性:v-bind:class,简写为 :class
<div :class="{ 'active': isActive }"></div>
其中,'active' 是定义的样式的类名,isActive 是控制样式是否显示的数据。
也可以动态切换多个class:
<div class="static" :class="{ 'active': isActive, 'text-danger': hasError }"></div>
<div class="static" :class="classObject"></div>
classObject: {
'active': false,
'text-danger': true
}
:class ="..." 省略号的内容可以是对象,数组一级三元表达式。
内联样式绑定:v-bind:style,简写为 :style
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }">内联样式绑定</div>
语法与前面的内部样式绑定语法相同。
多重值
可以为style绑定中的数据提供一个包含多个值的数组,常用于提供多个带前缀的值,这样只会渲染数组中最后一个被浏览器支持的值。
在组件上使用class属性:
<my-component :class="{ active: isActive }"></my-component>
<my-component class="classC classD"></my-component>
如果组件有多个根元素,需要定义哪些部分接收这个类,可以使用$attrs 组件属性执行:
template: `
<p :class="$attrs.class">I like runoob!</p>
<span>这是一个子组件</span>
`
只有p标签会接收这个自定义组件使用的类。
Vue3 事件处理
事件处理:v-on指令,简写为 @。
<button @click="greet">点我</button>
methods: {
greet(event) {
alert('Hello ' + this.name + '!')
if (event) {
alert(event.target.tagName)
}
}
}
v-on指令接收一个在methods属性中定义的方法来处理事件。
也可以直接使用内联的JS语句:
<button @click="counter += 1">增加 1</button>
事件处理程序也可以有多个方法,方法之间使用逗号分隔:
<button @click="one($event), two($event)">点我</button>
常用的事件有:
@click
@keyup
事件还可以通过. 表示的指令后缀来调用事件修饰符,常用的事件修饰符:
.stop - 阻止冒泡
.prevent - 阻止默认事件
.capture - 阻止捕获
.self - 只监听触发该元素的事件
.once - 只触发一次
.left - 左键事件
.right - 右键事件
.middle - 中间滚轮事件
常用的按键修饰符:
.enter
.tab
.delete (捕获 "删除" 和 "退格" 键)
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta
Vue3 表单
v-model指令在表单的一些元素上创建双向数据绑定。
v-model指令会根据控件类型自动选取正确的方法来更新元素。
v-model为不同的输入元素使用不同的属性并抛出不同的事件:
- text和textarea元素使用value属性和input事件
- checkbox和radio使用checked属性和change事件
- select字段将value作为属性并将change作为事件
<input v-model="message" placeholder="编辑我……">
<textarea v-model="message2" placeholder="多行文本输入……"></textarea>
<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
<input type="radio" id="runoob" value="Runoob" v-model="picked">
<select v-model="selected" name="fruit">
<option value="">选择一个网站</option>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
</select>
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
修饰符
.lazy修饰符,将在input事件中同步转为在change事件中同步:
<input v-model.lazy=“msg” >
.number修饰符自动将输入值转为Number类型:
<input v-model.number=“age” type=“number”>
.trim修饰符,自动过滤用户输入的首位空格:
<input v-model.trim=“msg”>
Vue3 自定义指令
除了前面介绍的由Vue提供的核心指令外,Vue也允许用户注册自定义的指令。
<input v-focus>
// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}
})
使用directive方法来注册自定义指令。
钩子
-
钩子函数 指令定义函数提供的几个钩子函数: created : 在绑定元素的属性或事件监听器被应用之前调用。
beforeMount : 指令第一次绑定到元素并且在挂载父组件之前调用。
mounted : 在绑定元素的父组件被挂载后调用。
beforeUpdate: 在更新包含组件的 VNode 之前调用。
updated: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
beforeUnmount: 当指令与元素解除绑定且父组件已卸载时,只调用一次。
unmounted: 当指令与元素解除绑定且父组件已卸载时,只调用一次。
钩子函数的参数有: 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:一个对象,在注册指令时作为参数传递
vnode:作为 el 参数收到的真实 DOM 元素的蓝图
prevNode:上一个虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用
app.directive('runoob', (el, binding, vnode) => {
console.log(binding.value.name) // => "菜鸟教程"
console.log(binding.value.url) // => "www.runoob.com"
var s = JSON.stringify
el.innerHTML = s(binding.value)
})
app.directive('runoob', (el, binding, vnode) => {
el.innerHTML = binding.value.text
el.style.backgroundColor = binding.value.color
})
Vue3 路由
使用Vue路由可以通过不同的URL访问不同的内容,使用Vue路由需要先载入vue-router库。
安装
直接加载:
https://unpkg.com/vue-router@4
使用淘宝镜像安装
npm install -g cnpm --registry=https://registry.npm.taobao.org ? cnpm install vue-router@4
使用
Vue.js + vue-router 可以简单的实现单页应用。
<router-link> 是一个组件,这个组件用来设置一个导航链接,切换不同HTML内容,其中to 属性为目标地址,即要显示的内容。
<div id="app">
<h1>Hello App!</h1>
<p>
<router-link to="/">Go to Home</router-link>
<router-link to="/about">Go to About</router-link>
</p>
<router-view></router-view>
</div>
使用自定义组件 router-link 来创建链接,使得 Vue Router 可以在不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。
router-view 将显示与 url 对应的组件。你可以把它放在任何地方,以适应你的布局。
<script>
const Home = {template:'<div>Home</div>'}
const About = {template:'<div>About</div>'}
const routes = [
{path:'/',component:Home},
{path:'/About',component:About},
]
const router = VueRouter.createRouter({
history:VueRouter.createWebHashHistory(),
routes,
})
const app=Vue.createApp({});
app.use(router);
app.mount('#app');
</script>
<router-link> 相关属性:
to:目标路由的链接
replace:当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录
append:在当前 (相对) 路径前添加其路径
tag:直接将 <router-link> 渲染成某种标签,例如:tag="li"则渲染成<li>标签
active-class:链接激活时使用的 CSS 类名
exact-active-class:当链接被精确匹配的时候应该激活的 class
event:声明可以用来触发导航的事件
Vue3 混入
混入:mixins
混入定义了一部分可复用的方法或者计算属性。混入对象可以包含任意组件选项。当组件混入对象时,所有混入对象的选项将被混入该组件本身的选项。
PS:这个地方优点没懂,后面弄懂了再来补。
Vue3 Ajax(axios)
在Vue中使用axios来完成ajax请求,axios是一个基于Promise的HTTP库,可以用在浏览器和node.js中。
安装方法
使用代码引入:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
使用方法
Vue.axios.get(api).then((response) => {
console.log(response.data)
})
GET方法
mounted () {
axios
.get('https://www.runoob.com/try/ajax/json_demo.json')
.then(response => (this.info = response))
.catch(function (error) {
console.log(error);
});
}
GET方法传递参数:axios.get('/user?ID=12345')... ,直接在URL上添加参数ID=12345。
POST方法
mounted () {
axios
.post('https://www.runoob.com/try/ajax/demo_axios_post.php')
.then(response => (this.info = response))
.catch(function (error) {
console.log(error);
});
}
POST方法传递参数:
axios.post('/user', {
firstName: 'Fred',
lastName: 'Flintstone'
})
...
执行多个并发请求
function getUserAccount() {
return axios.get('/user/12345');
}
function getUserPermissions() {
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(), getUserPermissions()])
.then(axios.spread(function (acct, perms) {
}));
axios API
通过向axios传递相关配置来创建请求:
axios(config)
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
axios({
method:'get',
url:'http://bit.ly/2mTM3nY',
responseType:'stream'
})
.then(function(response) {
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
});
axios(url[, config])
axios('/user/12345');
axios更详细的讲解
|