<!--
计算属性 computed
https://www.runoob.com/vue2/vue-computed.html
-->
<div id="app">
<p>原始字符串: {{ message }}</p>
<!-- 获取计算后的属性(用于复杂逻辑) -->
<p>computed计算后反转字符串: {{ reversedMessage1 }}</p>
<!-- 我们可以使用 methods 来替代 computed,效果上两个都是一样的,
但是 computed 是基于它的依赖缓存,只有相关依赖发生改变时才会重新取值。
而使用 methods ,在重新渲染的时候,函数总会重新调用执行 -->
<p>methods计算后反转字符串: {{ reversedMessage2() }}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
name: 'Google',
message: 'Runoob!'
},
methods: {
reversedMessage2: function () {
return this.message.split('').reverse().join('')
}
},
computed: {
// 计算属性的 getter
reversedMessage1: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
},
site : {
get:function(){//默认只有 getter
return this.name + ':' + this.message ;
}
set:function(newValue){// 手动提供一个 setter
var vals = newValue.split(' ');
this.name = vals[0]
this.message = vals[ vals.length - 1]
}
}
}
})
</script>
<!--
监听属性watch
https://www.runoob.com/vue2/vue-watch.html
-->
<div id = "computed_props"><!-- 千米与米之间的换算示例 -->
千米 : <input type = "text" v-model = "kilometers">
米 : <input type = "text" v-model = "meters">
</div>
<p id="info"></p>
<script type = "text/javascript">
var vm = new Vue({
el: '#computed_props',
data: {
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;
}
}
});
// $watch 是一个实例方法
vm.$watch('kilometers', function (newValue, oldValue) {
// 这个回调将在 vm.kilometers 改变后调用
document.getElementById ("info").innerHTML = "修改前值为: " + oldValue + ",修改后值为: " + newValue;
})
</script>
<!----------------------------------------------------->
<!--
表单
表单双向绑定
-->
<div id="app">
<!-- 文本框 -->
<p>input 元素:</p>
<input v-model="message" placeholder="编辑我……">
<p>消息是: {{ message }}</p>
<p>textarea 元素:</p>
<p style="white-space: pre">{{ message2 }}</p>
<textarea v-model="message2" placeholder="多行文本输入……"></textarea>
<hr>
<!-- 单选框与复选框 -->
<p>单个复选框:</p>
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
<p>多个复选框:</p>
<input type="checkbox" id="runoob" value="Runoob" v-model="checkedNames">
<label for="runoob">Runoob</label>
<input type="checkbox" id="google" value="Google" v-model="checkedNames">
<label for="google">Google</label>
<input type="checkbox" id="taobao" value="Taobao" v-model="checkedNames">
<label for="taobao">taobao</label>
<br>
<span>选择的值为: {{ checkedNames }}</span>
</div>
<hr>
<!-- select下拉框 -->
<select v-model="selected" name="fruit">
<option value="">选择一个网站</option>
<option value="www.runoob.com">Runoob</option>
<option value="www.google.com">Google</option>
</select>
<div id="output">
选择的网站是: {{selected}}
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Runoob',
message2: '菜鸟教程\r\nhttp://www.runoob.com' ,
checked : false,
checkedNames: [],
selected : ''
}
})
</script>
<!-- 关于表单修饰符
TODO 待详细了解
-->
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
<!-- 自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值) -->
<input v-model.number="age" type="number">
<!-- 过滤用户输入的首尾空格 -->
<input v-model.trim="msg">
<!----------------------------------------------------->
<!--
组件
element ui中使用了大量el开头的标签 , 可能是通过此种方法实现
-->
<div id="app">
<runoob></runoob>
<child message="hello!"></child>
</div>
<script>
//导入全局组件
import Editor from "@/components/Editor" // 富文本组件
Vue.component('Editor', Editor);
// 注册
Vue.component('child', {
// 声明 props , 用来声明参数名称
props: ['message'],//prop 是子组件用来接受父组件传递过来的数据的一个自定义属性
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
});
var Child = {//即将应用于实例的组件
template: '<h1>自定义组件!</h1>'
}
new Vue({// 创建根实例
el: '#app',
components: {
// <runoob> 将只在父模板可用
'runoob': Child
}
});
</script>
<!--
组件 : 动态 Prop 和 Prop 验证
参考 : https://www.runoob.com/try/try.php?filename=vue2-component4
https://www.runoob.com/try/try.php?filename=vue2-component5
-->
<div id="app">
<div>
<input v-model="parentMsg">
<br>
<!-- child 是一个自定义的组件标签,上面文本框中的值将动态传入到child组件中 -->
<child v-bind:message="parentMsg"></child>
</div>
<ol>
<todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
</ol>
</div>
<script>
// 注册
Vue.component('child', {
// 声明 props
props: ['message'],
// 同样也可以在 vm 实例中像 "this.message" 这样使用
template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
el: '#app',
data: {
parentMsg: '父组件内容' ,
sites: [
{ text: 'Runoob' },
{ text: 'Google' },
{ text: 'Taobao' }
]
}
});
<!-- Prop 验证
传值类型包含以下 : String,Number,Boolean,Array,Object,Date,Function,Symbol 也可以使用validator自定义验证参数
-->
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String, //type 也可以是一个自定义构造器,使用 instanceof 检测
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
}
}
}
})
</script>
<!----------------------------------------------------->
<!--
组件自定义事件
(子组件要把数据传递回去,需要使用自定义事件)
使用 $on(eventName) 监听事件 (另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件)
使用 $emit(eventName) 触发事件
https://www.runoob.com/vue2/vue-component-custom-event.html
-->
<div id="app">
<div id="counter-event-example">
<p>{{ total }}</p>
<!-- this.$emit('increment') 触发父组件的事件 -->
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</div>
<script>
//看起来 Vue.component 的结构有点类似 , 有data ,有methods (待了解组件参数)
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {//这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1 ;//this.counter 两个button-counter组件,每个组件的counter都是独立的
this.$emit('increment') ;//触发increment对应的父组件事件
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
</script>
<!-- native修饰符用来监听原生事件-->
<my-component v-on:click.native="doTheThing"></my-component>
<!--
自定义组件的 v-model
https://www.runoob.com/try/try.php?filename=vue2-component8
<input v-model="parentData">
等价于
<input :value="parentData" @input="parentData = $event.target.value">
v-bind: 缩写 : v-on:click缩写@
-->
<div id="app">
<runoob-input v-model="num"></runoob-input>
<p>输入的数字为:{{num}}</p>
</div>
<script>
Vue.component('runoob-input', {
template: `
<p> <!-- 包含了名为 input 的事件 -->
<input
ref="input"
:value="value"
@input="$emit('input', $event.target.value)"
>
</p>
`,
props: ['value'], // 名为 value 的 prop
})
new Vue({
el: '#app',
data: {
num: 100,
}
})
</script>