由于是学习基础知识,所以就先不用vue-cli脚手架构建项目,从基础搞起。
搭建环境:<script src="https://unpkg.com/vue@next"></script>
一、创建应用
(1)语法:Vue.createApp()
(2)使用:
二、常用属性
(1)v-bind:为标签属性绑定变量,当变量值改变时绑定的属性值也会改变(单向绑定)
(2)v-model:常用于输入框,将输入框内的值与某一变量绑定,无论哪一方的值发生变化,另一方都会随之变化(双向绑定,原理可参考Object.defineProperty,以及属性描述符set,get,发布-订阅者模式)
(3)v-if、v-if-else、v-else:条件语句,与v-show类似,v-if控制的是dom的移除和插入,v-show控制的是dom的显隐,实际上控制的是css的display
(4)v-on:绑定事件,可简写为@,例如v-on:click = @:click
(5)v-for:循环语句,例如v-for="item in list",或者v-for="(item, index) in list",也可以循环遍历对象,v-for="(value, key, index) in object"
(6)v-html:插入html,可以识别字符串中的html标签
(7)v-once:只赋值一次
三、组件
1、创建组件
(1)创建全局组件:利用Vue.createApp({})创建一个应用,通过component方法配置参数,然后挂载到根节点,这样全局各个组件都能使用
(2)创建局部组件:利用components属性,将配置的组件注册在组件内部,这样只有进行注册的组件才能够使用
2、props组件间传值
(1)组件内通过props属性接收注册从父组件设置的属性名,然后就可以在组件内部进行调用
<body>
<div id="app">
<my_component v-for="(item, index) in list" :name="item.name" :age="item.age"></my_component>
</div>
</body>
<script>
const MyComponent = {
props: ['name', 'age'],
template: `<p>姓名: {{name}}<br/>年龄:{{age}}</p>`
}
const app = Vue.createApp({
data() {
return {
list: [{
name: 'pzw',
age: 12
}, {
name: 'dh',
age: 18
}]
}
},
components: {
"my_component": MyComponent
}
})
app.mount("#app");
</script>
实现效果:
(2)props可以是一个对象,然后设置验证参数,可以校验传过来的值是否符合规定格式,type,validator,default,required,若接收的值不符合规则,则会在控制台输出警告信息
const MyComponent = {
props: {
name: {
type: String,
default: 'name',
required: true
},
age: {
type: Number,
default: 10086,
required: true
}
},
template: `<p>姓名: {{name}}<br/>年龄:{{age}}</p>`
}
四、计算属性computed
(1)用于显示一些需要原始数据经过一番处理才能得到的值
const MyComponent = {
props: ['name', 'age'],
computed: {
birth() {
return new Date().getFullYear() - this.age;
}
},
template: `<p>姓名: {{name}}<br/>年龄:{{age}}<br/>出生年份:{{birth}}</p>`
}
显示效果:
(2) computed默认只有getter属性,但是也可以设置setter
const MyComponent2 = {
data() {
return {
name: "pzw",
age: 22
}
},
computed: {
birth: {
set: function(param) {
let arr = param.split(" ");
this.name = arr[0];
this.age = arr[1];
}
}
},
template: `
<p>
姓名: {{name}}<br/>年龄:{{age}}<br/>出生年份:{{birth}}
<button @click='this.birth="dh 33";'>改变数据</button>
</p>
`
}
点击前:
点击后:
五、监听属性watch
响应数据变化【我咋感觉作用跟computed有点类似啊,然后带着不解去科普了一下,瞬间领悟】
1、computed支持缓存,只有依赖数据发生改变,才会重新进行计算;而watch不支持缓存,数据变化直接会触发相应的操作。
2、computed不支持异步,watch支持异步操作
3、computed常被用于多对一【即一个数据的值受多个数据影响】或者一对一,watch常被用于一对多【即一个数据发生改变会对多个数据产生影响】
const MyComponent3 = {
data() {
return {
name: "",
age: "",
gender: "",
birth: "",
userId: ""
}
},
template: `
<input type='text' v-model='userId' /><br/>
<h4>搜索结果如下:</h4>
<p>姓名:{{name}}</p>
<p>年龄:{{age}}</p>
<p>性别:{{gender}}</p>
<p>出生年月:{{birth}}</p>
`,
watch: {
userId: function(newValue, oldValue) {
setTimeout(() => {
this.name = "pzw";
this.age = "12";
this.birth = "1998-06-12";
this.gender = "男";
}, 2000);
}
}
}
=====》
六、样式绑定
对于组件的class,我们可以利用变量来实现切换样式的操作。
(1)<div :class="{ 'active': isActive }"></div>,isActive为true的时候添加类active,反之移除
(2)<div :class="{ 'active': isActive, 'active2': isActive2 }"></div>,可以同时设置多个类名
(3)<div :class="[class1, class2]"></div>,赋值为数组
(4)<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>,设置内联样式
七、自定义指令directives
<body>
<div id="app">
<p v-color="'red'">我是初始化文字</p>
<p v-color="'blue'">我是初始化文字</p>
<p v-color="'yellow'">我是初始化文字</p>
<p v-color="'green'">我是初始化文字</p>
</div>
</body>
<script>
const app = Vue.createApp({});
app.directive("color", {
mounted(el, binding) {
//el为该指令绑定的元素
el.style.color = binding.value;
}
})
//不使用生命周期
// app.directive("color", function(el, binding) {
// //el为该指令绑定的元素
// el.style.color = binding.value;
// })
app.mount("#app");
</script>
八、钩子函数
指令定义函数提供了几个钩子函数(可选):
created
: 在绑定元素的属性或事件监听器被应用之前调用。
beforeMount
: 指令第一次绑定到元素并且在挂载父组件之前调用。。
mounted
: 在绑定元素的父组件被挂载后调用。。
beforeUpdate
: 在更新包含组件的 VNode 之前调用。。
updated
: 在包含组件的 VNode 及其子组件的 VNode 更新后调用。
beforeUnmount
: 当指令与在绑定元素父组件卸载之前时,只调用一次。
unmounted
: 当指令与元素解除绑定且父组件已卸载时,只调用一次。
钩子函数参数:
el:指令绑定到的元素。这可用于直接操作 DOM。
binding:是一个对象,包含以下属性:
instance
:使用指令的组件实例。value
:传递给指令的值。例如,在v-color="'red'"
中,该值为red
。oldValue
:先前的值,仅在beforeUpdate
和updated
中可用。值是否已更改都可用。arg
:参数传递给指令 (如果有)。例如在v-color:foo
中,arg 为"foo"
。modifiers
:包含修饰符 (如果有) 的对象。例如在v-color.foo.bar
中,修饰符对象为{foo: true,bar: true}
。dir
:一个对象,在注册指令时作为参数传递。
vnode:作为 el 参数收到的真实 DOM 元素的蓝图。
prevNode:上一个虚拟节点,仅在 beforeUpdate 和 updated 钩子中可用。
九、路由
需要引入vue-router
因为我只是学习,我选择直接script导入:<script src="https://unpkg.com/vue-router@4"></script>
<body>
<div id="app">
<h3>欢迎来到我的世界</h3>
<p>
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/one">第一章:初始</router-link>
<router-link to="/two">第二章:入道</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</body>
<script>
// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = {
template: '<div>初始</div>'
}
const About = {
template: '<div>入道</div>'
}
//定义路由,以及对应显示的组件
const routes = [{
path: '/one',
component: Home
}, {
path: '/two',
component: About
}];
//创建路由
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes: routes
})
const app = Vue.createApp({});
app.use(router);
app.mount("#app");
</script>
router-link相关属性
to:表示目标路由的链接
<!-- 字符串 --> <router-link to="home">Home</router-link> <!-- 渲染结果 --> <a href="home">Home</a> <!-- 使用 v-bind 的 JS 表达式 --> <router-link v-bind:to="'home'">Home</router-link> <!-- 不写 v-bind 也可以,就像绑定别的属性一样 --> <router-link :to="'home'">Home</router-link> <!-- 同上 --> <router-link :to="{ path: 'home' }">Home</router-link> <!-- 命名的路由 --> <router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link> <!-- 带查询参数,下面的结果为 /register?plan=private --> <router-link :to="{ path: 'register', query: { plan: 'private' }}">Register</router-link>
replace:当点击时,会调用 router.replace() 而不是 router.push(),导航后不会留下 history 记录。
<router-link :to="{ path: '/abc'}" replace></router-link>
append:设置 append 属性后,则在当前 (相对) 路径前添加其路径。例如,我们从 /a 导航到一个相对路径 b,如果没有配置 append,则路径为 /b,如果配了,则为 /a/b
<router-link :to="{ path: 'relative/path'}" append></router-link>
tag:有时候想要 <router-link>
渲染成某种标签,例如 <li>
。 于是我们使用 tag
prop 类指定何种标签,同样它还是会监听点击,触发导航。
<router-link to="/foo" tag="li">foo</router-link> <!-- 渲染结果 --> <li>foo</li>
active-class: 设置 链接激活时使用的 CSS 类名
<style> ._active{ background-color : red; } </style> <router-link v-bind:to = "{ path: '/route1'}" active-class = "_active">Router Link 1</router-link>
十、混入Mixins
混入 (mixins)定义了一部分可复用的方法或者计算属性。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。
混入中定义的方法或者数据如果跟原组件内定义的方法或者数据命名冲突,则组件内定义的会覆盖混入中定义的。
<body>
<div id="app">
<button @click="inputProps('name')">输出name</button>
<button @click="inputProps('age')">输出age</button>
<button @click='say'>执行say函数</button>
<p>{{msg}}</p>
</div>
</body>
<script>
const myMixin = {
data() {
return {
name: "原名",
age: 12
}
},
methods: {
say() {
console.log("喵喵喵");
}
}
}
Vue.createApp({
mixins: [myMixin],
data() {
return {
name: "重命名",
msg: ""
}
},
methods: {
say() {
console.log("汪汪汪");
},
inputProps(type) {
this.msg = this[type];
}
}
}).mount("#app");
</script>
输出name:
输出age:
执行say函数: