参考自己的Vue专栏以及Vue官方文档
Vue 使用一种基于 HTML 的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML,可以被符合规范的浏览器和 HTML 解析器解析。
在底层机制中,Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统,当应用状态变更时,Vue 能够智能地推导出需要重新渲染的组件的最少数量,并应用最少的 DOM 操作。
<body>
<div id="root">
<h1>Hello.{{name}}h1>
<h3>现在的时间是{{new Date().getDate()}}h3>
<hr/>
div>
<script>
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
name:'CSDN'
}
})
script>
body>
html>
{{}}
这个就是Vue里的模板语法,可以在html中嵌入自己的表达式,类似于react中的{}
,并且作用域相当于Vue实例的作用域上面我们使用的就是插值语法,它是Vue模板语法的其中一类。
<body>
<div id="root">
<h1>Hello.{{name}}h1>
<h3>现在的时间是{{new Date().getDate()}}h3>
<a v-bind:href="url">点击跳转到CSDNa> <br>
<a :href="url">点击跳转到CSDNa>
<hr/>
div>
<script>
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
name:'CSDN',
url:'http://www.csdn.net'
}
})
script>
body>
html>
Vue有两种数据绑定的方式:
注意:
双向绑定一般都应用在表单类元素上(如:input、select等,这些元素都有一个特点就是都有value属性)
v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
<!-- 普通写法 -->
<!-- 单向数据绑定:
<input type="text" v-bind:value="name"><br/>
双向数据绑定:
<input type="text" v-model:value="name"><br/>
-->
<!-- 简写 -->
单向数据绑定:<input type="text" :value="name"><br/>
双向数据绑定:<input type="text" v-model="name"><br/>
<!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 -->
<!-- <h2 v-model:x="name">你好啊</h2> -->
其中双向绑定还有三个常用的修饰符:
trim
:输入首位的空格过滤
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
number
:将输入的字符串转化为有效数字
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
lazy
:失去焦点再收集数据
<textarea v-model.lazy="userInfo.other"></textarea> <br/><br/>
我们可以使用 v-on
指令 (简写为 @
) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click="handler"
或 @click="handler"
。
事件处理器 (handler) 的值可以是:
关于传参:
模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。这个时候我们就可以使用计算属性,它可以描述依赖响应式状态的复杂逻辑。
在Vue中属性与计算属性是分开放的,data中的放的都是属性,而计算属性放在配置项computed中,其值也写成一个对象的形式。同时computed中的属性其对应的值也要配置成一个对象,其中有getter和setter(setter并不是必须的,如果你确定这个属性只会被读取不会被修改那么可以不配置setter)。
getter的调用时机:
其他时间都是使用的缓存
我们在写setter的时候,一般都是对其依赖项进行修改。千万不要对计算属性本身又进行修改,否则又会调用setter从而造成无限递归。
计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。
watch:{
isHot:{
immediate:true, //初始化时让handler调用一下 默认false
deep:true,//深度监视 默认false
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
/* 简写 当你监视属性的配置项中只有handler的时候才可以使用
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
}
watch里面的被监视属性同样也要写成一个配置对象。其中:
不论是已有的属性还是计算属性都可以被监视
v-if与template的组合使用
想将v-if作用在多个标签上,并且不破坏结构的时候使用。
注意:
<ul>
<li v-for="(person,index) in persons" :key="person.id">
{{person.name}} -- {{person.age}} -- {{index}}
</li>
</ul>
diff具体比较过程可以参考Vue核心⑧(列表渲染)
前面我们已经见过:
我们再补充几个:
v-text
作用:向其所在的节点中渲染文本内容。
与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。(所以说插值语法更加的灵活)
<div v-text="str">123</div> //实际显示出来是str的内容
v-html
v-cloak
<div id="root">
<h2 v-cloak>{{name}}h2>
div>
v-once
v-pre
<div id="root">
<h2 v-pre>Vue其实很简单h2>
<h2 >当前的n值是:{{n}}h2>
<button @click="n++">点我n+1button>
div>
一张图就可以搞定:
Vue中使用组件的三大步骤:
一、定义组件(创建组件)
二、注册组件
三、使用组件(写组件标签)
一、如何定义一个组件?
使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别;
区别如下:
1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。
2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。
备注:使用template可以配置组件结构。
二、如何注册组件?
1.局部注册(哪里注册哪里用):靠new Vue的时候传入components选项
2.全局注册(一处注册到处用):靠Vue.component('组件名',组件)
三、编写组件标签:
<school></school>
组件的命名方式,推荐首字母大写
举个例子:
<body>
<div id="root">
<h2>欢迎来到{{msg}}</h2>
<hr>
<!-- 使用组件 -->
<school></school>
<hr>
<student></student>
</div>
</body>
<script>
//创建school组件
const school = Vue.extend({
template:`
学校名称:{{schoolName}}
学校地址:{{schoolAddress}}
`,
data(){
return {
schoolName:'NEFU',
schoolAddress:'哈尔滨',
}
}
})
//创建student组件
const student = Vue.extend({
template:`
学生名称:{{studentName}}
学生年纪:{{studentAge}}
`,
data(){
return {
studentName:'张三',
studentAge:'18'
}
}
})
new Vue({
el:'#root',
//注册组件
components:{
school:school,
student:student
},
data:{
msg:'CSDN'
}
})
</script>
<body>
<div id="root"></div>
</body>
<script>
//创建student组件
const student = Vue.extend({
template:`
学生名称:{{studentName}}
学生年纪:{{studentAge}}
`,
data(){
return {
studentName:'张三',
studentAge:18
}
}
})
//创建school组件
const school = Vue.extend({
name:'NEFU',
template:`
学校名称:{{schoolName}}
学校地址:{{schoolAddress}}
`,
data(){
return {
schoolName:'NEFU',
schoolAddress:'哈尔滨',
}
},
components:{
student:student
}
})
//创建hello组件
const hello = Vue.extend({
template:`
欢迎来到{{msg}}
`,
data(){
return {
msg:'CSDN'
}
}
})
//创建app组件
const app = Vue.extend({
components:{
hello,
school
},
template:`
`
})
new Vue({
el:'#root',
//注册组件
components:{
app
},
template:'
<app></app>
'
})
</script>
我们在开发中会定义这么一种组件,这个组件的名字叫app,这个组件的作用是管理应用里面所有的组件。也就是说vm只需要管理app这么一个组件。可以说app组件是一人之下万人之上。
组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
前面我们的代码中有多个组件,我们可以使用ES6的模块化将其改造成单文件组件。这也就意味着我们需要把一个个的组件写成.vue文件。我们知道组件由三个部分组成,部分html代码、css、js。在vue文件中为我们提供了三种标签,去完成每部分的内容。
比如:
<template>
<div>
<h2 class="stu">学生名称:{{studentName}}</h2>
<h2>学生年纪:{{studentAge}}</h2>
</div>
</template>
<script>
export default {
name:'Student',
data(){
return {
studentName:'张三',
studentAge:18
}
}
}
</script>
<style>
.stu{
background-color:red;
}
</style>
为什么这里可以不使用Vue.extend方法?
在组件化的范围内,还有两个重要的属性ref、props
ref
Vue 中,ref 是一个特殊的属性,用于获取组件实例或 DOM 元素的引用。ref 的作用有以下几点:
ref 的使用方法如下:
<template>
<div>
<input ref="input" type="text" />
<button @click="focusInput">聚焦button>
div>
template>
<script>
export default {
methods: {
focusInput() {
// 获取 DOM 元素
this.$refs.input.focus();
},
},
};
script>
<template>
<div>
<child ref="child">child>
<button @click="showChildName">显示子组件的名字button>
div>
template>
<script>
import Child from "./Child.vue";
export default {
components: {
Child,
},
methods: {
showChildName() {
// 获取组件实例
alert(this.$refs.child.name);
},
},
};
script>
Vue脚手架又称Vue CLI
官方网址https://cli.vuejs.org/zh/
第一步(仅第一次执行):全局安装@vue/cli。
npm install -g @vue/cli
第二步:切换到你要创建项目的目录,然后使用命令创建项目
vue create xxxx
xxxx处编辑你的项目名称
第三步:启动项目
npm run serve
项目结构:
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
我们使用的Vue包含两个部分
Vue 的运行时版本没有模板解析器,这意味着它不能在浏览器中直接编译模板,而需要通过构建工具预先编译模板为 JavaScript 代码。这会造成以下影响:
其中模板解析器这一部分大概占了总文件的三分之一。当我们把代码写完之后,使用webpack进行打包,那么模板解析器这一部分的代码就显得有些多余
render函数由Vue帮我们调用,render函数接收一个函数作为形参,这个函数在官方文档中叫做createElement,我们可以借助这个函数去渲染具体的内容,creatElement函数有两种传参方式: