<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> {{ message }} </div> </body> <script> var app = new Vue({ el: "#app", data: { message: "hello yangtuo" } }) </script> </html>
id 作为 el 的绑定标识, 从而让 vue 对标签进行识别,
让 data 里面的数据可以在对应的标签里面的模板展示出来
data 里面的数据属性可以直接进行使用
此处的绑定为双向绑定, 在控制台进行修改后页面上也会实时更新
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app" v-bind:title="message"> 让我看看悬浮 </div> </body> <script> var app = new Vue({ el: "#app", data: { message: "看吧看吧" } }) </script> </html>
悬浮没法截图, 意思就是这样
v-bind 可以在标签元素的属性中进行传递, 同样是双向绑定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <p v-if="message">我出来了</p> <p v-else>我不见了</p> <p v-if="mess === ‘A‘">A</p> <p v-else-if="mess === ‘B‘">B</p> <p v-else>Other</p> </div> </body> <script> var app = new Vue({ el: "#app", data: { message: true, mess: "A" } }) </script> </html>
v-if / v-elseif / v-else 类似 python 中的 if / eilf / else
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <li v-for="item in items"> {{item.message}} </li> </div> </body> <script> var app = new Vue({ el: "#app", data: { items: [ {message: "爬啊爬"}, {message: "滚啊滚"}, {message: "游啊游"} ] } }) </script> </html>
v-for 循环控制 x in xs , xs 为 vue 的绑定值, x 为形参
同样具备双向绑定影响
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <button v-on:click="greet">点我</button> </div> </body> <script> var app = new Vue({ el: "#app", // 在 methods 中定义方法 data:{ message: "yang" }, methods: { // 通过 this 可以拿到 data 里面的值 greet: function () { alert("hello yangtuo " + this.message) } } }) </script> </html>
v-on 进行绑定事件处理, 事件处理的函数需要在 methods 对象里面进行定义方法
methods 里面拿 data 里面的值得时候通过 this 即可拿到
相同路径下准备一个文件 data.json
{
"name": "test",
"version": "0.1.0",
"private": true,
"url": "www.test.com"
}
demo 文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <p>名字: {{info.name}} </p> <p>url: {{info.url}} </p> </div> </body> <script> var app = new Vue({ el: "#app", data() { return {info: {name: "", url: ""}} }, mounted() { axios.get(‘data.json‘).then(response => this.info = response.data) } }) </script> </html>
vue 中采用 Axios 进行异步通信, 同时在 vue 的生命周期中
存在一个 mounted 的钩子函数可以进行重写从而便于进行一系列操作
axios 拿到的数据放入提前在 data 里面声明的变量里面
从而再从标签中使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <input type="text" v-model="message" value="不生效的初始值"> // value 会无法显示 <p>输入: {{message}}</p> </div> </body> <script> var app = new Vue({ el: "#app", data: { message: "初始值的说" } }) </script> </html>
输入框中输入什么, 下面的 p 标签就展示什么进行同步更新
v-model 作为 vue 的语法糖对输入表单进行双向绑定, 从而实现实时联动展示数据
但是注意:
1. v-model 会让标签内本身定义的 value , checked , selected 等默认值属性失效
2. v-model 对下拉框的展示在 ios 中会有 bug 导致第一个选择会无法被选择
2.1 处理方法: 在下拉框中的第一个位置展示一个值为空的禁用选项, 比如置灰的 "请选择"
此 demo 为 js 的形式来实现组件, 开发中并不会使用此种方式
目前仅作为便于理解进行简单展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <ul> <my-component-li></my-component-li> </ul> </div> </body> <script> Vue.component("my-component-li", { template:"<li>hello cibo</li>>" }) var app = new Vue({ el: "#app" }) </script> </html>
组件可以理解为 vue 中可以重复使用的一组模板
可以通过 Vue.component 进行定义 ("名字", { template: "内容" })
然后 名字的 标签使用的地方就可以进行复用, 通常不会使用此方法
而且 li 一般用于循环, 这里改动一下代码
这里红色的 items 是通过 v-for 直接在 data 里面就可以拿到的
绿色的 item 是在组件里面 props 里面定义拿到的
红色和绿色彼此是互不干涉的, 因此需要 v-bind 进行绑定 (蓝色部分)
v-bind 前面穿的值是当前组件的一个属性, 这个属性在 组件的 porps中进行了定义
v-bind 后面穿得值是属性的赋值, 这里用了 v-for 循环的形参
结果展示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <p>当前时间方法: {{getCurrentTime()}}</p> <p>当前时间属性: {{getCurrentTime1}}</p> </div> </body> <script> var app = new Vue({ el: "#app", methods: { getCurrentTime: function () { return Date.now(); } }, computed: { getCurrentTime1: function () { return Date.now(); } } }) </script> </html>
可以看到计算属性出来的数据是不会发生变化的
而方法计算的数据是每次使用都重新计算的
通过 computed 进行定义, 然后计算函数放入, 将计算函数的结果缓存
避免下次使用此值得时候再次进行计算, 从而避免了额外的开销
本质上是将一个动态的运行结果转化为一个静态的属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <todo> <todo-title slot="todo-title" v-bind:title=‘title‘></todo-title> <todo-context slot="todo-context" v-for=‘context in contexts‘ v-bind:context=‘context‘></todo-context> </todo> </div> </body> <script> Vue.component("todo", { template: "<div>" + "<slot name=‘todo-title‘></slot>" + "<ul>" + "<slot name=‘todo-context‘></slot>" + "</ul>" + "</div>" }) Vue.component("todo-title", { props: ["title"], template: "<div>{{title}}</div>" }) Vue.component("todo-context", { props: ["context"], template: "<li>{{context}}</li>" }) var app = new Vue({ el: "#app", data: { title: "标题", contexts: ["a", "b", "c"] } }) </script> </html>
插槽是作为组件放入的位置进行定义的
大组件里面经常会放入小组件, 小组件在大组件的摆放的预留位置则是插槽
本次示例中大组件 todo 里面有 两个小组件 todo-title 和 todo-context
使用 solt 在大组价中预留位置
组件的传值依旧是定义 props 里面属性, 然后使用的地方 bind 绑定外部的 数据进行映射
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test_vue</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <todo> <todo-title slot="todo-title" :title=‘title‘></todo-title> <todo-context slot="todo-context" v-for=‘(context, index) in contexts‘ :context=‘context‘ // v-bind: 的简写 :index=‘index‘ v-on:remove="removeContexts"></todo-context> </todo> </div> </body> <script> Vue.component("todo", { template: "<div>" + "<slot name=‘todo-title‘></slot>" + "<ul>" + "<slot name=‘todo-context‘></slot>" + "</ul>" + "</div>" }) Vue.component("todo-title", { props: ["title"], template: "<div>{{title}}</div>" }) Vue.component("todo-context", { props: ["context", "index"], template: "<li>{{index}} --> {{context}} <button v-on:click=‘remove‘>删除</button></li>", methods: { remove: function () { this.$emit("remove"); } } }) var app = new Vue({ el: "#app", data: { title: "标题", contexts: ["a", "b", "c"] }, methods: { removeContexts: function (index) { this.contexts.splice(index, 1); alert(123) } } }) </script> </html>
点击删除按钮后会将此行删除掉
基于上一个示例, 在每行后面加一个删除按钮, 点击后删除本行
首先确认三个事实:
1. 每一行都是根据数据for出来的, 因为数据绑定, 删数据即可实现删行
1. 组件定义的地方里面是没有数据的, 数据是组件被渲染的时候外部穿进去展示的
2. 标签里面是没法调用到组件内的方法的, 标签本质是最外部最终展示的结果
基于这两个因素
1. 组件里面直接删除数据不可行
2. 组件里面定义删除方法, 外面调不到也不行
但是
1. 数据是在外面 data 里面定义的. 因此在外面就可以删掉
2. 通过组件内自定义方法 $emit("方法名") 指定后即可在标签内调用外部的方法
2.1 v-on:remve(自定义方法名):removeContext(外部方法名)
2.2 因为这里的 v-on 和 v-for 和组件 都是基于 Vue 内部, 可以省略参数的传递
最终的流程图
外部定义删除方法删除数据, 组件自定义方法, 标签内通过 v-on 将两方法链接
参数的传递标签内和组件内可以省略, 参数要和外部绑定起来让外部的函数能拿到
但是外部的方法必须该有的不能少 (毕竟这里是真正的计算逻辑少了参数怎么行)
原文:https://www.cnblogs.com/shijieli/p/14851323.html